2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/tokentype.h"
17 #include "mono/metadata/domain-internals.h"
18 #include "mono/metadata/opcodes.h"
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/object-internals.h"
21 #include <mono/metadata/exception.h>
30 #include "rawbuffer.h"
31 #include "mono-endian.h"
33 #include <mono/os/gc_wrapper.h>
35 #define TEXT_OFFSET 512
36 #define CLI_H_SIZE 136
37 #define FILE_ALIGN 512
38 #define VIRT_ALIGN 8192
39 #define START_TEXT_RVA 0x00002000
42 MonoReflectionILGen *ilgen;
43 MonoReflectionType *rtype;
44 MonoArray *parameters;
45 MonoArray *generic_params;
46 MonoGenericContainer *generic_container;
52 guint32 *table_idx; /* note: it's a pointer */
56 MonoBoolean init_locals;
57 MonoArray *return_modreq;
58 MonoArray *return_modopt;
59 MonoArray *param_modreq;
60 MonoArray *param_modopt;
61 MonoArray *permissions;
66 int charset, lasterr, native_cc;
67 MonoString *dll, *dllentry;
68 } ReflectionMethodBuilder;
72 MonoReflectionGenericParam *gparam;
73 } GenericParamTableEntry;
75 const unsigned char table_sizes [64] = {
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,
126 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
127 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
128 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
129 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
130 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
131 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
132 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
133 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
134 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
135 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
136 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
137 static void ensure_runtime_vtable (MonoClass *klass);
138 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
139 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
140 static guint32 type_get_signature_size (MonoType *type);
141 static void get_default_param_value_blobs (MonoMethod *method, char **blobs);
142 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
146 alloc_table (MonoDynamicTable *table, guint nrows)
149 g_assert (table->columns);
150 if (nrows + 1 >= table->alloc_rows) {
151 while (nrows + 1 >= table->alloc_rows) {
152 if (table->alloc_rows == 0)
153 table->alloc_rows = 16;
155 table->alloc_rows *= 2;
158 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
163 make_room_in_stream (MonoDynamicStream *stream, int size)
165 if (size <= stream->alloc_size)
168 while (stream->alloc_size <= size) {
169 if (stream->alloc_size < 4096)
170 stream->alloc_size = 4096;
172 stream->alloc_size *= 2;
175 stream->data = g_realloc (stream->data, stream->alloc_size);
179 mono_dynamic_stream_reset (MonoDynamicStream* stream)
181 stream->alloc_size = stream->index = stream->offset = 0;
182 g_free (stream->data);
184 g_hash_table_destroy (stream->hash);
188 string_heap_insert (MonoDynamicStream *sh, const char *str)
192 gpointer oldkey, oldval;
194 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
195 return GPOINTER_TO_UINT (oldval);
197 len = strlen (str) + 1;
200 make_room_in_stream (sh, idx + len);
203 * We strdup the string even if we already copy them in sh->data
204 * so that the string pointers in the hash remain valid even if
205 * we need to realloc sh->data. We may want to avoid that later.
207 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
208 memcpy (sh->data + idx, str, len);
214 string_heap_init (MonoDynamicStream *sh)
217 sh->alloc_size = 4096;
218 sh->data = g_malloc (4096);
219 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
220 string_heap_insert (sh, "");
224 string_heap_free (MonoDynamicStream *sh)
227 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
228 g_hash_table_destroy (sh->hash);
232 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
236 make_room_in_stream (stream, stream->index + len);
237 memcpy (stream->data + stream->index, data, len);
239 stream->index += len;
241 * align index? Not without adding an additional param that controls it since
242 * we may store a blob value in pieces.
248 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
252 make_room_in_stream (stream, stream->index + len);
253 memset (stream->data + stream->index, 0, len);
255 stream->index += len;
260 stream_data_align (MonoDynamicStream *stream)
263 guint32 count = stream->index % 4;
265 /* we assume the stream data will be aligned */
267 mono_image_add_stream_data (stream, buf, 4 - count);
271 mono_blob_entry_hash (const char* str)
275 len = mono_metadata_decode_blob_size (str, &str);
279 for (str += 1; str < end; str++)
280 h = (h << 5) - h + *str;
288 mono_blob_entry_equal (const char *str1, const char *str2) {
292 len = mono_metadata_decode_blob_size (str1, &end1);
293 len2 = mono_metadata_decode_blob_size (str2, &end2);
296 return memcmp (end1, end2, len) == 0;
300 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
304 gpointer oldkey, oldval;
306 copy = g_malloc (s1+s2);
307 memcpy (copy, b1, s1);
308 memcpy (copy + s1, b2, s2);
309 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
311 idx = GPOINTER_TO_UINT (oldval);
313 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
314 mono_image_add_stream_data (&assembly->blob, b2, s2);
315 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
321 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
322 * dest may be misaligned.
325 swap_with_size (char *dest, const char* val, int len, int nelem) {
326 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
329 for (elem = 0; elem < nelem; ++elem) {
355 g_assert_not_reached ();
361 memcpy (dest, val, len * nelem);
366 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
370 guint32 idx = 0, len;
372 len = str->length * 2;
373 mono_metadata_encode_value (len, b, &b);
374 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
376 char *swapped = g_malloc (2 * mono_string_length (str));
377 const char *p = (const char*)mono_string_chars (str);
379 swap_with_size (swapped, p, 2, mono_string_length (str));
380 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
384 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
389 /* modified version needed to handle building corlib */
391 my_mono_class_from_mono_type (MonoType *type) {
392 switch (type->type) {
393 case MONO_TYPE_ARRAY:
395 case MONO_TYPE_SZARRAY:
396 case MONO_TYPE_GENERICINST:
397 return mono_class_from_mono_type (type);
400 g_assert (type->data.generic_param->pklass);
401 return type->data.generic_param->pklass;
403 /* should be always valid when we reach this case... */
404 return type->data.klass;
409 default_class_from_mono_type (MonoType *type)
411 switch (type->type) {
412 case MONO_TYPE_OBJECT:
413 return mono_defaults.object_class;
415 return mono_defaults.void_class;
416 case MONO_TYPE_BOOLEAN:
417 return mono_defaults.boolean_class;
419 return mono_defaults.char_class;
421 return mono_defaults.sbyte_class;
423 return mono_defaults.byte_class;
425 return mono_defaults.int16_class;
427 return mono_defaults.uint16_class;
429 return mono_defaults.int32_class;
431 return mono_defaults.uint32_class;
433 return mono_defaults.int_class;
435 return mono_defaults.uint_class;
437 return mono_defaults.int64_class;
439 return mono_defaults.uint64_class;
441 return mono_defaults.single_class;
443 return mono_defaults.double_class;
444 case MONO_TYPE_STRING:
445 return mono_defaults.string_class;
447 g_warning ("implement me 0x%02x\n", type->type);
448 g_assert_not_reached ();
455 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char *p, char **endbuf)
460 g_assert_not_reached ();
464 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
465 encode_type (assembly, &gclass->container_class->byval_arg, p, &p);
466 mono_metadata_encode_value (gclass->inst->type_argc, p, &p);
467 for (i = 0; i < gclass->inst->type_argc; ++i)
468 encode_type (assembly, gclass->inst->type_argv [i], p, &p);
474 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
477 g_assert_not_reached ();
482 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
486 case MONO_TYPE_BOOLEAN:
500 case MONO_TYPE_STRING:
501 case MONO_TYPE_OBJECT:
502 case MONO_TYPE_TYPEDBYREF:
503 mono_metadata_encode_value (type->type, p, &p);
506 mono_metadata_encode_value (type->type, p, &p);
507 encode_type (assembly, type->data.type, p, &p);
509 case MONO_TYPE_SZARRAY:
510 mono_metadata_encode_value (type->type, p, &p);
511 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
513 case MONO_TYPE_VALUETYPE:
514 case MONO_TYPE_CLASS: {
515 MonoClass *k = mono_class_from_mono_type (type);
516 mono_metadata_encode_value (type->type, p, &p);
518 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
519 * otherwise two typerefs could point to the same type, leading to
520 * verification errors.
522 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
525 case MONO_TYPE_ARRAY:
526 mono_metadata_encode_value (type->type, p, &p);
527 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
528 mono_metadata_encode_value (type->data.array->rank, p, &p);
529 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
530 mono_metadata_encode_value (0, p, &p);
532 case MONO_TYPE_GENERICINST:
533 encode_generic_class (assembly, type->data.generic_class, p, &p);
537 mono_metadata_encode_value (type->type, p, &p);
538 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
541 g_error ("need to encode type %x", type->type);
547 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
550 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
554 encode_type (assembly, type->type, p, endbuf);
558 g_assert_not_reached ();
563 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
568 for (i = 0; i < mono_array_length (modreq); ++i) {
569 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
570 *p = MONO_TYPE_CMOD_REQD;
572 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
576 for (i = 0; i < mono_array_length (modopt); ++i) {
577 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
578 *p = MONO_TYPE_CMOD_OPT;
580 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
587 generic_class_get_signature_size (MonoGenericClass *gclass)
593 g_assert_not_reached ();
596 size += 1 + type_get_signature_size (&gclass->container_class->byval_arg);
598 for (i = 0; i < gclass->inst->type_argc; ++i)
599 size += type_get_signature_size (gclass->inst->type_argv [i]);
605 type_get_signature_size (MonoType *type)
610 g_assert_not_reached ();
618 case MONO_TYPE_BOOLEAN:
632 case MONO_TYPE_STRING:
633 case MONO_TYPE_OBJECT:
634 case MONO_TYPE_TYPEDBYREF:
637 return size + 1 + type_get_signature_size (type->data.type);
638 case MONO_TYPE_SZARRAY:
639 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
640 case MONO_TYPE_VALUETYPE:
641 case MONO_TYPE_CLASS:
643 case MONO_TYPE_ARRAY:
644 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
645 case MONO_TYPE_GENERICINST:
646 return size + generic_class_get_signature_size (type->data.generic_class);
651 g_error ("need to encode type %x", type->type);
657 method_get_signature_size (MonoMethodSignature *sig)
662 size = type_get_signature_size (sig->ret);
663 for (i = 0; i < sig->param_count; i++)
664 size += type_get_signature_size (sig->params [i]);
666 if (sig->generic_param_count)
668 if (sig->sentinelpos >= 0)
675 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
680 guint32 nparams = sig->param_count;
681 guint32 size = 11 + method_get_signature_size (sig);
689 p = buf = g_malloc (size);
691 * FIXME: vararg, explicit_this, differenc call_conv values...
693 *p = sig->call_convention;
695 *p |= 0x20; /* hasthis */
696 if (sig->generic_param_count)
697 *p |= 0x10; /* generic */
699 if (sig->generic_param_count)
700 mono_metadata_encode_value (sig->generic_param_count, p, &p);
701 mono_metadata_encode_value (nparams, p, &p);
702 encode_type (assembly, sig->ret, p, &p);
703 for (i = 0; i < nparams; ++i) {
704 if (i == sig->sentinelpos)
705 *p++ = MONO_TYPE_SENTINEL;
706 encode_type (assembly, sig->params [i], p, &p);
709 g_assert (p - buf < size);
710 mono_metadata_encode_value (p-buf, b, &b);
711 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
717 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
720 * FIXME: reuse code from method_encode_signature().
725 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
726 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
727 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
728 guint32 size = 21 + nparams * 20 + notypes * 20;
733 p = buf = g_malloc (size);
734 /* LAMESPEC: all the call conv spec is foobared */
735 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
736 if (mb->call_conv & 2)
737 *p |= 0x5; /* vararg */
738 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
739 *p |= 0x20; /* hasthis */
741 *p |= 0x10; /* generic */
744 mono_metadata_encode_value (ngparams, p, &p);
745 mono_metadata_encode_value (nparams + notypes, p, &p);
746 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
747 encode_reflection_type (assembly, mb->rtype, p, &p);
748 for (i = 0; i < nparams; ++i) {
749 MonoArray *modreq = NULL;
750 MonoArray *modopt = NULL;
751 MonoReflectionType *pt;
753 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
754 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
755 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
756 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
757 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
758 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
759 encode_reflection_type (assembly, pt, p, &p);
762 *p++ = MONO_TYPE_SENTINEL;
763 for (i = 0; i < notypes; ++i) {
764 MonoReflectionType *pt;
766 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
767 encode_reflection_type (assembly, pt, p, &p);
771 g_assert (p - buf < size);
772 mono_metadata_encode_value (p-buf, b, &b);
773 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
779 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
781 MonoDynamicTable *table;
784 guint32 idx, sig_idx, size;
785 guint nl = mono_array_length (ilgen->locals);
792 p = buf = g_malloc (size);
793 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
794 idx = table->next_idx ++;
796 alloc_table (table, table->rows);
797 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
799 mono_metadata_encode_value (0x07, p, &p);
800 mono_metadata_encode_value (nl, p, &p);
801 for (i = 0; i < nl; ++i) {
802 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
805 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
807 encode_reflection_type (assembly, lb->type, p, &p);
809 g_assert (p - buf < size);
810 mono_metadata_encode_value (p-buf, b, &b);
811 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
814 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
820 method_count_clauses (MonoReflectionILGen *ilgen)
822 guint32 num_clauses = 0;
825 MonoILExceptionInfo *ex_info;
826 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
827 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
828 if (ex_info->handlers)
829 num_clauses += mono_array_length (ex_info->handlers);
837 static MonoExceptionClause*
838 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
840 MonoExceptionClause *clauses;
841 MonoExceptionClause *clause;
842 MonoILExceptionInfo *ex_info;
843 MonoILExceptionBlock *ex_block;
844 guint32 finally_start;
845 int i, j, clause_index;;
847 clauses = g_new0 (MonoExceptionClause, num_clauses);
850 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
851 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
852 finally_start = ex_info->start + ex_info->len;
853 g_assert (ex_info->handlers);
854 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
855 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
856 clause = &(clauses [clause_index]);
858 clause->flags = ex_block->type;
859 clause->try_offset = ex_info->start;
861 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
862 clause->try_len = finally_start - ex_info->start;
864 clause->try_len = ex_info->len;
865 clause->handler_offset = ex_block->start;
866 clause->handler_len = ex_block->len;
867 if (ex_block->extype) {
868 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
870 /* FIXME: handle filters */
871 clause->data.filter_offset = 0;
873 finally_start = ex_block->start + ex_block->len;
883 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
889 gint32 num_locals = 0;
890 gint32 num_exception = 0;
893 char fat_header [12];
896 guint32 local_sig = 0;
897 guint32 header_size = 12;
900 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
901 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
905 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
907 code = mb->ilgen->code;
908 code_size = mb->ilgen->code_len;
909 max_stack = mb->ilgen->max_stack;
910 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
911 if (mb->ilgen->ex_handlers)
912 num_exception = method_count_clauses (mb->ilgen);
916 char *name = mono_string_to_utf8 (mb->name);
917 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
918 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
921 mono_raise_exception (exception);
924 code_size = mono_array_length (code);
925 max_stack = 8; /* we probably need to run a verifier on the code... */
928 stream_data_align (&assembly->code);
930 /* check for exceptions, maxstack, locals */
931 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
933 if (code_size < 64 && !(code_size & 1)) {
934 flags = (code_size << 2) | 0x2;
935 } else if (code_size < 32 && (code_size & 1)) {
936 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
940 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
941 /* add to the fixup todo list */
942 if (mb->ilgen && mb->ilgen->num_token_fixups)
943 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
944 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
945 return assembly->text_rva + idx;
949 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
951 * FIXME: need to set also the header size in fat_flags.
952 * (and more sects and init locals flags)
956 fat_flags |= METHOD_HEADER_MORE_SECTS;
958 fat_flags |= METHOD_HEADER_INIT_LOCALS;
959 fat_header [0] = fat_flags;
960 fat_header [1] = (header_size / 4 ) << 4;
961 shortp = (guint16*)(fat_header + 2);
962 *shortp = GUINT16_TO_LE (max_stack);
963 intp = (guint32*)(fat_header + 4);
964 *intp = GUINT32_TO_LE (code_size);
965 intp = (guint32*)(fat_header + 8);
966 *intp = GUINT32_TO_LE (local_sig);
967 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
968 /* add to the fixup todo list */
969 if (mb->ilgen && mb->ilgen->num_token_fixups)
970 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
972 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
974 unsigned char sheader [4];
975 MonoILExceptionInfo * ex_info;
976 MonoILExceptionBlock * ex_block;
979 stream_data_align (&assembly->code);
980 /* always use fat format for now */
981 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
982 num_exception *= 6 * sizeof (guint32);
983 num_exception += 4; /* include the size of the header */
984 sheader [1] = num_exception & 0xff;
985 sheader [2] = (num_exception >> 8) & 0xff;
986 sheader [3] = (num_exception >> 16) & 0xff;
987 mono_image_add_stream_data (&assembly->code, sheader, 4);
988 /* fat header, so we are already aligned */
990 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
991 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
992 if (ex_info->handlers) {
993 int finally_start = ex_info->start + ex_info->len;
994 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
996 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
998 val = GUINT32_TO_LE (ex_block->type);
999 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1001 val = GUINT32_TO_LE (ex_info->start);
1002 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1003 /* need fault, too, probably */
1004 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1005 val = GUINT32_TO_LE (finally_start - ex_info->start);
1007 val = GUINT32_TO_LE (ex_info->len);
1008 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1009 /* handler offset */
1010 val = GUINT32_TO_LE (ex_block->start);
1011 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1013 val = GUINT32_TO_LE (ex_block->len);
1014 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1015 finally_start = ex_block->start + ex_block->len;
1016 if (ex_block->extype) {
1017 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1019 /* FIXME: handle filters */
1022 val = GUINT32_TO_LE (val);
1023 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1024 /*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",
1025 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);*/
1028 g_error ("No clauses for ex info block %d", i);
1032 return assembly->text_rva + idx;
1036 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1039 MonoDynamicTable *table;
1042 table = &assembly->tables [table_idx];
1044 g_assert (col < table->columns);
1046 values = table->values + table->columns;
1047 for (i = 1; i <= table->rows; ++i) {
1048 if (values [col] == token)
1050 values += table->columns;
1055 static GHashTable *dynamic_custom_attrs = NULL;
1057 static MonoCustomAttrInfo*
1058 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1061 MonoCustomAttrInfo *ainfo;
1062 MonoReflectionCustomAttr *cattr;
1066 /* FIXME: check in assembly the Run flag is set */
1068 count = mono_array_length (cattrs);
1070 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1072 ainfo->image = image;
1073 ainfo->num_attrs = count;
1074 for (i = 0; i < count; ++i) {
1075 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1076 ainfo->attrs [i].ctor = cattr->ctor->method;
1077 /* FIXME: might want to memdup the data here */
1078 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1079 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1086 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1088 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1093 if (!dynamic_custom_attrs)
1094 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1096 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1097 ainfo->cached = TRUE;
1101 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1103 /* they are cached, so we don't free them */
1104 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1110 * idx is the table index of the object
1111 * type is one of MONO_CUSTOM_ATTR_*
1114 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1116 MonoDynamicTable *table;
1117 MonoReflectionCustomAttr *cattr;
1119 guint32 count, i, token;
1121 char *p = blob_size;
1123 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1126 count = mono_array_length (cattrs);
1127 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1128 table->rows += count;
1129 alloc_table (table, table->rows);
1130 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1131 idx <<= MONO_CUSTOM_ATTR_BITS;
1133 for (i = 0; i < count; ++i) {
1134 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1135 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1136 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1137 type = mono_metadata_token_index (token);
1138 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1139 switch (mono_metadata_token_table (token)) {
1140 case MONO_TABLE_METHOD:
1141 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1143 case MONO_TABLE_MEMBERREF:
1144 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1147 g_warning ("got wrong token in custom attr");
1150 values [MONO_CUSTOM_ATTR_TYPE] = type;
1152 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1153 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1154 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1155 values += MONO_CUSTOM_ATTR_SIZE;
1161 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1163 MonoDynamicTable *table;
1165 guint32 count, i, idx;
1166 MonoReflectionPermissionSet *perm;
1171 count = mono_array_length (permissions);
1172 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1173 table->rows += count;
1174 alloc_table (table, table->rows);
1176 for (i = 0; i < mono_array_length (permissions); ++i) {
1177 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1179 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1181 idx = mono_metadata_token_index (parent_token);
1182 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1183 switch (mono_metadata_token_table (parent_token)) {
1184 case MONO_TABLE_TYPEDEF:
1185 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1187 case MONO_TABLE_METHOD:
1188 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1190 case MONO_TABLE_ASSEMBLY:
1191 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1194 g_assert_not_reached ();
1197 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1198 values [MONO_DECL_SECURITY_PARENT] = idx;
1199 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1206 * Fill in the MethodDef and ParamDef tables for a method.
1207 * This is used for both normal methods and constructors.
1210 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1212 MonoDynamicTable *table;
1217 /* room in this table is already allocated */
1218 table = &assembly->tables [MONO_TABLE_METHOD];
1219 *mb->table_idx = table->next_idx ++;
1220 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1221 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1222 name = mono_string_to_utf8 (mb->name);
1223 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1225 values [MONO_METHOD_FLAGS] = mb->attrs;
1226 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1227 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1228 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1230 table = &assembly->tables [MONO_TABLE_PARAM];
1231 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1233 mono_image_add_decl_security (assembly,
1234 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1237 MonoDynamicTable *mtable;
1240 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1241 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1244 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1245 if (mono_array_get (mb->pinfo, gpointer, i))
1248 table->rows += count;
1249 alloc_table (table, table->rows);
1250 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1251 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1252 MonoReflectionParamBuilder *pb;
1253 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1254 values [MONO_PARAM_FLAGS] = pb->attrs;
1255 values [MONO_PARAM_SEQUENCE] = i;
1256 if (pb->name != NULL) {
1257 name = mono_string_to_utf8 (pb->name);
1258 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1261 values [MONO_PARAM_NAME] = 0;
1263 values += MONO_PARAM_SIZE;
1264 if (pb->marshal_info) {
1266 alloc_table (mtable, mtable->rows);
1267 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1268 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1269 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1271 pb->table_idx = table->next_idx++;
1272 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1273 guint32 field_type = 0;
1274 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1276 alloc_table (mtable, mtable->rows);
1277 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1278 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1279 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1280 mvalues [MONO_CONSTANT_TYPE] = field_type;
1281 mvalues [MONO_CONSTANT_PADDING] = 0;
1289 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1291 rmb->ilgen = mb->ilgen;
1292 rmb->rtype = mb->rtype;
1293 rmb->parameters = mb->parameters;
1294 rmb->generic_params = mb->generic_params;
1295 rmb->generic_container = mb->generic_container;
1296 rmb->opt_types = NULL;
1297 rmb->pinfo = mb->pinfo;
1298 rmb->attrs = mb->attrs;
1299 rmb->iattrs = mb->iattrs;
1300 rmb->call_conv = mb->call_conv;
1301 rmb->code = mb->code;
1302 rmb->type = mb->type;
1303 rmb->name = mb->name;
1304 rmb->table_idx = &mb->table_idx;
1305 rmb->init_locals = mb->init_locals;
1306 rmb->return_modreq = mb->return_modreq;
1307 rmb->return_modopt = mb->return_modopt;
1308 rmb->param_modreq = mb->param_modreq;
1309 rmb->param_modopt = mb->param_modopt;
1310 rmb->permissions = mb->permissions;
1311 rmb->mhandle = mb->mhandle;
1316 rmb->charset = mb->charset & 0xf;
1317 rmb->lasterr = mb->charset & 0x40;
1318 rmb->native_cc = mb->native_cc;
1319 rmb->dllentry = mb->dllentry;
1325 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1327 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1329 rmb->ilgen = mb->ilgen;
1330 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1331 rmb->parameters = mb->parameters;
1332 rmb->generic_params = NULL;
1333 rmb->generic_container = NULL;
1334 rmb->opt_types = NULL;
1335 rmb->pinfo = mb->pinfo;
1336 rmb->attrs = mb->attrs;
1337 rmb->iattrs = mb->iattrs;
1338 rmb->call_conv = mb->call_conv;
1340 rmb->type = mb->type;
1341 rmb->name = mono_string_new (mono_domain_get (), name);
1342 rmb->table_idx = &mb->table_idx;
1343 rmb->init_locals = mb->init_locals;
1344 rmb->return_modreq = NULL;
1345 rmb->return_modopt = NULL;
1346 rmb->param_modreq = mb->param_modreq;
1347 rmb->param_modopt = mb->param_modopt;
1348 rmb->permissions = mb->permissions;
1349 rmb->mhandle = mb->mhandle;
1355 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1357 rmb->ilgen = mb->ilgen;
1358 rmb->rtype = mb->rtype;
1359 rmb->parameters = mb->parameters;
1360 rmb->generic_params = NULL;
1361 rmb->generic_container = NULL;
1362 rmb->opt_types = NULL;
1364 rmb->attrs = mb->attrs;
1366 rmb->call_conv = mb->call_conv;
1369 rmb->name = mb->name;
1370 rmb->table_idx = NULL;
1371 rmb->init_locals = mb->init_locals;
1372 rmb->return_modreq = NULL;
1373 rmb->return_modopt = NULL;
1374 rmb->param_modreq = NULL;
1375 rmb->param_modopt = NULL;
1376 rmb->permissions = NULL;
1377 rmb->mhandle = mb->mhandle;
1383 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1385 MonoDynamicTable *table;
1388 ReflectionMethodBuilder rmb;
1391 reflection_methodbuilder_from_method_builder (&rmb, mb);
1393 mono_image_basic_method (&rmb, assembly);
1395 if (mb->dll) { /* It's a P/Invoke method */
1397 int charset = mb->charset & 0xf;
1398 int lasterr = mb->charset & 0x40;
1399 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1401 alloc_table (table, table->rows);
1402 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1403 /* map CharSet values to on-disk values */
1405 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1406 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1407 name = mono_string_to_utf8 (mb->dllentry);
1408 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1410 name = mono_string_to_utf8 (mb->dll);
1411 moduleref = string_heap_insert (&assembly->sheap, name);
1413 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1414 table = &assembly->tables [MONO_TABLE_MODULEREF];
1416 alloc_table (table, table->rows);
1417 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1418 values [MONO_IMPLMAP_SCOPE] = table->rows;
1422 if (mb->override_method) {
1423 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1425 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1427 alloc_table (table, table->rows);
1428 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1429 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1430 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1432 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1433 switch (mono_metadata_token_table (tok)) {
1434 case MONO_TABLE_MEMBERREF:
1435 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1437 case MONO_TABLE_METHOD:
1438 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1441 g_assert_not_reached ();
1443 values [MONO_METHODIMPL_DECLARATION] = tok;
1446 if (mb->generic_params) {
1447 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1448 table->rows += mono_array_length (mb->generic_params);
1449 alloc_table (table, table->rows);
1450 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1451 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1453 mono_image_get_generic_param_info (
1454 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1461 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1463 ReflectionMethodBuilder rmb;
1465 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1467 mono_image_basic_method (&rmb, assembly);
1471 type_get_fully_qualified_name (MonoType *type) {
1472 char *name, *result;
1476 name = mono_type_get_name (type);
1477 klass = my_mono_class_from_mono_type (type);
1478 ta = klass->image->assembly;
1480 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1481 name, ta->aname.name,
1482 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1483 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1484 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1490 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1494 klass = my_mono_class_from_mono_type (type);
1496 return mono_type_get_name (type);
1497 ta = klass->image->assembly;
1498 if (ta == ass || klass->image == mono_defaults.corlib)
1499 return mono_type_get_name (type);
1501 return type_get_fully_qualified_name (type);
1505 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1507 char blob_size [64];
1508 char *b = blob_size;
1513 if (!assembly->save)
1516 p = buf = g_malloc (64);
1518 mono_metadata_encode_value (0x06, p, &p);
1519 /* encode custom attributes before the type */
1520 encode_type (assembly, type, p, &p);
1521 g_assert (p-buf < 64);
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 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1531 char blob_size [64];
1532 char *b = blob_size;
1537 p = buf = g_malloc (64);
1539 mono_metadata_encode_value (0x06, p, &p);
1540 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1541 /* encode custom attributes before the type */
1542 encode_reflection_type (assembly, fb->type, p, &p);
1543 g_assert (p-buf < 64);
1544 mono_metadata_encode_value (p-buf, b, &b);
1545 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1551 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1552 char blob_size [64];
1553 char *b = blob_size;
1556 guint32 idx = 0, len = 0, dummy = 0;
1558 p = buf = g_malloc (64);
1560 *ret_type = MONO_TYPE_CLASS;
1562 box_val = (char*)&dummy;
1564 box_val = ((char*)val) + sizeof (MonoObject);
1565 *ret_type = val->vtable->klass->byval_arg.type;
1568 switch (*ret_type) {
1569 case MONO_TYPE_BOOLEAN:
1574 case MONO_TYPE_CHAR:
1589 case MONO_TYPE_VALUETYPE:
1590 if (val->vtable->klass->enumtype) {
1591 *ret_type = val->vtable->klass->enum_basetype->type;
1594 g_error ("we can't encode valuetypes");
1595 case MONO_TYPE_CLASS:
1597 case MONO_TYPE_STRING: {
1598 MonoString *str = (MonoString*)val;
1599 /* there is no signature */
1600 len = str->length * 2;
1601 mono_metadata_encode_value (len, b, &b);
1602 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1604 char *swapped = g_malloc (2 * mono_string_length (str));
1605 const char *p = (const char*)mono_string_chars (str);
1607 swap_with_size (swapped, p, 2, mono_string_length (str));
1608 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1612 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1619 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1622 /* there is no signature */
1623 mono_metadata_encode_value (len, b, &b);
1624 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1625 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1626 swap_with_size (blob_size, box_val, len, 1);
1627 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1629 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1637 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1638 char blob_size [64];
1639 char *b = blob_size;
1640 char *p, *buf, *str;
1641 guint32 idx, len, bufsize = 256;
1643 p = buf = g_malloc (bufsize);
1645 switch (minfo->type) {
1646 case MONO_NATIVE_BYVALTSTR:
1647 case MONO_NATIVE_BYVALARRAY:
1648 mono_metadata_encode_value (minfo->type, p, &p);
1649 mono_metadata_encode_value (minfo->count, p, &p);
1651 case MONO_NATIVE_LPARRAY:
1652 mono_metadata_encode_value (minfo->type, p, &p);
1653 if (minfo->eltype || (minfo->count > 0)) {
1654 mono_metadata_encode_value (minfo->eltype, p, &p);
1655 if (minfo->count > 0) {
1656 mono_metadata_encode_value (0, p, &p);
1657 mono_metadata_encode_value (minfo->count, p, &p);
1661 case MONO_NATIVE_CUSTOM:
1662 mono_metadata_encode_value (minfo->type, p, &p);
1664 str = mono_string_to_utf8 (minfo->guid);
1666 mono_metadata_encode_value (len, p, &p);
1667 memcpy (p, str, len);
1671 mono_metadata_encode_value (0, p, &p);
1673 if (minfo->marshaltype) {
1674 str = mono_string_to_utf8 (minfo->marshaltype);
1676 mono_metadata_encode_value (len, p, &p);
1677 if (p + len >= buf + bufsize) {
1680 buf = g_realloc (buf, bufsize);
1683 memcpy (p, str, len);
1687 mono_metadata_encode_value (0, p, &p);
1689 if (minfo->marshaltyperef) {
1690 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1692 mono_metadata_encode_value (len, p, &p);
1693 if (p + len >= buf + bufsize) {
1696 buf = g_realloc (buf, bufsize);
1699 memcpy (p, str, len);
1703 mono_metadata_encode_value (0, p, &p);
1705 if (minfo->mcookie) {
1706 str = mono_string_to_utf8 (minfo->mcookie);
1708 mono_metadata_encode_value (len, p, &p);
1709 if (p + len >= buf + bufsize) {
1712 buf = g_realloc (buf, bufsize);
1715 memcpy (p, str, len);
1719 mono_metadata_encode_value (0, p, &p);
1723 mono_metadata_encode_value (minfo->type, p, &p);
1727 mono_metadata_encode_value (len, b, &b);
1728 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1734 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1736 MonoDynamicTable *table;
1740 /* maybe this fixup should be done in the C# code */
1741 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1742 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1743 table = &assembly->tables [MONO_TABLE_FIELD];
1744 fb->table_idx = table->next_idx ++;
1745 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1746 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1747 name = mono_string_to_utf8 (fb->name);
1748 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1750 values [MONO_FIELD_FLAGS] = fb->attrs;
1751 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1753 if (fb->offset != -1) {
1754 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1756 alloc_table (table, table->rows);
1757 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1758 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1759 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1761 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1762 guint32 field_type = 0;
1763 table = &assembly->tables [MONO_TABLE_CONSTANT];
1765 alloc_table (table, table->rows);
1766 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1767 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1768 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1769 values [MONO_CONSTANT_TYPE] = field_type;
1770 values [MONO_CONSTANT_PADDING] = 0;
1772 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1774 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1776 alloc_table (table, table->rows);
1777 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1778 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1780 * We store it in the code section because it's simpler for now.
1783 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1785 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1786 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1788 if (fb->marshal_info) {
1789 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1791 alloc_table (table, table->rows);
1792 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1793 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1794 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1799 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1803 char *b = blob_size;
1804 guint32 nparams = 0;
1805 MonoReflectionMethodBuilder *mb = fb->get_method;
1806 MonoReflectionMethodBuilder *smb = fb->set_method;
1807 guint32 idx, i, size;
1809 if (mb && mb->parameters)
1810 nparams = mono_array_length (mb->parameters);
1811 if (!mb && smb && smb->parameters)
1812 nparams = mono_array_length (smb->parameters) - 1;
1813 size = 24 + nparams * 10;
1814 buf = p = g_malloc (size);
1817 mono_metadata_encode_value (nparams, p, &p);
1819 encode_reflection_type (assembly, mb->rtype, p, &p);
1820 for (i = 0; i < nparams; ++i) {
1821 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1822 encode_reflection_type (assembly, pt, p, &p);
1825 /* the property type is the last param */
1826 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1827 for (i = 0; i < nparams; ++i) {
1828 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1829 encode_reflection_type (assembly, pt, p, &p);
1833 g_assert (p - buf < size);
1834 mono_metadata_encode_value (p-buf, b, &b);
1835 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1841 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1843 MonoDynamicTable *table;
1846 guint num_methods = 0;
1850 * we need to set things in the following tables:
1851 * PROPERTYMAP (info already filled in _get_type_info ())
1852 * PROPERTY (rows already preallocated in _get_type_info ())
1853 * METHOD (method info already done with the generic method code)
1856 table = &assembly->tables [MONO_TABLE_PROPERTY];
1857 pb->table_idx = table->next_idx ++;
1858 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1859 name = mono_string_to_utf8 (pb->name);
1860 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1862 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1863 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1865 /* FIXME: we still don't handle 'other' methods */
1866 if (pb->get_method) num_methods ++;
1867 if (pb->set_method) num_methods ++;
1869 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1870 table->rows += num_methods;
1871 alloc_table (table, table->rows);
1873 if (pb->get_method) {
1874 semaidx = table->next_idx ++;
1875 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1876 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1877 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1878 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1880 if (pb->set_method) {
1881 semaidx = table->next_idx ++;
1882 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1883 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1884 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1885 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1890 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1892 MonoDynamicTable *table;
1895 guint num_methods = 0;
1899 * we need to set things in the following tables:
1900 * EVENTMAP (info already filled in _get_type_info ())
1901 * EVENT (rows already preallocated in _get_type_info ())
1902 * METHOD (method info already done with the generic method code)
1905 table = &assembly->tables [MONO_TABLE_EVENT];
1906 eb->table_idx = table->next_idx ++;
1907 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1908 name = mono_string_to_utf8 (eb->name);
1909 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1911 values [MONO_EVENT_FLAGS] = eb->attrs;
1912 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1915 * FIXME: we still don't handle 'other' methods
1917 if (eb->add_method) num_methods ++;
1918 if (eb->remove_method) num_methods ++;
1919 if (eb->raise_method) num_methods ++;
1921 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1922 table->rows += num_methods;
1923 alloc_table (table, table->rows);
1925 if (eb->add_method) {
1926 semaidx = table->next_idx ++;
1927 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1928 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1929 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1930 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1932 if (eb->remove_method) {
1933 semaidx = table->next_idx ++;
1934 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1935 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1936 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1937 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1939 if (eb->raise_method) {
1940 semaidx = table->next_idx ++;
1941 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1942 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1943 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1944 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1949 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1951 static MonoClass *NewConstraintAttr;
1952 static MonoMethod *NewConstraintAttr_ctor;
1953 MonoDynamicTable *table;
1955 guint32 token, type;
1956 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1959 if (!NewConstraintAttr)
1960 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1961 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1962 g_assert (NewConstraintAttr);
1964 if (!NewConstraintAttr_ctor) {
1967 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1968 MonoMethod *m = NewConstraintAttr->methods [i];
1970 if (strcmp (m->name, ".ctor"))
1973 NewConstraintAttr_ctor = m;
1977 g_assert (NewConstraintAttr_ctor);
1980 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1982 alloc_table (table, table->rows);
1984 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1985 owner <<= MONO_CUSTOM_ATTR_BITS;
1986 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1987 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1989 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1991 type = mono_metadata_token_index (token);
1992 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1993 switch (mono_metadata_token_table (token)) {
1994 case MONO_TABLE_METHOD:
1995 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1997 case MONO_TABLE_MEMBERREF:
1998 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
2001 g_warning ("got wrong token in custom attr");
2004 values [MONO_CUSTOM_ATTR_TYPE] = type;
2006 buf = p = g_malloc (1);
2007 mono_metadata_encode_value (4, p, &p);
2008 g_assert (p-buf == 1);
2010 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
2012 values += MONO_CUSTOM_ATTR_SIZE;
2017 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2019 MonoDynamicTable *table;
2020 guint32 num_constraints, i;
2024 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2025 num_constraints = gparam->iface_constraints ?
2026 mono_array_length (gparam->iface_constraints) : 0;
2027 table->rows += num_constraints;
2028 if (gparam->base_type)
2030 alloc_table (table, table->rows);
2032 if (gparam->base_type) {
2033 table_idx = table->next_idx ++;
2034 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2036 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2037 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2038 assembly, gparam->base_type->type);
2041 for (i = 0; i < num_constraints; i++) {
2042 MonoReflectionType *constraint = mono_array_get (
2043 gparam->iface_constraints, gpointer, i);
2045 table_idx = table->next_idx ++;
2046 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2048 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2049 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2050 assembly, constraint->type);
2053 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2054 encode_new_constraint (assembly, owner);
2058 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2060 GenericParamTableEntry *entry;
2063 * The GenericParam table must be sorted according to the `owner' field.
2064 * We need to do this sorting prior to writing the GenericParamConstraint
2065 * table, since we have to use the final GenericParam table indices there
2066 * and they must also be sorted.
2069 entry = g_new0 (GenericParamTableEntry, 1);
2070 entry->owner = owner;
2071 entry->gparam = gparam;
2073 g_ptr_array_add (assembly->gen_params, entry);
2077 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2079 MonoDynamicTable *table;
2080 MonoGenericParam *param;
2084 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2085 table_idx = table->next_idx ++;
2086 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2088 param = entry->gparam->type.type->data.generic_param;
2090 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2091 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2092 values [MONO_GENERICPARAM_NUMBER] = param->num;
2093 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2094 values [MONO_GENERICPARAM_KIND] = 0;
2096 encode_constraints (entry->gparam, table_idx, assembly);
2100 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2102 MonoDynamicTable *table;
2105 guint32 cols [MONO_ASSEMBLY_SIZE];
2109 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2112 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2113 table = &assembly->tables [MONO_TABLE_MODULEREF];
2114 token = table->next_idx ++;
2116 alloc_table (table, table->rows);
2117 values = table->values + token * MONO_MODULEREF_SIZE;
2118 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2120 token <<= MONO_RESOLTION_SCOPE_BITS;
2121 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2122 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2127 if (image->assembly->dynamic)
2129 memset (cols, 0, sizeof (cols));
2131 /* image->assembly->image is the manifest module */
2132 image = image->assembly->image;
2133 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2136 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2137 token = table->next_idx ++;
2139 alloc_table (table, table->rows);
2140 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2141 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2142 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2143 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2144 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2145 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2146 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2147 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2148 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2150 if (strcmp ("", image->assembly->aname.culture)) {
2151 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2152 image->assembly->aname.culture);
2155 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2156 guchar pubtoken [9];
2158 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2159 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2161 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2163 token <<= MONO_RESOLTION_SCOPE_BITS;
2164 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2165 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2170 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2172 MonoDynamicTable *table;
2178 char *b = blob_size;
2180 switch (type->type) {
2181 case MONO_TYPE_FNPTR:
2183 case MONO_TYPE_SZARRAY:
2184 case MONO_TYPE_ARRAY:
2186 case MONO_TYPE_MVAR:
2187 case MONO_TYPE_GENERICINST:
2188 encode_type (assembly, type, p, &p);
2190 case MONO_TYPE_CLASS:
2191 case MONO_TYPE_VALUETYPE: {
2192 MonoClass *k = mono_class_from_mono_type (type);
2193 if (!k || !k->generic_class)
2195 encode_generic_class (assembly, k->generic_class, p, &p);
2202 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2203 if (assembly->save) {
2204 g_assert (p-sig < 128);
2205 mono_metadata_encode_value (p-sig, b, &b);
2206 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2207 alloc_table (table, table->rows + 1);
2208 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2209 values [MONO_TYPESPEC_SIGNATURE] = token;
2212 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2213 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2219 * Despite the name, we handle also TypeSpec (with the above helper).
2222 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2224 MonoDynamicTable *table;
2226 guint32 token, scope, enclosing;
2229 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2232 token = create_typespec (assembly, type);
2235 klass = my_mono_class_from_mono_type (type);
2237 klass = mono_class_from_mono_type (type);
2240 * If it's in the same module and not a generic type parameter:
2242 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2243 (type->type != MONO_TYPE_MVAR)) {
2244 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2245 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2246 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2250 if (klass->nested_in) {
2251 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2252 /* get the typeref idx of the enclosing type */
2253 enclosing >>= MONO_TYPEDEFORREF_BITS;
2254 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2256 scope = resolution_scope_from_image (assembly, klass->image);
2258 table = &assembly->tables [MONO_TABLE_TYPEREF];
2259 if (assembly->save) {
2260 alloc_table (table, table->rows + 1);
2261 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2262 values [MONO_TYPEREF_SCOPE] = scope;
2263 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2264 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2266 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2267 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2269 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2274 * Insert a memberef row into the metadata: the token that point to the memberref
2275 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2276 * mono_image_get_fieldref_token()).
2277 * The sig param is an index to an already built signature.
2280 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2282 MonoDynamicTable *table;
2284 guint32 token, pclass;
2287 parent = mono_image_typedef_or_ref (assembly, type);
2288 switch (parent & MONO_TYPEDEFORREF_MASK) {
2289 case MONO_TYPEDEFORREF_TYPEREF:
2290 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2292 case MONO_TYPEDEFORREF_TYPESPEC:
2293 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2295 case MONO_TYPEDEFORREF_TYPEDEF:
2296 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2299 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2302 /* extract the index */
2303 parent >>= MONO_TYPEDEFORREF_BITS;
2305 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2307 if (assembly->save) {
2308 alloc_table (table, table->rows + 1);
2309 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2310 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2311 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2312 values [MONO_MEMBERREF_SIGNATURE] = sig;
2315 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2322 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2325 MonoMethodSignature *sig;
2327 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2332 * A methodref signature can't contain an unmanaged calling convention.
2334 sig = mono_metadata_signature_dup (method->signature);
2335 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2336 sig->call_convention = MONO_CALL_DEFAULT;
2337 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2338 method->name, method_encode_signature (assembly, sig));
2340 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2345 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2346 const gchar *name, guint32 sig)
2348 MonoDynamicTable *table;
2352 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2354 if (assembly->save) {
2355 alloc_table (table, table->rows + 1);
2356 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2357 values [MONO_MEMBERREF_CLASS] = original;
2358 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2359 values [MONO_MEMBERREF_SIGNATURE] = sig;
2362 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2369 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2372 ReflectionMethodBuilder rmb;
2374 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2378 reflection_methodbuilder_from_method_builder (&rmb, mb);
2380 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2381 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2382 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2387 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2390 ReflectionMethodBuilder rmb;
2392 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2396 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2398 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2399 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2400 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2405 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2410 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2413 g_assert (f->field->parent);
2414 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2415 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2416 f->field->name, fieldref_encode_signature (assembly, type));
2417 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2422 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2427 guint32 nparams = gmethod->inst->type_argc;
2428 guint32 size = 10 + nparams * 10;
2431 char *b = blob_size;
2433 if (!assembly->save)
2436 p = buf = g_malloc (size);
2438 * FIXME: vararg, explicit_this, differenc call_conv values...
2440 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2441 mono_metadata_encode_value (nparams, p, &p);
2443 for (i = 0; i < nparams; i++)
2444 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2447 g_assert (p - buf < size);
2448 mono_metadata_encode_value (p-buf, b, &b);
2449 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2455 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2457 MonoDynamicTable *table;
2459 guint32 token, mtoken = 0, sig;
2460 MonoMethodInflated *imethod;
2461 MonoMethod *declaring;
2463 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2465 g_assert (method->is_inflated);
2466 method = mono_get_inflated_method (method);
2467 imethod = (MonoMethodInflated *) method;
2468 declaring = imethod->declaring;
2470 sig = method_encode_signature (assembly, declaring->signature);
2471 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2473 if (!declaring->signature->generic_param_count)
2476 switch (mono_metadata_token_table (mtoken)) {
2477 case MONO_TABLE_MEMBERREF:
2478 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2480 case MONO_TABLE_METHOD:
2481 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2484 g_assert_not_reached ();
2487 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2489 if (assembly->save) {
2490 alloc_table (table, table->rows + 1);
2491 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2492 values [MONO_METHODSPEC_METHOD] = mtoken;
2493 values [MONO_METHODSPEC_SIGNATURE] = sig;
2496 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2503 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2505 MonoMethodInflated *imethod;
2508 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2512 g_assert (m->is_inflated);
2513 m = mono_get_inflated_method (m);
2514 imethod = (MonoMethodInflated *) m;
2516 if (imethod->declaring->signature->generic_param_count) {
2517 token = method_encode_methodspec (assembly, m);
2519 guint32 sig = method_encode_signature (
2520 assembly, imethod->declaring->signature);
2521 token = mono_image_get_memberref_token (
2522 assembly, &m->klass->byval_arg, m->name, sig);
2525 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2530 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2532 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2535 sig = method_encode_signature (assembly, imethod->declaring->signature);
2536 token = mono_image_get_memberref_token (
2537 assembly, &m->klass->byval_arg, m->name, sig);
2543 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2545 MonoDynamicTable *table;
2552 char *b = blob_size;
2556 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2557 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2558 * Because of this, we must not insert it into the `typeref' hash table.
2561 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2565 g_assert (tb->generic_params);
2566 klass = mono_class_from_mono_type (tb->type.type);
2568 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2569 encode_type (assembly, &klass->byval_arg, p, &p);
2571 count = mono_array_length (tb->generic_params);
2572 mono_metadata_encode_value (count, p, &p);
2573 for (i = 0; i < count; i++) {
2574 MonoReflectionGenericParam *gparam;
2576 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2578 encode_type (assembly, gparam->type.type, p, &p);
2581 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2582 if (assembly->save) {
2583 g_assert (p-sig < 128);
2584 mono_metadata_encode_value (p-sig, b, &b);
2585 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2586 alloc_table (table, table->rows + 1);
2587 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2588 values [MONO_TYPESPEC_SIGNATURE] = token;
2591 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2592 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2598 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2600 MonoDynamicTable *table;
2603 guint32 token, pclass, parent, sig;
2606 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2610 klass = mono_class_from_mono_type (fb->typeb->type);
2611 name = mono_string_to_utf8 (fb->name);
2613 sig = fieldref_encode_signature (assembly, fb->type->type);
2615 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2616 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2618 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2619 parent >>= MONO_TYPEDEFORREF_BITS;
2621 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2623 if (assembly->save) {
2624 alloc_table (table, table->rows + 1);
2625 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2626 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2627 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2628 values [MONO_MEMBERREF_SIGNATURE] = sig;
2631 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2633 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2638 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2646 char *b = blob_size;
2648 if (!assembly->save)
2652 g_assert (helper->type == 2);
2654 if (helper->arguments)
2655 nargs = mono_array_length (helper->arguments);
2659 size = 10 + (nargs * 10);
2661 p = buf = g_malloc (size);
2663 /* Encode calling convention */
2664 /* Change Any to Standard */
2665 if ((helper->call_conv & 0x03) == 0x03)
2666 helper->call_conv = 0x01;
2667 /* explicit_this implies has_this */
2668 if (helper->call_conv & 0x40)
2669 helper->call_conv &= 0x20;
2671 if (helper->call_conv == 0) { /* Unmanaged */
2672 *p = helper->unmanaged_call_conv - 1;
2675 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2676 if (helper->call_conv & 0x02) /* varargs */
2681 mono_metadata_encode_value (nargs, p, &p);
2682 encode_reflection_type (assembly, helper->return_type, p, &p);
2683 for (i = 0; i < nargs; ++i) {
2684 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2685 encode_reflection_type (assembly, pt, p, &p);
2688 g_assert (p - buf < size);
2689 mono_metadata_encode_value (p-buf, b, &b);
2690 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2697 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2700 MonoDynamicTable *table;
2703 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2704 idx = table->next_idx ++;
2706 alloc_table (table, table->rows);
2707 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2709 values [MONO_STAND_ALONE_SIGNATURE] =
2710 mono_reflection_encode_sighelper (assembly, helper);
2716 reflection_cc_to_file (int call_conv) {
2717 switch (call_conv & 0x3) {
2719 case 1: return MONO_CALL_DEFAULT;
2720 case 2: return MONO_CALL_VARARG;
2722 g_assert_not_reached ();
2729 MonoMethodSignature *sig;
2735 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2740 MonoMethodSignature *sig;
2743 name = mono_string_to_utf8 (m->name);
2744 nparams = mono_array_length (m->parameters);
2745 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2747 sig->sentinelpos = -1;
2748 sig->call_convention = reflection_cc_to_file (m->call_conv);
2749 sig->param_count = nparams;
2750 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2751 for (i = 0; i < nparams; ++i) {
2752 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2753 sig->params [i] = t->type;
2756 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2758 if (strcmp (name, am->name) == 0 &&
2759 mono_metadata_type_equal (am->parent, m->parent->type) &&
2760 mono_metadata_signature_equal (am->sig, sig)) {
2763 m->table_idx = am->token & 0xffffff;
2767 am = g_new0 (ArrayMethod, 1);
2770 am->parent = m->parent->type;
2771 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2772 method_encode_signature (assembly, sig));
2773 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2774 m->table_idx = am->token & 0xffffff;
2779 * Insert into the metadata tables all the info about the TypeBuilder tb.
2780 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2783 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2785 MonoDynamicTable *table;
2787 int i, is_object = 0, is_system = 0;
2790 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2791 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2792 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2793 n = mono_string_to_utf8 (tb->name);
2794 if (strcmp (n, "Object") == 0)
2796 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2798 n = mono_string_to_utf8 (tb->nspace);
2799 if (strcmp (n, "System") == 0)
2801 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2803 if (tb->parent && !(is_system && is_object) &&
2804 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2805 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2807 values [MONO_TYPEDEF_EXTENDS] = 0;
2809 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2810 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2813 * if we have explicitlayout or sequentiallayouts, output data in the
2814 * ClassLayout table.
2816 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2817 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2818 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2820 alloc_table (table, table->rows);
2821 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2822 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2823 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2824 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2827 /* handle interfaces */
2828 if (tb->interfaces) {
2829 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2831 table->rows += mono_array_length (tb->interfaces);
2832 alloc_table (table, table->rows);
2833 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2834 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2835 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2836 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2837 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2838 values += MONO_INTERFACEIMPL_SIZE;
2844 table = &assembly->tables [MONO_TABLE_FIELD];
2845 table->rows += tb->num_fields;
2846 alloc_table (table, table->rows);
2847 for (i = 0; i < tb->num_fields; ++i)
2848 mono_image_get_field_info (
2849 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2852 /* handle constructors */
2854 table = &assembly->tables [MONO_TABLE_METHOD];
2855 table->rows += mono_array_length (tb->ctors);
2856 alloc_table (table, table->rows);
2857 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2858 mono_image_get_ctor_info (domain,
2859 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2862 /* handle methods */
2864 table = &assembly->tables [MONO_TABLE_METHOD];
2865 table->rows += tb->num_methods;
2866 alloc_table (table, table->rows);
2867 for (i = 0; i < tb->num_methods; ++i)
2868 mono_image_get_method_info (
2869 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2872 /* Do the same with properties etc.. */
2873 if (tb->events && mono_array_length (tb->events)) {
2874 table = &assembly->tables [MONO_TABLE_EVENT];
2875 table->rows += mono_array_length (tb->events);
2876 alloc_table (table, table->rows);
2877 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2879 alloc_table (table, table->rows);
2880 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2881 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2882 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2883 for (i = 0; i < mono_array_length (tb->events); ++i)
2884 mono_image_get_event_info (
2885 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2887 if (tb->properties && mono_array_length (tb->properties)) {
2888 table = &assembly->tables [MONO_TABLE_PROPERTY];
2889 table->rows += mono_array_length (tb->properties);
2890 alloc_table (table, table->rows);
2891 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2893 alloc_table (table, table->rows);
2894 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2895 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2896 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2897 for (i = 0; i < mono_array_length (tb->properties); ++i)
2898 mono_image_get_property_info (
2899 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2902 /* handle generic parameters */
2903 if (tb->generic_params) {
2904 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2905 table->rows += mono_array_length (tb->generic_params);
2906 alloc_table (table, table->rows);
2907 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2908 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2910 mono_image_get_generic_param_info (
2911 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2915 mono_image_add_decl_security (assembly,
2916 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2919 MonoDynamicTable *ntable;
2921 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2922 ntable->rows += mono_array_length (tb->subtypes);
2923 alloc_table (ntable, ntable->rows);
2924 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2926 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2927 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2929 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2930 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2931 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2932 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2933 mono_string_to_utf8 (tb->name), tb->table_idx,
2934 ntable->next_idx, ntable->rows);*/
2935 values += MONO_NESTED_CLASS_SIZE;
2942 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2946 g_ptr_array_add (types, type);
2948 if (!type->subtypes)
2951 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2952 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2953 collect_types (types, subtype);
2958 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2960 if ((*type1)->table_idx < (*type2)->table_idx)
2963 if ((*type1)->table_idx > (*type2)->table_idx)
2970 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2975 for (i = 0; i < mono_array_length (pinfo); ++i) {
2976 MonoReflectionParamBuilder *pb;
2977 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2980 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2985 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2988 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2990 for (i = 0; i < tb->num_fields; ++i) {
2991 MonoReflectionFieldBuilder* fb;
2992 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2993 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2997 for (i = 0; i < mono_array_length (tb->events); ++i) {
2998 MonoReflectionEventBuilder* eb;
2999 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3000 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3003 if (tb->properties) {
3004 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3005 MonoReflectionPropertyBuilder* pb;
3006 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3007 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3011 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3012 MonoReflectionCtorBuilder* cb;
3013 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3014 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3015 params_add_cattrs (assembly, cb->pinfo);
3020 for (i = 0; i < tb->num_methods; ++i) {
3021 MonoReflectionMethodBuilder* mb;
3022 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3023 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3024 params_add_cattrs (assembly, mb->pinfo);
3029 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3030 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3035 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3038 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3040 /* no types in the module */
3044 for (i = 0; i < mb->num_types; ++i)
3045 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3049 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3051 MonoDynamicTable *table;
3055 char *b = blob_size;
3058 table = &assembly->tables [MONO_TABLE_FILE];
3060 alloc_table (table, table->rows);
3061 values = table->values + table->next_idx * MONO_FILE_SIZE;
3062 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3063 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3064 if (module->image->dynamic) {
3065 /* This depends on the fact that the main module is emitted last */
3066 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3067 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3070 path = g_strdup (module->image->name);
3072 mono_sha1_get_digest_from_file (path, hash);
3075 mono_metadata_encode_value (20, b, &b);
3076 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3077 mono_image_add_stream_data (&assembly->blob, hash, 20);
3082 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3084 MonoDynamicTable *table;
3088 table = &assembly->tables [MONO_TABLE_MODULE];
3089 mb->table_idx = table->next_idx ++;
3090 name = mono_string_to_utf8 (mb->module.name);
3091 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3093 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3096 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3097 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3098 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3102 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3103 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3105 MonoDynamicTable *table;
3109 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3110 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3113 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3115 alloc_table (table, table->rows);
3116 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3118 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3119 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3120 if (klass->nested_in)
3121 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3123 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3124 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3125 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3127 res = table->next_idx;
3131 /* Emit nested types */
3132 if (klass->nested_classes) {
3135 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3136 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3143 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3144 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3149 klass = mono_class_from_mono_type (tb->type.type);
3151 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3153 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3154 parent_index, assembly);
3158 * We need to do this ourselves since klass->nested_classes is not set up.
3161 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3162 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3167 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3168 guint32 module_index, MonoDynamicImage *assembly)
3170 MonoImage *image = module->image;
3174 t = &image->tables [MONO_TABLE_TYPEDEF];
3176 for (i = 0; i < t->rows; ++i) {
3177 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3179 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3180 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3184 #define align_pointer(base,p)\
3186 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3188 (p) += 4 - (__diff & 3);\
3192 compare_constants (const void *a, const void *b)
3194 const guint32 *a_values = a;
3195 const guint32 *b_values = b;
3196 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3200 compare_semantics (const void *a, const void *b)
3202 const guint32 *a_values = a;
3203 const guint32 *b_values = b;
3204 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3207 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3211 compare_custom_attrs (const void *a, const void *b)
3213 const guint32 *a_values = a;
3214 const guint32 *b_values = b;
3216 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3220 compare_field_marshal (const void *a, const void *b)
3222 const guint32 *a_values = a;
3223 const guint32 *b_values = b;
3225 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3229 compare_nested (const void *a, const void *b)
3231 const guint32 *a_values = a;
3232 const guint32 *b_values = b;
3234 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3238 compare_genericparam (const void *a, const void *b)
3240 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3241 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3243 if ((*b_entry)->owner == (*a_entry)->owner)
3245 (*a_entry)->gparam->type.type->data.generic_param->num -
3246 (*b_entry)->gparam->type.type->data.generic_param->num;
3248 return (*a_entry)->owner - (*b_entry)->owner;
3252 compare_declsecurity_attrs (const void *a, const void *b)
3254 const guint32 *a_values = a;
3255 const guint32 *b_values = b;
3257 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3261 pad_heap (MonoDynamicStream *sh)
3263 if (sh->index & 3) {
3264 int sz = 4 - (sh->index & 3);
3265 memset (sh->data + sh->index, 0, sz);
3272 MonoDynamicStream *stream;
3276 * build_compressed_metadata() fills in the blob of data that represents the
3277 * raw metadata as it will be saved in the PE file. The five streams are output
3278 * and the metadata tables are comnpressed from the guint32 array representation,
3279 * to the compressed on-disk format.
3282 build_compressed_metadata (MonoDynamicImage *assembly)
3284 MonoDynamicTable *table;
3286 guint64 valid_mask = 0;
3287 guint64 sorted_mask;
3288 guint32 heapt_size = 0;
3289 guint32 meta_size = 256; /* allow for header and other stuff */
3290 guint32 table_offset;
3291 guint32 ntables = 0;
3297 struct StreamDesc stream_desc [5];
3299 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3300 for (i = 0; i < assembly->gen_params->len; i++){
3301 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3302 write_generic_param_entry (assembly, entry);
3305 stream_desc [0].name = "#~";
3306 stream_desc [0].stream = &assembly->tstream;
3307 stream_desc [1].name = "#Strings";
3308 stream_desc [1].stream = &assembly->sheap;
3309 stream_desc [2].name = "#US";
3310 stream_desc [2].stream = &assembly->us;
3311 stream_desc [3].name = "#Blob";
3312 stream_desc [3].stream = &assembly->blob;
3313 stream_desc [4].name = "#GUID";
3314 stream_desc [4].stream = &assembly->guid;
3316 /* tables that are sorted */
3317 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3318 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3319 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3320 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3321 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3322 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3324 /* Compute table sizes */
3325 /* the MonoImage has already been created in mono_image_basic_init() */
3326 meta = &assembly->image;
3328 /* sizes should be multiple of 4 */
3329 pad_heap (&assembly->blob);
3330 pad_heap (&assembly->guid);
3331 pad_heap (&assembly->sheap);
3332 pad_heap (&assembly->us);
3334 /* Setup the info used by compute_sizes () */
3335 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3336 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3337 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3339 meta_size += assembly->blob.index;
3340 meta_size += assembly->guid.index;
3341 meta_size += assembly->sheap.index;
3342 meta_size += assembly->us.index;
3344 for (i=0; i < 64; ++i)
3345 meta->tables [i].rows = assembly->tables [i].rows;
3347 for (i = 0; i < 64; i++){
3348 if (meta->tables [i].rows == 0)
3350 valid_mask |= (guint64)1 << i;
3352 meta->tables [i].row_size = mono_metadata_compute_size (
3353 meta, i, &meta->tables [i].size_bitfield);
3354 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3356 heapt_size += 24; /* #~ header size */
3357 heapt_size += ntables * 4;
3358 /* make multiple of 4 */
3361 meta_size += heapt_size;
3362 meta->raw_metadata = g_malloc0 (meta_size);
3363 p = meta->raw_metadata;
3364 /* the metadata signature */
3365 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3366 /* version numbers and 4 bytes reserved */
3367 int16val = (guint16*)p;
3368 *int16val++ = GUINT16_TO_LE (1);
3369 *int16val = GUINT16_TO_LE (1);
3371 /* version string */
3372 int32val = (guint32*)p;
3373 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3375 memcpy (p, meta->version, strlen (meta->version));
3376 p += GUINT32_FROM_LE (*int32val);
3377 align_pointer (meta->raw_metadata, p);
3378 int16val = (guint16*)p;
3379 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3380 *int16val = GUINT16_TO_LE (5); /* number of streams */
3384 * write the stream info.
3386 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3387 table_offset += 3; table_offset &= ~3;
3389 assembly->tstream.index = heapt_size;
3390 for (i = 0; i < 5; ++i) {
3391 int32val = (guint32*)p;
3392 stream_desc [i].stream->offset = table_offset;
3393 *int32val++ = GUINT32_TO_LE (table_offset);
3394 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3395 table_offset += GUINT32_FROM_LE (*int32val);
3396 table_offset += 3; table_offset &= ~3;
3398 strcpy (p, stream_desc [i].name);
3399 p += strlen (stream_desc [i].name) + 1;
3400 align_pointer (meta->raw_metadata, p);
3403 * now copy the data, the table stream header and contents goes first.
3405 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3406 p = meta->raw_metadata + assembly->tstream.offset;
3407 int32val = (guint32*)p;
3408 *int32val = GUINT32_TO_LE (0); /* reserved */
3411 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3412 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3413 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3414 *p++ = 1; /* version */
3417 *p++ = 1; /* version */
3421 if (meta->idx_string_wide)
3423 if (meta->idx_guid_wide)
3425 if (meta->idx_blob_wide)
3428 *p++ = 1; /* reserved */
3429 int64val = (guint64*)p;
3430 *int64val++ = GUINT64_TO_LE (valid_mask);
3431 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3433 int32val = (guint32*)p;
3434 for (i = 0; i < 64; i++){
3435 if (meta->tables [i].rows == 0)
3437 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3439 p = (unsigned char*)int32val;
3441 /* sort the tables that still need sorting */
3442 table = &assembly->tables [MONO_TABLE_CONSTANT];
3444 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3445 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3447 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3448 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3450 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3451 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3453 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3454 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3456 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3457 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3458 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3460 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3462 /* compress the tables */
3463 for (i = 0; i < 64; i++){
3466 guint32 bitfield = meta->tables [i].size_bitfield;
3467 if (!meta->tables [i].rows)
3469 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3470 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3471 meta->tables [i].base = p;
3472 for (row = 1; row <= meta->tables [i].rows; ++row) {
3473 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3474 for (col = 0; col < assembly->tables [i].columns; ++col) {
3475 switch (mono_metadata_table_size (bitfield, col)) {
3477 *p++ = values [col];
3480 *p++ = values [col] & 0xff;
3481 *p++ = (values [col] >> 8) & 0xff;
3484 *p++ = values [col] & 0xff;
3485 *p++ = (values [col] >> 8) & 0xff;
3486 *p++ = (values [col] >> 16) & 0xff;
3487 *p++ = (values [col] >> 24) & 0xff;
3490 g_assert_not_reached ();
3494 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3497 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3498 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3499 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3500 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3501 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3503 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3507 * Some tables in metadata need to be sorted according to some criteria, but
3508 * when methods and fields are first created with reflection, they may be assigned a token
3509 * that doesn't correspond to the final token they will get assigned after the sorting.
3510 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3511 * with the reflection objects that represent them. Once all the tables are set up, the
3512 * reflection objects will contains the correct table index. fixup_method() will fixup the
3513 * tokens for the method with ILGenerator @ilgen.
3516 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3517 guint32 code_idx = GPOINTER_TO_UINT (value);
3518 MonoReflectionILTokenInfo *iltoken;
3519 MonoReflectionFieldBuilder *field;
3520 MonoReflectionCtorBuilder *ctor;
3521 MonoReflectionMethodBuilder *method;
3522 MonoReflectionTypeBuilder *tb;
3523 MonoReflectionArrayMethod *am;
3525 unsigned char *target;
3527 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3528 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3529 target = assembly->code.data + code_idx + iltoken->code_pos;
3530 switch (target [3]) {
3531 case MONO_TABLE_FIELD:
3532 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3533 field = (MonoReflectionFieldBuilder *)iltoken->member;
3534 idx = field->table_idx;
3535 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3536 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3537 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3539 g_assert_not_reached ();
3542 case MONO_TABLE_METHOD:
3543 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3544 method = (MonoReflectionMethodBuilder *)iltoken->member;
3545 idx = method->table_idx;
3546 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3547 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3548 idx = ctor->table_idx;
3549 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3550 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3551 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3552 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3554 g_assert_not_reached ();
3557 case MONO_TABLE_TYPEDEF:
3558 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3559 g_assert_not_reached ();
3560 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3561 idx = tb->table_idx;
3563 case MONO_TABLE_MEMBERREF:
3564 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3565 am = (MonoReflectionArrayMethod*)iltoken->member;
3566 idx = am->table_idx;
3567 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3568 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3569 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3570 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3571 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3572 g_assert (m->klass->generic_class || m->klass->generic_container);
3574 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3576 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3577 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3578 g_assert (f->generic_info);
3580 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3583 g_assert_not_reached ();
3586 case MONO_TABLE_METHODSPEC:
3587 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3588 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3589 g_assert (m->signature->generic_param_count);
3592 g_assert_not_reached ();
3596 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3598 target [0] = idx & 0xff;
3599 target [1] = (idx >> 8) & 0xff;
3600 target [2] = (idx >> 16) & 0xff;
3607 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3608 * value is not known when the table is emitted.
3611 fixup_cattrs (MonoDynamicImage *assembly)
3613 MonoDynamicTable *table;
3615 guint32 type, i, idx, token;
3618 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3620 for (i = 0; i < table->rows; ++i) {
3621 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3623 type = values [MONO_CUSTOM_ATTR_TYPE];
3624 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3625 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3626 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3627 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3630 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3631 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3632 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3633 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3640 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3642 MonoDynamicTable *table;
3646 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3648 alloc_table (table, table->rows);
3649 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3650 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3651 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3652 name = mono_string_to_utf8 (rsrc->name);
3653 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3655 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3660 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3662 MonoDynamicTable *table;
3666 char *b = blob_size;
3668 guint32 idx, offset;
3670 if (rsrc->filename) {
3671 name = mono_string_to_utf8 (rsrc->filename);
3672 sname = g_path_get_basename (name);
3674 table = &assembly->tables [MONO_TABLE_FILE];
3676 alloc_table (table, table->rows);
3677 values = table->values + table->next_idx * MONO_FILE_SIZE;
3678 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3679 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3682 mono_sha1_get_digest_from_file (name, hash);
3683 mono_metadata_encode_value (20, b, &b);
3684 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3685 mono_image_add_stream_data (&assembly->blob, hash, 20);
3687 idx = table->next_idx++;
3689 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3692 offset = mono_array_length (rsrc->data);
3693 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3694 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3695 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3696 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3700 * The entry should be emitted into the MANIFESTRESOURCE table of
3701 * the main module, but that needs to reference the FILE table
3702 * which isn't emitted yet.
3709 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3713 set_version_from_string (MonoString *version, guint32 *values)
3715 gchar *ver, *p, *str;
3718 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3719 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3720 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3721 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3724 ver = str = mono_string_to_utf8 (version);
3725 for (i = 0; i < 4; ++i) {
3726 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3732 /* handle Revision and Build */
3742 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3746 char *b = blob_size;
3751 len = mono_array_length (pkey);
3752 mono_metadata_encode_value (len, b, &b);
3753 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3754 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3756 /* need to get the actual value from the key type... */
3757 assembly->strong_name_size = 128;
3758 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3764 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3766 MonoDynamicTable *table;
3767 MonoDynamicImage *assembly;
3768 MonoReflectionAssemblyBuilder *assemblyb;
3773 guint32 module_index;
3775 assemblyb = moduleb->assemblyb;
3776 assembly = moduleb->dynamic_image;
3777 domain = mono_object_domain (assemblyb);
3779 /* Emit ASSEMBLY table */
3780 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3781 alloc_table (table, 1);
3782 values = table->values + MONO_ASSEMBLY_SIZE;
3783 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3784 name = mono_string_to_utf8 (assemblyb->name);
3785 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3787 if (assemblyb->culture) {
3788 name = mono_string_to_utf8 (assemblyb->culture);
3789 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3792 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3794 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3795 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3796 set_version_from_string (assemblyb->version, values);
3798 /* Emit FILE + EXPORTED_TYPE table */
3800 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3802 MonoReflectionModuleBuilder *file_module =
3803 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3804 if (file_module != moduleb) {
3805 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3807 if (file_module->types) {
3808 for (j = 0; j < file_module->num_types; ++j) {
3809 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3810 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3815 if (assemblyb->loaded_modules) {
3816 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3817 MonoReflectionModule *file_module =
3818 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3819 mono_image_fill_file_table (domain, file_module, assembly);
3821 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3825 /* Emit MANIFESTRESOURCE table */
3827 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3829 MonoReflectionModuleBuilder *file_module =
3830 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3831 /* The table for the main module is emitted later */
3832 if (file_module != moduleb) {
3834 if (file_module->resources) {
3835 int len = mono_array_length (file_module->resources);
3836 for (j = 0; j < len; ++j) {
3837 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3838 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3846 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3847 * for the modulebuilder @moduleb.
3848 * At the end of the process, method and field tokens are fixed up and the
3849 * on-disk compressed metadata representation is created.
3852 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3854 MonoDynamicTable *table;
3855 MonoDynamicImage *assembly;
3856 MonoReflectionAssemblyBuilder *assemblyb;
3861 assemblyb = moduleb->assemblyb;
3862 assembly = moduleb->dynamic_image;
3863 domain = mono_object_domain (assemblyb);
3865 if (assembly->text_rva)
3868 assembly->text_rva = START_TEXT_RVA;
3870 if (moduleb->is_main) {
3871 mono_image_emit_manifest (moduleb);
3874 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3875 table->rows = 1; /* .<Module> */
3877 alloc_table (table, table->rows);
3879 * Set the first entry.
3881 values = table->values + table->columns;
3882 values [MONO_TYPEDEF_FLAGS] = 0;
3883 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3884 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3885 values [MONO_TYPEDEF_EXTENDS] = 0;
3886 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3887 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3890 * handle global methods
3891 * FIXME: test what to do when global methods are defined in multiple modules.
3893 if (moduleb->global_methods) {
3894 table = &assembly->tables [MONO_TABLE_METHOD];
3895 table->rows += mono_array_length (moduleb->global_methods);
3896 alloc_table (table, table->rows);
3897 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3898 mono_image_get_method_info (
3899 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3901 if (moduleb->global_fields) {
3902 table = &assembly->tables [MONO_TABLE_FIELD];
3903 table->rows += mono_array_length (moduleb->global_fields);
3904 alloc_table (table, table->rows);
3905 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3906 mono_image_get_field_info (
3907 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3910 table = &assembly->tables [MONO_TABLE_MODULE];
3911 alloc_table (table, 1);
3912 mono_image_fill_module_table (domain, moduleb, assembly);
3916 /* Collect all types into a list sorted by their table_idx */
3917 GPtrArray *types = g_ptr_array_new ();
3920 for (i = 0; i < moduleb->num_types; ++i) {
3921 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3922 collect_types (types, type);
3925 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3926 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3927 table->rows += types->len;
3928 alloc_table (table, table->rows);
3930 for (i = 0; i < types->len; ++i) {
3931 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3932 mono_image_get_type_info (domain, type, assembly);
3934 g_ptr_array_free (types, TRUE);
3938 * table->rows is already set above and in mono_image_fill_module_table.
3940 /* add all the custom attributes at the end, once all the indexes are stable */
3941 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3943 /* CAS assembly permissions */
3944 if (assemblyb->permissions_minimum)
3945 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3946 if (assemblyb->permissions_optional)
3947 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3948 if (assemblyb->permissions_refused)
3949 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3951 module_add_cattrs (assembly, moduleb);
3954 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3955 fixup_cattrs (assembly);
3959 * mono_image_insert_string:
3960 * @module: module builder object
3963 * Insert @str into the user string stream of @module.
3966 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3968 MonoDynamicImage *assembly;
3973 MONO_ARCH_SAVE_REGS;
3975 if (!module->dynamic_image)
3976 mono_image_module_basic_init (module);
3978 assembly = module->dynamic_image;
3980 if (assembly->save) {
3981 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3982 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3983 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3985 char *swapped = g_malloc (2 * mono_string_length (str));
3986 const char *p = (const char*)mono_string_chars (str);
3988 swap_with_size (swapped, p, 2, mono_string_length (str));
3989 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3993 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3995 mono_image_add_stream_data (&assembly->us, "", 1);
3997 idx = assembly->us.index ++;
4000 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4002 return MONO_TOKEN_STRING | idx;
4006 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4011 klass = obj->vtable->klass;
4012 if (strcmp (klass->name, "MonoMethod") == 0) {
4013 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4014 MonoMethodSignature *sig, *old;
4015 guint32 sig_token, parent;
4018 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
4020 nargs = mono_array_length (opt_param_types);
4021 old = method->signature;
4022 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4024 sig->hasthis = old->hasthis;
4025 sig->explicit_this = old->explicit_this;
4026 sig->call_convention = old->call_convention;
4027 sig->generic_param_count = old->generic_param_count;
4028 sig->param_count = old->param_count + nargs;
4029 sig->sentinelpos = old->param_count;
4030 sig->ret = old->ret;
4032 for (i = 0; i < old->param_count; i++)
4033 sig->params [i] = old->params [i];
4035 for (i = 0; i < nargs; i++) {
4036 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4037 sig->params [old->param_count + i] = rt->type;
4040 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4041 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4042 parent >>= MONO_TYPEDEFORREF_BITS;
4044 parent <<= MONO_MEMBERREF_PARENT_BITS;
4045 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4047 sig_token = method_encode_signature (assembly, sig);
4048 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4049 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4050 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4051 ReflectionMethodBuilder rmb;
4052 guint32 parent, sig;
4054 reflection_methodbuilder_from_method_builder (&rmb, mb);
4055 rmb.opt_types = opt_param_types;
4057 sig = method_builder_encode_signature (assembly, &rmb);
4059 parent = mono_image_create_token (assembly, obj, TRUE);
4060 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4062 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4063 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4065 token = mono_image_get_varargs_method_token (
4066 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4068 g_error ("requested method token for %s\n", klass->name);
4075 * mono_image_create_token:
4076 * @assembly: a dynamic assembly
4079 * Get a token to insert in the IL code stream for the given MemberInfo.
4080 * @obj can be one of:
4081 * ConstructorBuilder
4091 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4096 klass = obj->vtable->klass;
4097 if (strcmp (klass->name, "MethodBuilder") == 0) {
4098 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4100 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4101 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4103 token = mono_image_get_methodbuilder_token (assembly, mb);
4104 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4105 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4106 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4108 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4109 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4111 token = mono_image_get_ctorbuilder_token (assembly, mb);
4112 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4113 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4114 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4115 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4116 if (tb->generic_params) {
4117 token = mono_image_get_generic_field_token (assembly, fb);
4119 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4121 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4122 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4123 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4124 } else if (strcmp (klass->name, "MonoType") == 0 ||
4125 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4126 MonoReflectionType *tb = (MonoReflectionType *)obj;
4127 token = mono_metadata_token_from_dor (
4128 mono_image_typedef_or_ref (assembly, tb->type));
4129 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4130 MonoReflectionType *tb = (MonoReflectionType *)obj;
4131 token = mono_metadata_token_from_dor (
4132 mono_image_typedef_or_ref (assembly, tb->type));
4133 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4134 strcmp (klass->name, "MonoMethod") == 0 ||
4135 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4136 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4137 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4138 if (m->method->is_inflated) {
4139 if (create_methodspec)
4140 token = mono_image_get_methodspec_token (assembly, m->method);
4142 token = mono_image_get_inflated_method_token (assembly, m->method);
4143 } else if ((m->method->klass->image == &assembly->image) &&
4144 !m->method->klass->generic_class) {
4145 static guint32 method_table_idx = 0xffffff;
4146 if (m->method->klass->wastypebuilder) {
4147 /* we use the same token as the one that was assigned
4148 * to the Methodbuilder.
4149 * FIXME: do the equivalent for Fields.
4151 token = m->method->token;
4154 * Each token should have a unique index, but the indexes are
4155 * assigned by managed code, so we don't know about them. An
4156 * easy solution is to count backwards...
4158 method_table_idx --;
4159 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4162 token = mono_image_get_methodref_token (assembly, m->method);
4164 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4165 } else if (strcmp (klass->name, "MonoField") == 0) {
4166 MonoReflectionField *f = (MonoReflectionField *)obj;
4167 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4168 static guint32 field_table_idx = 0xffffff;
4170 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4172 token = mono_image_get_fieldref_token (assembly, f);
4174 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4175 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4176 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4177 token = mono_image_get_array_token (assembly, m);
4178 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4179 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4180 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4182 g_error ("requested token for %s\n", klass->name);
4185 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4191 guint32 import_lookup_table;
4195 guint32 import_address_table_rva;
4203 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4205 static MonoDynamicImage*
4206 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4208 static const guchar entrycode [16] = {0xff, 0x25, 0};
4209 MonoDynamicImage *image;
4212 const char *version = mono_get_runtime_version ();
4215 image = GC_MALLOC (sizeof (MonoDynamicImage));
4217 image = g_new0 (MonoDynamicImage, 1);
4220 /* keep in sync with image.c */
4221 image->image.name = assembly_name;
4222 image->image.assembly_name = image->image.name; /* they may be different */
4223 image->image.module_name = module_name;
4224 image->image.version = g_strdup (version);
4225 image->image.dynamic = TRUE;
4227 image->image.references = g_new0 (MonoAssembly*, 1);
4228 image->image.references [0] = NULL;
4230 mono_image_init (&image->image);
4232 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4233 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4234 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4235 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4236 image->handleref = g_hash_table_new (NULL, NULL);
4237 image->tokens = mono_g_hash_table_new (NULL, NULL);
4238 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4239 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4240 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4241 image->gen_params = g_ptr_array_new ();
4243 string_heap_init (&image->sheap);
4244 mono_image_add_stream_data (&image->us, "", 1);
4245 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4246 /* import tables... */
4247 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4248 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4249 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4250 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4251 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4252 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4253 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4254 stream_data_align (&image->code);
4256 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4258 for (i=0; i < 64; ++i) {
4259 image->tables [i].next_idx = 1;
4260 image->tables [i].columns = table_sizes [i];
4263 image->image.assembly = (MonoAssembly*)assembly;
4264 image->run = assembly->run;
4265 image->save = assembly->save;
4266 image->pe_kind = 0x1; /* ILOnly */
4267 image->machine = 0x14c; /* I386 */
4273 * mono_image_basic_init:
4274 * @assembly: an assembly builder object
4276 * Create the MonoImage that represents the assembly builder and setup some
4277 * of the helper hash table and the basic metadata streams.
4280 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4282 MonoDynamicAssembly *assembly;
4283 MonoDynamicImage *image;
4285 MONO_ARCH_SAVE_REGS;
4287 if (assemblyb->dynamic_assembly)
4291 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4293 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4296 assembly->assembly.dynamic = TRUE;
4297 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4298 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4299 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4300 if (assemblyb->culture)
4301 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4303 assembly->assembly.aname.culture = g_strdup ("");
4305 assembly->run = assemblyb->access != 2;
4306 assembly->save = assemblyb->access != 1;
4308 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4309 image->initial_image = TRUE;
4310 assembly->assembly.aname.name = image->image.name;
4311 assembly->assembly.image = &image->image;
4313 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4314 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4318 calc_section_size (MonoDynamicImage *assembly)
4322 /* alignment constraints */
4323 assembly->code.index += 3;
4324 assembly->code.index &= ~3;
4325 assembly->meta_size += 3;
4326 assembly->meta_size &= ~3;
4327 assembly->resources.index += 3;
4328 assembly->resources.index &= ~3;
4330 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4331 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4334 if (assembly->win32_res) {
4335 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4337 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4338 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4342 assembly->sections [MONO_SECTION_RELOC].size = 12;
4343 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4353 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4357 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4359 ResTreeNode *t1 = (ResTreeNode*)a;
4360 ResTreeNode *t2 = (ResTreeNode*)b;
4362 return t1->id - t2->id;
4366 * resource_tree_create:
4368 * Organize the resources into a resource tree.
4370 static ResTreeNode *
4371 resource_tree_create (MonoArray *win32_resources)
4373 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4377 tree = g_new0 (ResTreeNode, 1);
4379 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4380 MonoReflectionWin32Resource *win32_res =
4381 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4385 lang_node = g_new0 (ResTreeNode, 1);
4386 lang_node->id = win32_res->lang_id;
4387 lang_node->win32_res = win32_res;
4389 /* Create type node if neccesary */
4391 for (l = tree->children; l; l = l->next)
4392 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4393 type_node = (ResTreeNode*)l->data;
4398 type_node = g_new0 (ResTreeNode, 1);
4399 type_node->id = win32_res->res_type;
4402 * The resource types have to be sorted otherwise
4403 * Windows Explorer can't display the version information.
4405 tree->children = g_slist_insert_sorted (tree->children,
4406 type_node, resource_tree_compare_by_id);
4409 /* Create res node if neccesary */
4411 for (l = type_node->children; l; l = l->next)
4412 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4413 res_node = (ResTreeNode*)l->data;
4418 res_node = g_new0 (ResTreeNode, 1);
4419 res_node->id = win32_res->res_id;
4420 type_node->children = g_slist_append (type_node->children, res_node);
4423 res_node->children = g_slist_append (res_node->children, lang_node);
4430 * resource_tree_encode:
4432 * Encode the resource tree into the format used in the PE file.
4435 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4438 MonoPEResourceDir dir;
4439 MonoPEResourceDirEntry dir_entry;
4440 MonoPEResourceDataEntry data_entry;
4444 * For the format of the resource directory, see the article
4445 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4449 memset (&dir, 0, sizeof (dir));
4450 memset (&dir_entry, 0, sizeof (dir_entry));
4451 memset (&data_entry, 0, sizeof (data_entry));
4453 g_assert (sizeof (dir) == 16);
4454 g_assert (sizeof (dir_entry) == 8);
4455 g_assert (sizeof (data_entry) == 16);
4457 node->offset = p - begin;
4459 /* IMAGE_RESOURCE_DIRECTORY */
4460 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4462 memcpy (p, &dir, sizeof (dir));
4465 /* Reserve space for entries */
4467 p += sizeof (dir_entry) * dir.res_id_entries;
4469 /* Write children */
4470 for (l = node->children; l; l = l->next) {
4471 ResTreeNode *child = (ResTreeNode*)l->data;
4473 if (child->win32_res) {
4475 child->offset = p - begin;
4477 /* IMAGE_RESOURCE_DATA_ENTRY */
4478 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4479 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4481 memcpy (p, &data_entry, sizeof (data_entry));
4482 p += sizeof (data_entry);
4484 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4485 p += data_entry.rde_size;
4487 resource_tree_encode (child, begin, p, &p);
4491 /* IMAGE_RESOURCE_ENTRY */
4492 for (l = node->children; l; l = l->next) {
4493 ResTreeNode *child = (ResTreeNode*)l->data;
4494 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4496 dir_entry.is_dir = child->win32_res ? 0 : 1;
4497 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4499 memcpy (entries, &dir_entry, sizeof (dir_entry));
4500 entries += sizeof (dir_entry);
4507 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4512 MonoReflectionWin32Resource *win32_res;
4515 if (!assemblyb->win32_resources)
4519 * Resources are stored in a three level tree inside the PE file.
4520 * - level one contains a node for each type of resource
4521 * - level two contains a node for each resource
4522 * - level three contains a node for each instance of a resource for a
4523 * specific language.
4526 tree = resource_tree_create (assemblyb->win32_resources);
4528 /* Estimate the size of the encoded tree */
4530 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4531 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4532 size += mono_array_length (win32_res->res_data);
4534 /* Directory structure */
4535 size += mono_array_length (assemblyb->win32_resources) * 256;
4536 p = buf = g_malloc (size);
4538 resource_tree_encode (tree, p, p, &p);
4540 g_assert (p - buf < size);
4542 assembly->win32_res = g_malloc (p - buf);
4543 assembly->win32_res_size = p - buf;
4544 memcpy (assembly->win32_res, buf, p - buf);
4550 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4552 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4555 p += sizeof (MonoPEResourceDir);
4556 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4557 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4558 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4559 if (dir_entry->is_dir) {
4560 fixup_resource_directory (res_section, child, rva);
4562 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4563 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4566 p += sizeof (MonoPEResourceDirEntry);
4571 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4574 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4575 g_error ("WriteFile returned %d\n", GetLastError ());
4579 * mono_image_create_pefile:
4580 * @mb: a module builder object
4582 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4583 * assembly->pefile where it can be easily retrieved later in chunks.
4586 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4587 MonoMSDOSHeader *msdos;
4588 MonoDotNetHeader *header;
4589 MonoSectionTable *section;
4590 MonoCLIHeader *cli_header;
4591 guint32 size, image_size, virtual_base, text_offset;
4592 guint32 header_start, section_start, file_offset, virtual_offset;
4593 MonoDynamicImage *assembly;
4594 MonoReflectionAssemblyBuilder *assemblyb;
4595 MonoDynamicStream pefile_stream = {0};
4596 MonoDynamicStream *pefile = &pefile_stream;
4598 guint32 *rva, value;
4600 static const unsigned char msheader[] = {
4601 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4602 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4605 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4606 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4607 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4608 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4611 assemblyb = mb->assemblyb;
4613 mono_image_basic_init (assemblyb);
4614 assembly = mb->dynamic_image;
4616 assembly->pe_kind = assemblyb->pe_kind;
4617 assembly->machine = assemblyb->machine;
4618 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4619 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4621 mono_image_build_metadata (mb);
4623 if (mb->is_main && assemblyb->resources) {
4624 int len = mono_array_length (assemblyb->resources);
4625 for (i = 0; i < len; ++i)
4626 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4629 if (mb->resources) {
4630 int len = mono_array_length (mb->resources);
4631 for (i = 0; i < len; ++i)
4632 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4635 build_compressed_metadata (assembly);
4638 assembly_add_win32_resources (assembly, assemblyb);
4640 nsections = calc_section_size (assembly);
4642 /* The DOS header and stub */
4643 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4644 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4646 /* the dotnet header */
4647 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4649 /* the section tables */
4650 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4652 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4653 virtual_offset = VIRT_ALIGN;
4656 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4657 if (!assembly->sections [i].size)
4660 file_offset += FILE_ALIGN - 1;
4661 file_offset &= ~(FILE_ALIGN - 1);
4662 virtual_offset += VIRT_ALIGN - 1;
4663 virtual_offset &= ~(VIRT_ALIGN - 1);
4665 assembly->sections [i].offset = file_offset;
4666 assembly->sections [i].rva = virtual_offset;
4668 file_offset += assembly->sections [i].size;
4669 virtual_offset += assembly->sections [i].size;
4670 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4673 file_offset += FILE_ALIGN - 1;
4674 file_offset &= ~(FILE_ALIGN - 1);
4676 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4678 /* back-patch info */
4679 msdos = (MonoMSDOSHeader*)pefile->data;
4680 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4681 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4682 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4684 header = (MonoDotNetHeader*)(pefile->data + header_start);
4685 header->pesig [0] = 'P';
4686 header->pesig [1] = 'E';
4688 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4689 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4690 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4691 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4692 if (assemblyb->pekind == 1) {
4694 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4697 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4700 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4702 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4703 header->pe.pe_major = 6;
4704 header->pe.pe_minor = 0;
4705 size = assembly->sections [MONO_SECTION_TEXT].size;
4706 size += FILE_ALIGN - 1;
4707 size &= ~(FILE_ALIGN - 1);
4708 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4709 size = assembly->sections [MONO_SECTION_RSRC].size;
4710 size += FILE_ALIGN - 1;
4711 size &= ~(FILE_ALIGN - 1);
4712 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4713 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4714 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4715 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4716 /* pe_rva_entry_point always at the beginning of the text section */
4717 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4719 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4720 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4721 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4722 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4723 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4724 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4725 size = section_start;
4726 size += FILE_ALIGN - 1;
4727 size &= ~(FILE_ALIGN - 1);
4728 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4730 size += VIRT_ALIGN - 1;
4731 size &= ~(VIRT_ALIGN - 1);
4732 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4735 // Translate the PEFileKind value to the value expected by the Windows loader
4741 // PEFileKinds.Dll == 1
4742 // PEFileKinds.ConsoleApplication == 2
4743 // PEFileKinds.WindowApplication == 3
4746 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4747 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4749 if (assemblyb->pekind == 3)
4754 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4756 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4757 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4758 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4759 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4760 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4761 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4763 /* fill data directory entries */
4765 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4766 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4768 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4769 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4771 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4772 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4773 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4774 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4775 /* patch entrypoint name */
4776 if (assemblyb->pekind == 1)
4777 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4779 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4780 /* patch imported function RVA name */
4781 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4782 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4784 /* the import table */
4785 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4786 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4787 /* patch imported dll RVA name and other entries in the dir */
4788 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4789 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4790 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4791 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4792 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4793 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4795 p = (assembly->code.data + assembly->ilt_offset);
4796 value = (assembly->text_rva + assembly->imp_names_offset);
4797 *p++ = (value) & 0xff;
4798 *p++ = (value >> 8) & (0xff);
4799 *p++ = (value >> 16) & (0xff);
4800 *p++ = (value >> 24) & (0xff);
4802 /* the CLI header info */
4803 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4804 cli_header->ch_size = GUINT32_FROM_LE (72);
4805 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4806 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4807 if (assemblyb->entry_point) {
4808 guint32 table_idx = 0;
4809 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4810 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4811 table_idx = methodb->table_idx;
4813 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4815 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4817 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4819 /* The embedded managed resources */
4820 text_offset = assembly->text_rva + assembly->code.index;
4821 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4822 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4823 text_offset += assembly->resources.index;
4824 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4825 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4826 text_offset += assembly->meta_size;
4827 if (assembly->strong_name_size) {
4828 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4829 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4830 text_offset += assembly->strong_name_size;
4833 /* write the section tables and section content */
4834 section = (MonoSectionTable*)(pefile->data + section_start);
4835 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4836 static const char *section_names [] = {
4837 ".text", ".rsrc", ".reloc"
4839 if (!assembly->sections [i].size)
4841 strcpy (section->st_name, section_names [i]);
4842 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4843 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4844 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4845 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4846 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4847 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4848 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4852 checked_write_file (file, pefile->data, pefile->index);
4854 mono_dynamic_stream_reset (pefile);
4856 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4857 if (!assembly->sections [i].size)
4860 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4861 g_error ("SetFilePointer returned %d\n", GetLastError ());
4864 case MONO_SECTION_TEXT:
4865 /* patch entry point */
4866 p = (assembly->code.data + 2);
4867 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4868 *p++ = (value) & 0xff;
4869 *p++ = (value >> 8) & 0xff;
4870 *p++ = (value >> 16) & 0xff;
4871 *p++ = (value >> 24) & 0xff;
4873 checked_write_file (file, assembly->code.data, assembly->code.index);
4874 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4875 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4876 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4879 g_free (assembly->image.raw_metadata);
4881 case MONO_SECTION_RELOC: {
4885 guint16 type_and_offset;
4889 g_assert (sizeof (reloc) == 12);
4891 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4892 reloc.block_size = GUINT32_FROM_LE (12);
4895 * the entrypoint is always at the start of the text section
4896 * 3 is IMAGE_REL_BASED_HIGHLOW
4897 * 2 is patch_size_rva - text_rva
4899 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4902 checked_write_file (file, &reloc, sizeof (reloc));
4906 case MONO_SECTION_RSRC:
4907 if (assembly->win32_res) {
4909 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4910 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4911 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
4915 g_assert_not_reached ();
4919 /* check that the file is properly padded */
4920 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4921 g_error ("SetFilePointer returned %d\n", GetLastError ());
4922 if (! SetEndOfFile (file))
4923 g_error ("SetEndOfFile returned %d\n", GetLastError ());
4925 mono_dynamic_stream_reset (&assembly->code);
4926 mono_dynamic_stream_reset (&assembly->us);
4927 mono_dynamic_stream_reset (&assembly->blob);
4928 mono_dynamic_stream_reset (&assembly->guid);
4929 string_heap_free (&assembly->sheap);
4931 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
4932 g_hash_table_destroy (assembly->blob_cache);
4935 MonoReflectionModule *
4936 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4940 MonoImageOpenStatus status;
4941 MonoDynamicAssembly *assembly;
4942 guint32 module_count;
4943 MonoImage **new_modules;
4945 name = mono_string_to_utf8 (fileName);
4947 image = mono_image_open (name, &status);
4950 if (status == MONO_IMAGE_ERROR_ERRNO)
4951 exc = mono_get_exception_file_not_found (fileName);
4953 exc = mono_get_exception_bad_image_format (name);
4955 mono_raise_exception (exc);
4960 assembly = ab->dynamic_assembly;
4961 image->assembly = (MonoAssembly*)assembly;
4963 module_count = image->assembly->image->module_count;
4964 new_modules = g_new0 (MonoImage *, module_count + 1);
4966 if (image->assembly->image->modules)
4967 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4968 new_modules [module_count] = image;
4970 g_free (image->assembly->image->modules);
4971 image->assembly->image->modules = new_modules;
4972 image->assembly->image->module_count ++;
4974 mono_assembly_load_references (image, &status);
4976 mono_image_close (image);
4977 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4980 return mono_module_get_object (mono_domain_get (), image);
4984 * We need to return always the same object for MethodInfo, FieldInfo etc..
4985 * but we need to consider the reflected type.
4986 * type uses a different hash, since it uses custom hash/equal functions.
4991 MonoClass *refclass;
4995 reflected_equal (gconstpointer a, gconstpointer b) {
4996 const ReflectedEntry *ea = a;
4997 const ReflectedEntry *eb = b;
4999 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5003 reflected_hash (gconstpointer a) {
5004 const ReflectedEntry *ea = a;
5005 return GPOINTER_TO_UINT (ea->item);
5008 #define CHECK_OBJECT(t,p,k) \
5014 mono_domain_lock (domain); \
5015 if (!domain->refobject_hash) \
5016 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5017 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5018 mono_domain_unlock (domain); \
5024 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5026 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5029 #define CACHE_OBJECT(p,o,k) \
5031 ReflectedEntry *e = ALLOC_REFENTRY; \
5033 e->refclass = (k); \
5034 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5035 mono_domain_unlock (domain); \
5039 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5041 /* this is done only once */
5042 mono_domain_lock (domain);
5043 CACHE_OBJECT (assembly, res, NULL);
5047 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5049 /* this is done only once */
5050 mono_domain_lock (domain);
5051 CACHE_OBJECT (module, res, NULL);
5055 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5057 MonoDynamicImage *image = moduleb->dynamic_image;
5058 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5061 * FIXME: we already created an image in mono_image_basic_init (), but
5062 * we don't know which module it belongs to, since that is only
5063 * determined at assembly save time.
5065 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5066 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5068 moduleb->module.image = &image->image;
5069 moduleb->dynamic_image = image;
5070 register_module (mono_object_domain (moduleb), moduleb, image);
5075 * mono_assembly_get_object:
5076 * @domain: an app domain
5077 * @assembly: an assembly
5079 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5081 MonoReflectionAssembly*
5082 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5084 static MonoClass *System_Reflection_Assembly;
5085 MonoReflectionAssembly *res;
5087 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5088 if (!System_Reflection_Assembly)
5089 System_Reflection_Assembly = mono_class_from_name (
5090 mono_defaults.corlib, "System.Reflection", "Assembly");
5091 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5092 res->assembly = assembly;
5094 CACHE_OBJECT (assembly, res, NULL);
5100 MonoReflectionModule*
5101 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5103 static MonoClass *System_Reflection_Module;
5104 MonoReflectionModule *res;
5107 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5108 if (!System_Reflection_Module)
5109 System_Reflection_Module = mono_class_from_name (
5110 mono_defaults.corlib, "System.Reflection", "Module");
5111 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5114 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5116 res->fqname = mono_string_new (domain, image->name);
5117 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5118 res->scopename = mono_string_new (domain, image->module_name);
5122 if (image->assembly->image == image) {
5123 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5126 g_assert (image->assembly->image->modules);
5128 for (i = 0; i < image->assembly->image->module_count; i++) {
5129 if (image->assembly->image->modules [i] == image)
5130 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5132 g_assert (res->token);
5135 mono_image_addref (image);
5137 CACHE_OBJECT (image, res, NULL);
5141 MonoReflectionModule*
5142 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5144 static MonoClass *System_Reflection_Module;
5145 MonoReflectionModule *res;
5146 MonoTableInfo *table;
5147 guint32 cols [MONO_FILE_SIZE];
5149 guint32 i, name_idx;
5152 if (!System_Reflection_Module)
5153 System_Reflection_Module = mono_class_from_name (
5154 mono_defaults.corlib, "System.Reflection", "Module");
5155 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5157 table = &image->tables [MONO_TABLE_FILE];
5158 g_assert (table_index < table->rows);
5159 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5162 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5163 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5165 /* Check whenever the row has a corresponding row in the moduleref table */
5166 table = &image->tables [MONO_TABLE_MODULEREF];
5167 for (i = 0; i < table->rows; ++i) {
5168 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5169 val = mono_metadata_string_heap (image, name_idx);
5170 if (strcmp (val, name) == 0)
5171 res->image = image->modules [i];
5174 res->fqname = mono_string_new (domain, name);
5175 res->name = mono_string_new (domain, name);
5176 res->scopename = mono_string_new (domain, name);
5177 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5178 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5184 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5186 if ((t1->type != t2->type) ||
5187 (t1->byref != t2->byref))
5191 case MONO_TYPE_VOID:
5192 case MONO_TYPE_BOOLEAN:
5193 case MONO_TYPE_CHAR:
5204 case MONO_TYPE_STRING:
5207 case MONO_TYPE_OBJECT:
5208 case MONO_TYPE_TYPEDBYREF:
5210 case MONO_TYPE_VALUETYPE:
5211 case MONO_TYPE_CLASS:
5212 case MONO_TYPE_SZARRAY:
5213 return t1->data.klass == t2->data.klass;
5215 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5216 case MONO_TYPE_ARRAY:
5217 if (t1->data.array->rank != t2->data.array->rank)
5219 return t1->data.array->eklass == t2->data.array->eklass;
5220 case MONO_TYPE_GENERICINST: {
5222 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5224 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5225 &t2->data.generic_class->container_class->byval_arg))
5227 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5228 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5234 case MONO_TYPE_MVAR:
5235 return t1->data.generic_param == t2->data.generic_param;
5237 g_error ("implement type compare for %0x!", t1->type);
5245 mymono_metadata_type_hash (MonoType *t1)
5251 hash |= t1->byref << 6; /* do not collide with t1->type values */
5253 case MONO_TYPE_VALUETYPE:
5254 case MONO_TYPE_CLASS:
5255 case MONO_TYPE_SZARRAY:
5256 /* check if the distribution is good enough */
5257 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5259 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5264 static MonoReflectionGenericClass*
5265 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5267 static MonoClass *System_Reflection_MonoGenericClass;
5268 MonoReflectionGenericClass *res;
5269 MonoGenericClass *gclass;
5272 if (!System_Reflection_MonoGenericClass) {
5273 System_Reflection_MonoGenericClass = mono_class_from_name (
5274 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5275 g_assert (System_Reflection_MonoGenericClass);
5278 gclass = geninst->data.generic_class;
5279 gklass = gclass->container_class;
5281 mono_class_init (gclass->klass);
5283 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5285 res->type.type = geninst;
5286 if (gklass->wastypebuilder && gklass->reflection_info)
5287 res->generic_type = gklass->reflection_info;
5289 res->generic_type = mono_type_get_object (domain, &gclass->container_class->byval_arg);
5295 * mono_type_get_object:
5296 * @domain: an app domain
5299 * Return an System.MonoType object representing the type @type.
5302 mono_type_get_object (MonoDomain *domain, MonoType *type)
5304 MonoReflectionType *res;
5305 MonoClass *klass = mono_class_from_mono_type (type);
5307 mono_domain_lock (domain);
5308 if (!domain->type_hash)
5309 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5310 (GCompareFunc)mymono_metadata_type_equal);
5311 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5312 mono_domain_unlock (domain);
5315 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5316 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5317 mono_g_hash_table_insert (domain->type_hash, type, res);
5318 mono_domain_unlock (domain);
5321 if (klass->reflection_info && !klass->wastypebuilder) {
5322 /* g_assert_not_reached (); */
5323 /* should this be considered an error condition? */
5325 mono_domain_unlock (domain);
5326 return klass->reflection_info;
5329 mono_class_init (klass);
5330 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5332 mono_g_hash_table_insert (domain->type_hash, type, res);
5333 mono_domain_unlock (domain);
5338 * mono_method_get_object:
5339 * @domain: an app domain
5341 * @refclass: the reflected type (can be NULL)
5343 * Return an System.Reflection.MonoMethod object representing the method @method.
5345 MonoReflectionMethod*
5346 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5349 * We use the same C representation for methods and constructors, but the type
5350 * name in C# is different.
5354 MonoReflectionMethod *ret;
5356 if (method->is_inflated) {
5357 MonoReflectionGenericMethod *gret;
5359 refclass = method->klass;
5360 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5361 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5362 cname = "MonoGenericCMethod";
5364 cname = "MonoGenericMethod";
5365 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5367 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5368 gret->method.method = method;
5369 gret->method.name = mono_string_new (domain, method->name);
5370 gret->method.reftype = mono_type_get_object (domain, &refclass->byval_arg);
5371 CACHE_OBJECT (method, gret, refclass);
5372 return (MonoReflectionMethod *) gret;
5376 refclass = method->klass;
5378 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5379 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5380 cname = "MonoCMethod";
5382 cname = "MonoMethod";
5383 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5385 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5386 ret->method = method;
5387 ret->name = mono_string_new (domain, method->name);
5388 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5389 CACHE_OBJECT (method, ret, refclass);
5394 * mono_field_get_object:
5395 * @domain: an app domain
5399 * Return an System.Reflection.MonoField object representing the field @field
5402 MonoReflectionField*
5403 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5405 MonoReflectionField *res;
5408 CHECK_OBJECT (MonoReflectionField *, field, klass);
5409 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5410 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5413 res->name = mono_string_new (domain, field->name);
5414 if (field->generic_info)
5415 res->attrs = field->generic_info->generic_type->attrs;
5417 res->attrs = field->type->attrs;
5418 res->type = mono_type_get_object (domain, field->type);
5419 CACHE_OBJECT (field, res, klass);
5424 * mono_property_get_object:
5425 * @domain: an app domain
5427 * @property: a property
5429 * Return an System.Reflection.MonoProperty object representing the property @property
5432 MonoReflectionProperty*
5433 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5435 MonoReflectionProperty *res;
5438 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5439 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5440 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5442 res->property = property;
5443 CACHE_OBJECT (property, res, klass);
5448 * mono_event_get_object:
5449 * @domain: an app domain
5453 * Return an System.Reflection.MonoEvent object representing the event @event
5456 MonoReflectionEvent*
5457 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5459 MonoReflectionEvent *res;
5462 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5463 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5464 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5467 CACHE_OBJECT (event, res, klass);
5472 * mono_param_get_objects:
5473 * @domain: an app domain
5476 * Return an System.Reflection.ParameterInfo array object representing the parameters
5477 * in the method @method.
5480 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5482 static MonoClass *System_Reflection_ParameterInfo;
5483 MonoArray *res = NULL;
5484 MonoReflectionMethod *member = NULL;
5485 MonoReflectionParameter *param = NULL;
5486 char **names, **blobs = NULL;
5487 MonoObject *dbnull = mono_get_dbnull_object (domain);
5488 MonoMarshalSpec **mspecs;
5491 if (!System_Reflection_ParameterInfo)
5492 System_Reflection_ParameterInfo = mono_class_from_name (
5493 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5495 if (!method->signature->param_count)
5496 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5498 /* Note: the cache is based on the address of the signature into the method
5499 * since we already cache MethodInfos with the method as keys.
5501 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5503 member = mono_method_get_object (domain, method, NULL);
5504 names = g_new (char *, method->signature->param_count);
5505 mono_method_get_param_names (method, (const char **) names);
5507 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5508 mono_method_get_marshal_info (method, mspecs);
5510 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5511 for (i = 0; i < method->signature->param_count; ++i) {
5512 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5513 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5514 param->MemberImpl = (MonoObject*)member;
5515 param->NameImpl = mono_string_new (domain, names [i]);
5516 param->PositionImpl = i;
5517 param->AttrsImpl = method->signature->params [i]->attrs;
5519 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5520 param->DefaultValueImpl = dbnull;
5522 MonoType *type = param->ClassImpl->type;
5525 blobs = g_new0 (char *, method->signature->param_count);
5526 get_default_param_value_blobs (method, blobs);
5529 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5531 if (!param->DefaultValueImpl) {
5532 param->DefaultValueImpl = dbnull;
5537 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5539 mono_array_set (res, gpointer, i, param);
5544 for (i = method->signature->param_count; i >= 0; i--)
5546 mono_metadata_free_marshal_spec (mspecs [i]);
5549 CACHE_OBJECT (&(method->signature), res, NULL);
5554 * mono_method_body_get_object:
5555 * @domain: an app domain
5558 * Return an System.Reflection.MethodBody object representing the method @method.
5560 MonoReflectionMethodBody*
5561 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5563 static MonoClass *System_Reflection_MethodBody = NULL;
5564 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5565 MonoReflectionMethodBody *ret;
5566 MonoMethodNormal *mn;
5567 MonoMethodHeader *header;
5570 if (!System_Reflection_MethodBody)
5571 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5572 if (!System_Reflection_LocalVariableInfo)
5573 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5575 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5577 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5578 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5580 mn = (MonoMethodNormal *)method;
5581 header = mono_method_get_header (method);
5583 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5584 /* FIXME: Other fields */
5585 ret->init_locals = header->init_locals;
5586 ret->max_stack = header->max_stack;
5587 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5588 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5589 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5590 for (i = 0; i < header->num_locals; ++i) {
5591 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5592 info->local_type = mono_type_get_object (domain, header->locals [i]);
5593 info->is_pinned = header->locals [i]->pinned;
5594 info->local_index = 0;
5597 CACHE_OBJECT (method, ret, NULL);
5602 mono_get_dbnull_object (MonoDomain *domain)
5606 static MonoClassField *dbnull_value_field = NULL;
5608 if (!dbnull_value_field) {
5609 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5610 mono_class_init (klass);
5611 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5612 g_assert (dbnull_value_field);
5614 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5621 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5623 guint32 param_index, i, lastp, crow = 0;
5624 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5627 MonoClass *klass = method->klass;
5628 MonoImage *image = klass->image;
5629 MonoMethodSignature *methodsig = method->signature;
5631 MonoTableInfo *constt;
5632 MonoTableInfo *methodt;
5633 MonoTableInfo *paramt;
5635 if (!methodsig->param_count)
5638 if (klass->generic_class) {
5639 return; /* FIXME - ??? */
5642 mono_class_init (klass);
5644 if (klass->image->dynamic) {
5645 MonoReflectionMethodAux *aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5646 if (aux && aux->param_defaults)
5647 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5651 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5652 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5653 constt = &image->tables [MONO_TABLE_CONSTANT];
5655 for (i = 0; i < klass->method.count; ++i) {
5656 if (method == klass->methods [i]) {
5657 idx = klass->method.first + i;
5662 g_assert (idx != -1);
5664 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5665 if (idx + 1 < methodt->rows)
5666 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5668 lastp = paramt->rows + 1;
5670 for (i = param_index; i < lastp; ++i) {
5673 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5674 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5676 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5679 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5684 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5685 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5692 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5701 klass = mono_class_from_mono_type (type);
5702 if (klass->valuetype) {
5703 object = mono_object_new (domain, klass);
5704 retval = ((gchar *) object + sizeof (MonoObject));
5709 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5716 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5720 memset (assembly, 0, sizeof (MonoAssemblyName));
5722 assembly->culture = "";
5723 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5725 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5728 while (g_ascii_isspace (*p) || *p == ',') {
5737 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5739 assembly->major = strtoul (p, &s, 10);
5740 if (s == p || *s != '.')
5743 assembly->minor = strtoul (p, &s, 10);
5744 if (s == p || *s != '.')
5747 assembly->build = strtoul (p, &s, 10);
5748 if (s == p || *s != '.')
5751 assembly->revision = strtoul (p, &s, 10);
5755 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5757 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5758 assembly->culture = "";
5761 assembly->culture = p;
5762 while (*p && *p != ',') {
5766 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5768 if (strncmp (p, "null", 4) == 0) {
5773 while (*p && *p != ',') {
5776 len = (p - start + 1);
5777 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5778 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5779 g_strlcpy (assembly->public_key_token, start, len);
5782 while (*p && *p != ',')
5786 while (g_ascii_isspace (*p) || *p == ',') {
5800 * mono_reflection_parse_type:
5803 * Parse a type name as accepted by the GetType () method and output the info
5804 * extracted in the info structure.
5805 * the name param will be mangled, so, make a copy before passing it to this function.
5806 * The fields in info will be valid until the memory pointed to by name is valid.
5808 * See also mono_type_get_name () below.
5810 * Returns: 0 on parse error.
5813 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5815 char *start, *p, *w, *last_point, *startn;
5816 int in_modifiers = 0;
5817 int isbyref = 0, rank;
5819 start = p = w = name;
5821 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5822 info->name = info->name_space = NULL;
5823 info->nested = NULL;
5824 info->modifiers = NULL;
5826 /* last_point separates the namespace from the name */
5832 *p = 0; /* NULL terminate the name */
5834 info->nested = g_list_append (info->nested, startn);
5835 /* we have parsed the nesting namespace + name */
5839 info->name_space = start;
5841 info->name = last_point + 1;
5843 info->name_space = (char *)"";
5869 info->name_space = start;
5871 info->name = last_point + 1;
5873 info->name_space = (char *)"";
5880 if (isbyref) /* only one level allowed by the spec */
5883 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5887 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5898 else if (*p != '*') /* '*' means unknown lower bound */
5904 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5909 if (g_ascii_isspace (*p)) {
5916 return 0; /* missing assembly name */
5917 if (!assembly_name_to_aname (&info->assembly, p))
5924 if (info->assembly.name)
5927 *w = 0; /* terminate class name */
5928 if (!info->name || !*info->name)
5930 /* add other consistency checks */
5935 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5942 image = mono_defaults.corlib;
5945 klass = mono_class_from_name_case (image, info->name_space, info->name);
5947 klass = mono_class_from_name (image, info->name_space, info->name);
5950 for (mod = info->nested; mod; mod = mod->next) {
5953 mono_class_init (klass);
5954 nested = klass->nested_classes;
5957 klass = nested->data;
5959 if (g_strcasecmp (klass->name, mod->data) == 0)
5962 if (strcmp (klass->name, mod->data) == 0)
5966 nested = nested->next;
5973 mono_class_init (klass);
5974 for (mod = info->modifiers; mod; mod = mod->next) {
5975 modval = GPOINTER_TO_UINT (mod->data);
5976 if (!modval) { /* byref: must be last modifier */
5977 return &klass->this_arg;
5978 } else if (modval == -1) {
5979 klass = mono_ptr_class_get (&klass->byval_arg);
5980 } else { /* array rank */
5981 klass = mono_array_class_get (klass, modval);
5983 mono_class_init (klass);
5986 return &klass->byval_arg;
5990 * mono_reflection_get_type:
5991 * @image: a metadata context
5992 * @info: type description structure
5993 * @ignorecase: flag for case-insensitive string compares
5994 * @type_resolve: whenever type resolve was already tried
5996 * Build a MonoType from the type description in @info.
6001 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6004 MonoReflectionAssembly *assembly;
6008 type = mono_reflection_get_type_internal (image, info, ignorecase);
6011 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6018 *type_resolve = TRUE;
6021 /* Reconstruct the type name */
6022 fullName = g_string_new ("");
6023 if (info->name_space && (info->name_space [0] != '\0'))
6024 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6026 g_string_printf (fullName, info->name);
6027 for (mod = info->nested; mod; mod = mod->next)
6028 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6030 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6032 if (assembly->assembly->dynamic) {
6033 /* Enumerate all modules */
6034 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6038 if (abuilder->modules) {
6039 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6040 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6041 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6047 if (!type && abuilder->loaded_modules) {
6048 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6049 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6050 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6057 type = mono_reflection_get_type_internal (assembly->assembly->image,
6060 g_string_free (fullName, TRUE);
6065 * mono_reflection_type_from_name:
6067 * @image: a metadata context (can be NULL).
6069 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6070 * it defaults to get the type from @image or, if @image is NULL or loading
6071 * from it fails, uses corlib.
6075 mono_reflection_type_from_name (char *name, MonoImage *image)
6078 MonoTypeNameParse info;
6079 MonoAssembly *assembly;
6081 gboolean type_resolve = FALSE;
6083 /* Make a copy since parse_type modifies its argument */
6084 tmp = g_strdup (name);
6086 /*g_print ("requested type %s\n", str);*/
6087 if (!mono_reflection_parse_type (tmp, &info)) {
6089 g_list_free (info.modifiers);
6090 g_list_free (info.nested);
6094 if (info.assembly.name) {
6095 assembly = mono_assembly_loaded (&info.assembly);
6097 /* then we must load the assembly ourselve - see #60439 */
6098 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6101 g_list_free (info.modifiers);
6102 g_list_free (info.nested);
6106 image = assembly->image;
6107 } else if (image == NULL) {
6108 image = mono_defaults.corlib;
6111 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6112 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6113 image = mono_defaults.corlib;
6114 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6118 g_list_free (info.modifiers);
6119 g_list_free (info.nested);
6124 * mono_reflection_get_token:
6126 * Return the metadata token of OBJ which should be an object
6127 * representing a metadata element.
6130 mono_reflection_get_token (MonoObject *obj)
6135 klass = obj->vtable->klass;
6137 if (strcmp (klass->name, "MethodBuilder") == 0) {
6138 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6140 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6141 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6142 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6144 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6145 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6146 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6147 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6148 if (tb->generic_params) {
6149 g_assert_not_reached ();
6151 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6153 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6154 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6155 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6156 } else if (strcmp (klass->name, "MonoType") == 0) {
6157 MonoReflectionType *tb = (MonoReflectionType *)obj;
6158 token = mono_class_from_mono_type (tb->type)->type_token;
6159 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6160 strcmp (klass->name, "MonoMethod") == 0) {
6161 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6162 if (m->method->is_inflated) {
6163 g_assert_not_reached ();
6164 } else if (m->method->signature->generic_param_count) {
6165 g_assert_not_reached ();
6166 } else if (m->method->klass->generic_class) {
6167 g_assert_not_reached ();
6169 token = m->method->token;
6171 } else if (strcmp (klass->name, "MonoField") == 0) {
6172 MonoReflectionField *f = (MonoReflectionField*)obj;
6174 token = mono_class_get_field_token (f->field);
6175 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6176 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6178 token = mono_class_get_property_token (p->property);
6179 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6180 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6182 token = mono_class_get_event_token (p->event);
6183 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6184 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6186 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6187 } else if (strcmp (klass->name, "Module") == 0) {
6188 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6191 } else if (strcmp (klass->name, "Assembly") == 0) {
6192 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6194 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6195 MonoException *ex = mono_get_exception_not_implemented (msg);
6197 mono_raise_exception (ex);
6204 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6206 int slen, type = t->type;
6211 case MONO_TYPE_BOOLEAN: {
6212 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6217 case MONO_TYPE_CHAR:
6219 case MONO_TYPE_I2: {
6220 guint16 *val = g_malloc (sizeof (guint16));
6225 #if SIZEOF_VOID_P == 4
6231 case MONO_TYPE_I4: {
6232 guint32 *val = g_malloc (sizeof (guint32));
6237 #if SIZEOF_VOID_P == 8
6238 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6243 case MONO_TYPE_I8: {
6244 guint64 *val = g_malloc (sizeof (guint64));
6249 case MONO_TYPE_VALUETYPE:
6250 if (t->data.klass->enumtype) {
6251 type = t->data.klass->enum_basetype->type;
6254 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6257 case MONO_TYPE_STRING:
6258 if (*p == (char)0xFF) {
6262 slen = mono_metadata_decode_value (p, &p);
6264 return mono_string_new_len (mono_domain_get (), p, slen);
6265 case MONO_TYPE_CLASS: {
6268 if (*p == (char)0xFF) {
6273 slen = mono_metadata_decode_value (p, &p);
6274 n = g_memdup (p, slen + 1);
6276 t = mono_reflection_type_from_name (n, image);
6278 g_warning ("Cannot load type '%s'", n);
6282 return mono_type_get_object (mono_domain_get (), t);
6286 case MONO_TYPE_OBJECT: {
6289 MonoClass *subc = NULL;
6294 } else if (subt == 0x0E) {
6295 type = MONO_TYPE_STRING;
6297 } else if (subt == 0x55) {
6300 slen = mono_metadata_decode_value (p, &p);
6301 n = g_memdup (p, slen + 1);
6303 t = mono_reflection_type_from_name (n, image);
6305 g_warning ("Cannot load type '%s'", n);
6308 subc = mono_class_from_mono_type (t);
6309 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6310 MonoType simple_type = {{0}};
6311 simple_type.type = subt;
6312 subc = mono_class_from_mono_type (&simple_type);
6314 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6316 val = load_cattr_value (image, &subc->byval_arg, p, end);
6317 obj = mono_object_new (mono_domain_get (), subc);
6318 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6322 case MONO_TYPE_SZARRAY: {
6324 guint32 i, alen, basetype;
6327 if (alen == 0xffffffff) {
6331 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6332 basetype = t->data.klass->byval_arg.type;
6337 case MONO_TYPE_BOOLEAN:
6338 for (i = 0; i < alen; i++) {
6339 MonoBoolean val = *p++;
6340 mono_array_set (arr, MonoBoolean, i, val);
6343 case MONO_TYPE_CHAR:
6346 for (i = 0; i < alen; i++) {
6347 guint16 val = read16 (p);
6348 mono_array_set (arr, guint16, i, val);
6355 for (i = 0; i < alen; i++) {
6356 guint32 val = read32 (p);
6357 mono_array_set (arr, guint32, i, val);
6364 for (i = 0; i < alen; i++) {
6365 guint64 val = read64 (p);
6366 mono_array_set (arr, guint64, i, val);
6370 case MONO_TYPE_CLASS:
6371 case MONO_TYPE_OBJECT:
6372 case MONO_TYPE_STRING:
6373 for (i = 0; i < alen; i++) {
6374 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6375 mono_array_set (arr, gpointer, i, item);
6379 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6385 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6391 type_is_reference (MonoType *type)
6393 switch (type->type) {
6394 case MONO_TYPE_BOOLEAN:
6395 case MONO_TYPE_CHAR:
6408 case MONO_TYPE_VALUETYPE:
6416 free_param_data (MonoMethodSignature *sig, void **params) {
6418 for (i = 0; i < sig->param_count; ++i) {
6419 if (!type_is_reference (sig->params [i]))
6420 g_free (params [i]);
6425 * Find the method index in the metadata methodDef table.
6426 * Later put these three helper methods in metadata and export them.
6429 find_method_index (MonoMethod *method) {
6430 MonoClass *klass = method->klass;
6433 for (i = 0; i < klass->method.count; ++i) {
6434 if (method == klass->methods [i])
6435 return klass->method.first + 1 + i;
6441 * Find the field index in the metadata FieldDef table.
6444 find_field_index (MonoClass *klass, MonoClassField *field) {
6447 for (i = 0; i < klass->field.count; ++i) {
6448 if (field == &klass->fields [i])
6449 return klass->field.first + 1 + i;
6455 * Find the property index in the metadata Property table.
6458 find_property_index (MonoClass *klass, MonoProperty *property) {
6461 for (i = 0; i < klass->property.count; ++i) {
6462 if (property == &klass->properties [i])
6463 return klass->property.first + 1 + i;
6469 * Find the event index in the metadata Event table.
6472 find_event_index (MonoClass *klass, MonoEvent *event) {
6475 for (i = 0; i < klass->event.count; ++i) {
6476 if (event == &klass->events [i])
6477 return klass->event.first + 1 + i;
6483 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6485 const char *p = data;
6487 guint32 i, j, num_named;
6491 mono_class_init (method->klass);
6494 attr = mono_object_new (mono_domain_get (), method->klass);
6495 mono_runtime_invoke (method, attr, NULL, NULL);
6499 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6502 /*g_print ("got attr %s\n", method->klass->name);*/
6504 params = g_new (void*, method->signature->param_count);
6508 for (i = 0; i < method->signature->param_count; ++i) {
6509 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6513 attr = mono_object_new (mono_domain_get (), method->klass);
6514 mono_runtime_invoke (method, attr, params, NULL);
6515 free_param_data (method->signature, params);
6517 num_named = read16 (named);
6519 for (j = 0; j < num_named; j++) {
6521 char *name, named_type, data_type;
6522 named_type = *named++;
6523 data_type = *named++; /* type of data */
6524 if (data_type == 0x55) {
6527 type_len = mono_metadata_decode_blob_size (named, &named);
6528 type_name = g_malloc (type_len + 1);
6529 memcpy (type_name, named, type_len);
6530 type_name [type_len] = 0;
6532 /* FIXME: lookup the type and check type consistency */
6533 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6534 /* this seems to be the type of the element of the array */
6535 /* g_print ("skipping 0x%02x after prop\n", *named); */
6538 name_len = mono_metadata_decode_blob_size (named, &named);
6539 name = g_malloc (name_len + 1);
6540 memcpy (name, named, name_len);
6541 name [name_len] = 0;
6543 if (named_type == 0x53) {
6544 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6545 void *val = load_cattr_value (image, field->type, named, &named);
6546 mono_field_set_value (attr, field, val);
6547 if (!type_is_reference (field->type))
6549 } else if (named_type == 0x54) {
6552 MonoType *prop_type;
6554 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6555 /* can we have more that 1 arg in a custom attr named property? */
6556 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6557 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6558 mono_property_set_value (prop, attr, pparams, NULL);
6559 if (!type_is_reference (prop_type))
6560 g_free (pparams [0]);
6569 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6576 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6577 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6578 for (i = 0; i < cinfo->num_attrs; ++i) {
6579 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6580 mono_array_set (result, gpointer, i, attr);
6586 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6588 guint32 mtoken, i, len;
6589 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6591 MonoCustomAttrInfo *ainfo;
6592 GList *tmp, *list = NULL;
6595 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6597 i = mono_metadata_custom_attrs_from_index (image, idx);
6601 while (i < ca->rows) {
6602 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6604 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6607 len = g_list_length (list);
6610 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6611 ainfo->num_attrs = len;
6612 ainfo->image = image;
6613 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6614 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6615 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6616 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6617 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6618 mtoken |= MONO_TOKEN_METHOD_DEF;
6620 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6621 mtoken |= MONO_TOKEN_MEMBER_REF;
6624 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6627 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6628 if (!ainfo->attrs [i].ctor)
6629 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6630 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6631 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6632 ainfo->attrs [i].data = data;
6640 mono_custom_attrs_from_method (MonoMethod *method)
6642 MonoCustomAttrInfo *cinfo;
6645 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6647 idx = find_method_index (method);
6648 idx <<= MONO_CUSTOM_ATTR_BITS;
6649 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6650 return mono_custom_attrs_from_index (method->klass->image, idx);
6654 mono_custom_attrs_from_class (MonoClass *klass)
6656 MonoCustomAttrInfo *cinfo;
6659 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6661 idx = mono_metadata_token_index (klass->type_token);
6662 idx <<= MONO_CUSTOM_ATTR_BITS;
6663 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6664 return mono_custom_attrs_from_index (klass->image, idx);
6668 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6670 MonoCustomAttrInfo *cinfo;
6673 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6675 idx = 1; /* there is only one assembly */
6676 idx <<= MONO_CUSTOM_ATTR_BITS;
6677 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6678 return mono_custom_attrs_from_index (assembly->image, idx);
6681 static MonoCustomAttrInfo*
6682 mono_custom_attrs_from_module (MonoImage *image)
6684 MonoCustomAttrInfo *cinfo;
6687 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6689 idx = 1; /* there is only one module */
6690 idx <<= MONO_CUSTOM_ATTR_BITS;
6691 idx |= MONO_CUSTOM_ATTR_MODULE;
6692 return mono_custom_attrs_from_index (image, idx);
6696 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6698 MonoCustomAttrInfo *cinfo;
6701 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6703 idx = find_property_index (klass, property);
6704 idx <<= MONO_CUSTOM_ATTR_BITS;
6705 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6706 return mono_custom_attrs_from_index (klass->image, idx);
6710 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6712 MonoCustomAttrInfo *cinfo;
6715 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6717 idx = find_event_index (klass, event);
6718 idx <<= MONO_CUSTOM_ATTR_BITS;
6719 idx |= MONO_CUSTOM_ATTR_EVENT;
6720 return mono_custom_attrs_from_index (klass->image, idx);
6724 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6726 MonoCustomAttrInfo *cinfo;
6729 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6731 idx = find_field_index (klass, field);
6732 idx <<= MONO_CUSTOM_ATTR_BITS;
6733 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6734 return mono_custom_attrs_from_index (klass->image, idx);
6738 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6741 guint32 i, idx, method_index;
6742 guint32 param_list, param_last, param_pos, found;
6744 MonoReflectionMethodAux *aux;
6746 if (method->klass->image->dynamic) {
6747 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6748 if (!aux || !aux->param_cattr)
6750 return aux->param_cattr [param];
6753 image = method->klass->image;
6754 method_index = find_method_index (method);
6755 ca = &image->tables [MONO_TABLE_METHOD];
6757 if (method->klass->generic_class || method->signature->generic_param_count) {
6758 /* FIXME FIXME FIXME */
6762 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6763 if (method_index == ca->rows) {
6764 ca = &image->tables [MONO_TABLE_PARAM];
6765 param_last = ca->rows + 1;
6767 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6768 ca = &image->tables [MONO_TABLE_PARAM];
6771 for (i = param_list; i < param_last; ++i) {
6772 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6773 if (param_pos == param) {
6781 idx <<= MONO_CUSTOM_ATTR_BITS;
6782 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6783 return mono_custom_attrs_from_index (image, idx);
6787 * mono_reflection_get_custom_attrs:
6788 * @obj: a reflection object handle
6790 * Return an array with all the custom attributes defined of the
6791 * reflection handle @obj. The objects are fully build.
6794 mono_reflection_get_custom_attrs (MonoObject *obj)
6798 MonoCustomAttrInfo *cinfo = NULL;
6800 MONO_ARCH_SAVE_REGS;
6802 klass = obj->vtable->klass;
6803 if (klass == mono_defaults.monotype_class) {
6804 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6805 klass = mono_class_from_mono_type (rtype->type);
6806 cinfo = mono_custom_attrs_from_class (klass);
6807 } else if (strcmp ("Assembly", klass->name) == 0) {
6808 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6809 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6810 } else if (strcmp ("Module", klass->name) == 0) {
6811 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6812 cinfo = mono_custom_attrs_from_module (module->image);
6813 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6814 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6815 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6816 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6817 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6818 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6819 } else if (strcmp ("MonoField", klass->name) == 0) {
6820 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6821 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6822 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6823 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6824 cinfo = mono_custom_attrs_from_method (rmethod->method);
6825 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
6826 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
6827 cinfo = mono_custom_attrs_from_method (method);
6828 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6829 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6830 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6831 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6832 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6833 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6834 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6835 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6836 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6837 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6838 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
6839 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
6840 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
6841 } else { /* handle other types here... */
6842 g_error ("get custom attrs not yet supported for %s", klass->name);
6846 result = mono_custom_attrs_construct (cinfo);
6848 mono_custom_attrs_free (cinfo);
6850 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6851 result = mono_array_new (mono_domain_get (), klass, 0);
6857 static MonoMethodSignature*
6858 parameters_to_signature (MonoArray *parameters) {
6859 MonoMethodSignature *sig;
6862 count = parameters? mono_array_length (parameters): 0;
6864 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6865 sig->param_count = count;
6866 sig->sentinelpos = -1; /* FIXME */
6867 for (i = 0; i < count; ++i) {
6868 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6869 sig->params [i] = pt->type;
6874 static MonoMethodSignature*
6875 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6876 MonoMethodSignature *sig;
6878 sig = parameters_to_signature (ctor->parameters);
6879 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6880 sig->ret = &mono_defaults.void_class->byval_arg;
6884 static MonoMethodSignature*
6885 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6886 MonoMethodSignature *sig;
6888 sig = parameters_to_signature (method->parameters);
6889 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6890 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6891 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6895 static MonoMethodSignature*
6896 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6897 MonoMethodSignature *sig;
6899 sig = parameters_to_signature (method->parameters);
6900 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6901 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6902 sig->generic_param_count = 0;
6907 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6909 MonoClass *klass = mono_object_class (prop);
6910 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6911 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6912 *name = mono_string_to_utf8 (pb->name);
6913 *type = pb->type->type;
6915 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6916 *name = g_strdup (p->property->name);
6917 if (p->property->get)
6918 *type = p->property->get->signature->ret;
6920 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6925 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6927 MonoClass *klass = mono_object_class (field);
6928 if (strcmp (klass->name, "FieldBuilder") == 0) {
6929 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6930 *name = mono_string_to_utf8 (fb->name);
6931 *type = fb->type->type;
6933 MonoReflectionField *f = (MonoReflectionField *)field;
6934 *name = g_strdup (f->field->name);
6935 *type = f->field->type;
6940 * Encode a value in a custom attribute stream of bytes.
6941 * The value to encode is either supplied as an object in argument val
6942 * (valuetypes are boxed), or as a pointer to the data in the
6944 * @type represents the type of the value
6945 * @buffer is the start of the buffer
6946 * @p the current position in the buffer
6947 * @buflen contains the size of the buffer and is used to return the new buffer size
6948 * if this needs to be realloced.
6949 * @retbuffer and @retp return the start and the position of the buffer
6952 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6954 MonoTypeEnum simple_type;
6956 if ((p-buffer) + 10 >= *buflen) {
6959 newbuf = g_realloc (buffer, *buflen);
6960 p = newbuf + (p-buffer);
6964 argval = ((char*)arg + sizeof (MonoObject));
6965 simple_type = type->type;
6967 switch (simple_type) {
6968 case MONO_TYPE_BOOLEAN:
6973 case MONO_TYPE_CHAR:
6976 swap_with_size (p, argval, 2, 1);
6982 swap_with_size (p, argval, 4, 1);
6988 swap_with_size (p, argval, 8, 1);
6991 case MONO_TYPE_VALUETYPE:
6992 if (type->data.klass->enumtype) {
6993 simple_type = type->data.klass->enum_basetype->type;
6996 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6999 case MONO_TYPE_STRING: {
7006 str = mono_string_to_utf8 ((MonoString*)arg);
7007 slen = strlen (str);
7008 if ((p-buffer) + 10 + slen >= *buflen) {
7012 newbuf = g_realloc (buffer, *buflen);
7013 p = newbuf + (p-buffer);
7016 mono_metadata_encode_value (slen, p, &p);
7017 memcpy (p, str, slen);
7022 case MONO_TYPE_CLASS: {
7030 k = mono_object_class (arg);
7031 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7032 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7033 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7035 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7036 slen = strlen (str);
7037 if ((p-buffer) + 10 + slen >= *buflen) {
7041 newbuf = g_realloc (buffer, *buflen);
7042 p = newbuf + (p-buffer);
7045 mono_metadata_encode_value (slen, p, &p);
7046 memcpy (p, str, slen);
7051 case MONO_TYPE_SZARRAY: {
7053 MonoClass *eclass, *arg_eclass;
7056 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7059 len = mono_array_length ((MonoArray*)arg);
7061 *p++ = (len >> 8) & 0xff;
7062 *p++ = (len >> 16) & 0xff;
7063 *p++ = (len >> 24) & 0xff;
7065 *retbuffer = buffer;
7066 eclass = type->data.klass;
7067 arg_eclass = mono_object_class (arg)->element_class;
7068 if (eclass->valuetype && arg_eclass->valuetype) {
7069 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7070 int elsize = mono_class_array_element_size (eclass);
7071 for (i = 0; i < len; ++i) {
7072 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7076 for (i = 0; i < len; ++i) {
7077 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7082 /* it may be a boxed value or a Type */
7083 case MONO_TYPE_OBJECT: {
7089 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7094 klass = mono_object_class (arg);
7096 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7099 } else if (klass->enumtype) {
7101 } else if (klass == mono_defaults.string_class) {
7102 simple_type = MONO_TYPE_STRING;
7105 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7106 *p++ = simple_type = klass->byval_arg.type;
7109 g_error ("unhandled type in custom attr");
7111 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7112 slen = strlen (str);
7113 if ((p-buffer) + 10 + slen >= *buflen) {
7117 newbuf = g_realloc (buffer, *buflen);
7118 p = newbuf + (p-buffer);
7121 mono_metadata_encode_value (slen, p, &p);
7122 memcpy (p, str, slen);
7125 simple_type = klass->enum_basetype->type;
7129 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7132 *retbuffer = buffer;
7136 * mono_reflection_get_custom_attrs_blob:
7137 * @ctor: custom attribute constructor
7138 * @ctorArgs: arguments o the constructor
7144 * Creates the blob of data that needs to be saved in the metadata and that represents
7145 * the custom attributed described by @ctor, @ctorArgs etc.
7146 * Returns: a Byte array representing the blob of data.
7149 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7152 MonoMethodSignature *sig;
7157 MONO_ARCH_SAVE_REGS;
7159 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7160 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7162 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7164 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7166 p = buffer = g_malloc (buflen);
7167 /* write the prolog */
7170 for (i = 0; i < sig->param_count; ++i) {
7171 arg = mono_array_get (ctorArgs, MonoObject*, i);
7172 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7176 i += mono_array_length (properties);
7178 i += mono_array_length (fields);
7180 *p++ = (i >> 8) & 0xff;
7183 for (i = 0; i < mono_array_length (properties); ++i) {
7188 prop = mono_array_get (properties, gpointer, i);
7189 get_prop_name_and_type (prop, &pname, &ptype);
7190 *p++ = 0x54; /* PROPERTY signature */
7192 /* Preallocate a large enough buffer */
7193 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7194 char *str = type_get_qualified_name (ptype, NULL);
7200 len += strlen (pname);
7202 if ((p-buffer) + 20 + len >= buflen) {
7206 newbuf = g_realloc (buffer, buflen);
7207 p = newbuf + (p-buffer);
7211 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7212 char *str = type_get_qualified_name (ptype, NULL);
7213 int slen = strlen (str);
7217 * This seems to be optional...
7220 mono_metadata_encode_value (slen, p, &p);
7221 memcpy (p, str, slen);
7225 mono_metadata_encode_value (ptype->type, p, &p);
7226 if (ptype->type == MONO_TYPE_SZARRAY)
7227 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7229 len = strlen (pname);
7230 mono_metadata_encode_value (len, p, &p);
7231 memcpy (p, pname, len);
7233 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7240 for (i = 0; i < mono_array_length (fields); ++i) {
7245 field = mono_array_get (fields, gpointer, i);
7246 get_field_name_and_type (field, &fname, &ftype);
7247 *p++ = 0x53; /* FIELD signature */
7248 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7249 char *str = type_get_qualified_name (ftype, NULL);
7250 int slen = strlen (str);
7251 if ((p-buffer) + 10 + slen >= buflen) {
7255 newbuf = g_realloc (buffer, buflen);
7256 p = newbuf + (p-buffer);
7261 * This seems to be optional...
7264 mono_metadata_encode_value (slen, p, &p);
7265 memcpy (p, str, slen);
7269 mono_metadata_encode_value (ftype->type, p, &p);
7270 if (ftype->type == MONO_TYPE_SZARRAY)
7271 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7273 len = strlen (fname);
7274 mono_metadata_encode_value (len, p, &p);
7275 memcpy (p, fname, len);
7277 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7282 g_assert (p - buffer <= buflen);
7283 buflen = p - buffer;
7284 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7285 p = mono_array_addr (result, char, 0);
7286 memcpy (p, buffer, buflen);
7288 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7294 * mono_reflection_setup_internal_class:
7295 * @tb: a TypeBuilder object
7297 * Creates a MonoClass that represents the TypeBuilder.
7298 * This is a trick that lets us simplify a lot of reflection code
7299 * (and will allow us to support Build and Run assemblies easier).
7302 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7304 MonoClass *klass, *parent;
7306 MONO_ARCH_SAVE_REGS;
7309 /* check so we can compile corlib correctly */
7310 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7311 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7312 parent = tb->parent->type->data.klass;
7314 parent = my_mono_class_from_mono_type (tb->parent->type);
7320 /* the type has already being created: it means we just have to change the parent */
7321 if (tb->type.type) {
7322 klass = mono_class_from_mono_type (tb->type.type);
7323 klass->parent = NULL;
7324 /* fool mono_class_setup_parent */
7325 g_free (klass->supertypes);
7326 klass->supertypes = NULL;
7327 mono_class_setup_parent (klass, parent);
7328 mono_class_setup_mono_type (klass);
7332 klass = g_new0 (MonoClass, 1);
7334 klass->image = &tb->module->dynamic_image->image;
7336 klass->inited = 1; /* we lie to the runtime */
7337 klass->name = mono_string_to_utf8 (tb->name);
7338 klass->name_space = mono_string_to_utf8 (tb->nspace);
7339 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7340 klass->flags = tb->attrs;
7342 klass->element_class = klass;
7343 klass->reflection_info = tb; /* need to pin. */
7345 /* Put into cache so mono_class_get () will find it */
7346 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7348 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7349 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7351 if (parent != NULL) {
7352 mono_class_setup_parent (klass, parent);
7353 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7354 const char *old_n = klass->name;
7355 /* trick to get relative numbering right when compiling corlib */
7356 klass->name = "BuildingObject";
7357 mono_class_setup_parent (klass, mono_defaults.object_class);
7358 klass->name = old_n;
7361 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7362 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7363 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7364 klass->instance_size = sizeof (MonoObject);
7365 klass->size_inited = 1;
7366 mono_class_setup_vtable (klass, NULL, 0);
7369 mono_class_setup_mono_type (klass);
7371 mono_class_setup_supertypes (klass);
7374 * FIXME: handle interfaces.
7377 tb->type.type = &klass->byval_arg;
7379 if (tb->nesting_type) {
7380 g_assert (tb->nesting_type->type);
7381 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7384 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7388 * mono_reflection_setup_generic_class:
7389 * @tb: a TypeBuilder object
7391 * Setup the generic class before adding the first generic parameter.
7394 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7398 MONO_ARCH_SAVE_REGS;
7400 klass = my_mono_class_from_mono_type (tb->type.type);
7401 if (tb->generic_container)
7404 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7405 tb->generic_container->klass = klass;
7407 tb->generic_container->context.container = tb->generic_container;
7411 * mono_reflection_create_generic_class:
7412 * @tb: a TypeBuilder object
7414 * Creates the generic class after all generic parameters have been added.
7417 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7422 MONO_ARCH_SAVE_REGS;
7424 klass = my_mono_class_from_mono_type (tb->type.type);
7426 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7428 if (klass->generic_container || (count == 0))
7431 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7433 klass->generic_container = tb->generic_container;
7435 klass->generic_container->type_argc = count;
7436 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7438 for (i = 0; i < count; i++) {
7439 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7440 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7441 g_assert (klass->generic_container->type_params [i].owner);
7444 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
7448 * mono_reflection_create_internal_class:
7449 * @tb: a TypeBuilder object
7451 * Actually create the MonoClass that is associated with the TypeBuilder.
7454 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7458 MONO_ARCH_SAVE_REGS;
7460 klass = my_mono_class_from_mono_type (tb->type.type);
7462 if (klass->enumtype && klass->enum_basetype == NULL) {
7463 MonoReflectionFieldBuilder *fb;
7466 g_assert (tb->fields != NULL);
7467 g_assert (mono_array_length (tb->fields) >= 1);
7469 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7471 klass->enum_basetype = fb->type->type;
7472 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7473 if (!klass->element_class)
7474 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7477 * get the element_class from the current corlib.
7479 ec = default_class_from_mono_type (klass->enum_basetype);
7480 klass->instance_size = ec->instance_size;
7481 klass->size_inited = 1;
7483 * this is almost safe to do with enums and it's needed to be able
7484 * to create objects of the enum type (for use in SetConstant).
7486 /* FIXME: Does this mean enums can't have method overrides ? */
7487 mono_class_setup_vtable (klass, NULL, 0);
7491 static MonoMarshalSpec*
7492 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7493 MonoReflectionMarshal *minfo)
7495 MonoMarshalSpec *res;
7497 res = g_new0 (MonoMarshalSpec, 1);
7498 res->native = minfo->type;
7500 switch (minfo->type) {
7501 case MONO_NATIVE_LPARRAY:
7502 res->data.array_data.elem_type = minfo->eltype;
7503 res->data.array_data.param_num = 0; /* Not yet */
7504 res->data.array_data.num_elem = minfo->count;
7507 case MONO_NATIVE_BYVALTSTR:
7508 case MONO_NATIVE_BYVALARRAY:
7509 res->data.array_data.num_elem = minfo->count;
7512 case MONO_NATIVE_CUSTOM:
7513 if (minfo->marshaltyperef)
7514 res->data.custom_data.custom_name =
7515 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7517 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7527 MonoReflectionMarshal*
7528 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7529 MonoMarshalSpec *spec)
7531 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7532 MonoReflectionMarshal *minfo;
7535 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7536 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7537 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7538 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7541 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7542 minfo->type = spec->native;
7544 switch (minfo->type) {
7545 case MONO_NATIVE_LPARRAY:
7546 minfo->eltype = spec->data.array_data.elem_type;
7547 minfo->count = spec->data.array_data.num_elem;
7550 case MONO_NATIVE_BYVALTSTR:
7551 case MONO_NATIVE_BYVALARRAY:
7552 minfo->count = spec->data.array_data.num_elem;
7555 case MONO_NATIVE_CUSTOM:
7556 if (spec->data.custom_data.custom_name) {
7557 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7559 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7561 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7563 if (spec->data.custom_data.cookie)
7564 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7575 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7576 ReflectionMethodBuilder *rmb,
7577 MonoMethodSignature *sig)
7580 MonoMethodNormal *pm;
7581 MonoMarshalSpec **specs;
7582 MonoReflectionMethodAux *method_aux;
7585 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7586 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7587 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7589 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7591 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7593 pm = (MonoMethodNormal*)m;
7596 m->flags = rmb->attrs;
7597 m->iflags = rmb->iattrs;
7598 m->name = mono_string_to_utf8 (rmb->name);
7602 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7604 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7605 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7608 m->signature->pinvoke = 1;
7609 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7610 m->signature->pinvoke = 1;
7612 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7614 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7615 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7617 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7618 printf ("B: %d %d\n", ((MonoMethodPInvoke*)m)->piflags, rmb->charset);
7620 if (klass->image->dynamic)
7621 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7624 } else if (!m->klass->dummy &&
7625 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7626 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7627 MonoMethodHeader *header;
7629 gint32 max_stack, i;
7630 gint32 num_locals = 0;
7631 gint32 num_clauses = 0;
7635 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7636 code_size = rmb->ilgen->code_len;
7637 max_stack = rmb->ilgen->max_stack;
7638 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7639 if (rmb->ilgen->ex_handlers)
7640 num_clauses = method_count_clauses (rmb->ilgen);
7643 code = mono_array_addr (rmb->code, guint8, 0);
7644 code_size = mono_array_length (rmb->code);
7645 /* we probably need to run a verifier on the code... */
7655 header = g_malloc0 (sizeof (MonoMethodHeader) +
7656 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7657 header->code_size = code_size;
7658 header->code = g_malloc (code_size);
7659 memcpy ((char*)header->code, code, code_size);
7660 header->max_stack = max_stack;
7661 header->init_locals = rmb->init_locals;
7662 header->num_locals = num_locals;
7664 for (i = 0; i < num_locals; ++i) {
7665 MonoReflectionLocalBuilder *lb =
7666 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7668 header->locals [i] = g_new0 (MonoType, 1);
7669 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7672 header->num_clauses = num_clauses;
7674 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7675 rmb->ilgen, num_clauses);
7678 pm->header = header;
7681 if (rmb->generic_params) {
7682 int count = mono_array_length (rmb->generic_params);
7683 MonoGenericContainer *container;
7685 pm->generic_container = container = rmb->generic_container;
7686 container->type_argc = count;
7687 container->type_params = g_new0 (MonoGenericParam, count);
7689 for (i = 0; i < count; i++) {
7690 MonoReflectionGenericParam *gp =
7691 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7693 container->type_params [i] = *gp->type.type->data.generic_param;
7698 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7701 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7703 for (i = 0; i < rmb->nrefs; ++i)
7704 mw->data = g_list_append (mw->data, rmb->refs [i]);
7709 /* Parameter info */
7712 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7713 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7714 for (i = 0; i <= m->signature->param_count; ++i) {
7715 MonoReflectionParamBuilder *pb;
7716 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7718 m->signature->params [i - 1]->attrs = pb->attrs;
7720 if (pb->def_value) {
7721 MonoDynamicImage *assembly;
7722 guint32 idx, def_type, len;
7726 if (!method_aux->param_defaults)
7727 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7728 assembly = (MonoDynamicImage*)klass->image;
7729 idx = encode_constant (assembly, pb->def_value, &def_type);
7730 /* Copy the data from the blob since it might get realloc-ed */
7731 p = assembly->blob.data + idx;
7732 len = mono_metadata_decode_blob_size (p, &p2);
7734 method_aux->param_defaults [i] = g_malloc (len);
7735 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7739 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7741 if (!method_aux->param_cattr)
7742 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7743 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7749 /* Parameter marshalling */
7752 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7753 MonoReflectionParamBuilder *pb;
7754 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7755 if (pb->marshal_info) {
7757 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7758 specs [pb->position] =
7759 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7763 if (specs != NULL) {
7765 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7766 method_aux->param_marshall = specs;
7769 if (klass->image->dynamic && method_aux)
7770 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7776 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7778 ReflectionMethodBuilder rmb;
7779 MonoMethodSignature *sig;
7781 sig = ctor_builder_to_signature (mb);
7783 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7785 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7786 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7788 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7789 /* ilgen is no longer needed */
7797 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7799 ReflectionMethodBuilder rmb;
7800 MonoMethodSignature *sig;
7802 sig = method_builder_to_signature (mb);
7804 reflection_methodbuilder_from_method_builder (&rmb, mb);
7806 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7807 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7809 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7810 /* ilgen is no longer needed */
7816 static MonoClassField*
7817 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7819 MonoClassField *field;
7826 field = g_new0 (MonoClassField, 1);
7828 field->name = mono_string_to_utf8 (fb->name);
7830 /* FIXME: handle type modifiers */
7831 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7832 field->type->attrs = fb->attrs;
7834 field->type = fb->type->type;
7836 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7837 field->data = mono_array_addr (fb->rva_data, char, 0);
7838 if (fb->offset != -1)
7839 field->offset = fb->offset;
7840 field->parent = klass;
7842 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7844 if (fb->def_value) {
7845 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7846 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7847 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7848 /* Copy the data from the blob since it might get realloc-ed */
7849 p = assembly->blob.data + idx;
7850 len = mono_metadata_decode_blob_size (p, &p2);
7852 field->data = g_malloc (len);
7853 memcpy ((gpointer)field->data, p, len);
7860 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
7864 MonoReflectionTypeBuilder *tb = NULL;
7865 MonoGenericClass *gclass, *cached;
7866 MonoDynamicGenericClass *dgclass = NULL;
7867 gboolean is_dynamic = FALSE;
7872 klass = mono_class_from_mono_type (type->type);
7873 if (!klass->generic_container && !klass->generic_class &&
7874 !(klass->nested_in && klass->nested_in->generic_container))
7877 mono_loader_lock ();
7879 domain = mono_object_domain (type);
7881 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7882 tb = (MonoReflectionTypeBuilder *) type;
7884 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7886 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
7887 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
7888 MonoReflectionType *rgt = rgi->generic_type;
7890 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7891 tb = (MonoReflectionTypeBuilder *) rgt;
7893 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7896 icount = klass->interface_count;
7900 dgclass = g_new0 (MonoDynamicGenericClass, 1);
7901 gclass = &dgclass->generic_class;
7902 gclass->is_dynamic = TRUE;
7904 gclass = g_new0 (MonoGenericClass, 1);
7906 gclass->inst = g_new0 (MonoGenericInst, 1);
7908 gclass->inst->type_argc = type_argc;
7909 gclass->inst->type_argv = types;
7911 for (i = 0; i < gclass->inst->type_argc; ++i) {
7912 if (!gclass->inst->is_open)
7913 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
7916 gclass->container_class = klass;
7918 if (klass->generic_class) {
7919 MonoGenericClass *kgclass = klass->generic_class;
7920 MonoGenericClass *ogclass = gclass;
7922 ogclass->context = g_new0 (MonoGenericContext, 1);
7923 ogclass->context->container = ogclass->container_class->generic_container;
7924 ogclass->context->gclass = ogclass;
7927 dgclass = g_new0 (MonoDynamicGenericClass, 1);
7928 gclass = &dgclass->generic_class;
7929 gclass->is_dynamic = TRUE;
7931 gclass = g_new0 (MonoGenericClass, 1);
7933 gclass->inst = g_new0 (MonoGenericInst, 1);
7935 gclass->inst->type_argc = kgclass->inst->type_argc;
7936 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
7938 for (i = 0; i < gclass->inst->type_argc; i++) {
7939 MonoType *t = kgclass->inst->type_argv [i];
7941 t = mono_class_inflate_generic_type (t, ogclass->context);
7943 if (!gclass->inst->is_open)
7944 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
7946 gclass->inst->type_argv [i] = t;
7949 gclass->container_class = kgclass->container_class;
7952 geninst = g_new0 (MonoType, 1);
7953 geninst->type = MONO_TYPE_GENERICINST;
7955 cached = mono_metadata_lookup_generic_class (gclass);
7958 mono_loader_unlock ();
7959 geninst->data.generic_class = cached;
7963 geninst->data.generic_class = gclass;
7965 gclass->parent = parent;
7967 gclass->context = g_new0 (MonoGenericContext, 1);
7968 gclass->context->container = gclass->container_class->generic_container;
7969 gclass->context->gclass = gclass;
7971 gclass->ifaces = g_new0 (MonoType *, icount);
7972 gclass->count_ifaces = icount;
7974 for (i = 0; i < icount; i++) {
7975 MonoReflectionType *itype;
7978 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7980 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7981 gclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7982 if (!gclass->ifaces [i])
7983 gclass->ifaces [i] = itype->type;
7986 mono_class_create_generic (gclass);
7987 mono_class_create_generic_2 (gclass);
7989 mono_loader_unlock ();
7995 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7997 MonoClass *klass, *pklass = NULL;
7998 MonoReflectionType *parent = NULL;
7999 MonoType *the_parent = NULL, *geninst;
8000 MonoReflectionTypeBuilder *tb = NULL;
8001 MonoGenericClass *gclass;
8004 domain = mono_object_domain (type);
8005 klass = mono_class_from_mono_type (type->type);
8007 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8008 tb = (MonoReflectionTypeBuilder *) type;
8011 parent = tb->parent;
8012 pklass = mono_class_from_mono_type (parent->type);
8015 pklass = klass->parent;
8017 parent = mono_type_get_object (domain, &pklass->byval_arg);
8018 else if (klass->generic_class && klass->generic_class->parent) {
8019 parent = mono_type_get_object (domain, klass->generic_class->parent);
8020 pklass = mono_class_from_mono_type (klass->generic_class->parent);
8024 if (pklass && pklass->generic_class)
8025 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
8027 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
8031 gclass = geninst->data.generic_class;
8037 dup_type (const MonoType *original)
8039 MonoType *r = g_new0 (MonoType, 1);
8041 r->attrs = original->attrs;
8042 r->byref = original->byref;
8043 mono_stats.generics_metadata_size += sizeof (MonoType);
8047 MonoReflectionMethod*
8048 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8050 MonoMethod *method, *inflated;
8051 MonoReflectionMethodBuilder *mb = NULL;
8052 MonoGenericContainer *container;
8053 MonoGenericMethod *gmethod;
8054 MonoGenericContext *context;
8055 MonoGenericInst *ginst;
8058 MONO_ARCH_SAVE_REGS;
8059 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8060 MonoReflectionTypeBuilder *tb;
8063 mb = (MonoReflectionMethodBuilder *) rmethod;
8064 tb = (MonoReflectionTypeBuilder *) mb->type;
8065 klass = mono_class_from_mono_type (tb->type.type);
8067 method = methodbuilder_to_mono_method (klass, mb);
8069 method = rmethod->method;
8072 count = method->signature->generic_param_count;
8073 if (count != mono_array_length (types))
8076 container = ((MonoMethodNormal*) method)->generic_container;
8077 g_assert (container);
8079 if (!container->method_hash)
8080 container->method_hash = g_hash_table_new (
8081 (GHashFunc) mono_metadata_generic_method_hash,
8082 (GCompareFunc) mono_metadata_generic_method_equal);
8084 ginst = g_new0 (MonoGenericInst,1 );
8085 ginst->type_argc = count;
8086 ginst->type_argv = g_new0 (MonoType *, count);
8087 for (i = 0; i < count; i++) {
8088 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8089 ginst->type_argv [i] = dup_type (garg->type);
8091 if (!ginst->is_open)
8092 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8094 ginst = mono_metadata_lookup_generic_inst (ginst);
8096 gmethod = g_new0 (MonoGenericMethod, 1);
8097 gmethod->container = container;
8098 gmethod->inst = ginst;
8100 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8104 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8107 gmethod->reflection_info = rmethod;
8109 context = g_new0 (MonoGenericContext, 1);
8110 context->container = container;
8111 context->gclass = method->klass->generic_class;
8112 context->gmethod = gmethod;
8114 inflated = mono_class_inflate_generic_method (method, context, NULL);
8115 g_hash_table_insert (container->method_hash, gmethod, inflated);
8117 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8121 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8123 MonoGenericMethod *gmethod;
8124 MonoGenericClass *gclass;
8125 MonoGenericContext *context;
8128 gclass = type->type.type->data.generic_class;
8130 gmethod = g_new0 (MonoGenericMethod, 1);
8131 gmethod->inst = g_new0 (MonoGenericInst, 1);
8132 gmethod->reflection_info = obj;
8134 gmethod->inst->type_argc = method->signature->generic_param_count;
8135 gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8137 for (i = 0; i < gmethod->inst->type_argc; i++) {
8138 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8139 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8141 g_assert (gparam->pklass);
8142 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8145 context = g_new0 (MonoGenericContext, 1);
8146 context->container = gclass->container_class->generic_container;
8147 context->gclass = gclass;
8148 context->gmethod = gmethod;
8150 return mono_class_inflate_generic_method (method, context, gclass->klass);
8154 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8159 klass = mono_class_from_mono_type (type->type.type);
8161 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8162 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8163 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8164 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8165 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8166 method = ((MonoReflectionMethod *) obj)->method;
8168 method = NULL; /* prevent compiler warning */
8169 g_assert_not_reached ();
8172 return inflate_mono_method (type, method, obj);
8176 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8177 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8180 MonoGenericClass *gclass;
8181 MonoDynamicGenericClass *dgclass;
8182 MonoClass *klass, *gklass, *pklass;
8185 MONO_ARCH_SAVE_REGS;
8187 klass = mono_class_from_mono_type (type->type.type);
8188 gclass = type->type.type->data.generic_class;
8190 if (gclass->initialized)
8193 g_assert (gclass->is_dynamic);
8194 dgclass = (MonoDynamicGenericClass *) gclass;
8196 gklass = gclass->container_class;
8197 mono_class_init (gklass);
8200 pklass = mono_class_from_mono_type (gclass->parent);
8202 pklass = gklass->parent;
8204 mono_class_setup_parent (klass, pklass);
8206 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8207 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8208 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8209 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8210 dgclass->count_events = events ? mono_array_length (events) : 0;
8212 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8213 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8214 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8215 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8216 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8218 for (i = 0; i < dgclass->count_methods; i++) {
8219 MonoObject *obj = mono_array_get (methods, gpointer, i);
8221 dgclass->methods [i] = inflate_method (type, obj);
8224 for (i = 0; i < dgclass->count_ctors; i++) {
8225 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8227 dgclass->ctors [i] = inflate_method (type, obj);
8230 for (i = 0; i < dgclass->count_fields; i++) {
8231 MonoObject *obj = mono_array_get (fields, gpointer, i);
8232 MonoClassField *field;
8233 MonoInflatedField *ifield;
8235 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8236 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8237 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8238 field = ((MonoReflectionField *) obj)->field;
8240 field = NULL; /* prevent compiler warning */
8241 g_assert_not_reached ();
8244 ifield = g_new0 (MonoInflatedField, 1);
8245 ifield->generic_type = field->type;
8246 ifield->reflection_info = obj;
8248 dgclass->fields [i] = *field;
8249 dgclass->fields [i].generic_info = ifield;
8250 dgclass->fields [i].type = mono_class_inflate_generic_type (field->type, gclass->context);
8253 for (i = 0; i < dgclass->count_properties; i++) {
8254 MonoObject *obj = mono_array_get (properties, gpointer, i);
8255 MonoProperty *property = &dgclass->properties [i];
8257 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8258 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8260 property->parent = klass;
8261 property->attrs = pb->attrs;
8262 property->name = mono_string_to_utf8 (pb->name);
8264 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8266 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8267 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8268 *property = *((MonoReflectionProperty *) obj)->property;
8271 property->get = inflate_mono_method (type, property->get, NULL);
8273 property->set = inflate_mono_method (type, property->set, NULL);
8275 g_assert_not_reached ();
8278 for (i = 0; i < dgclass->count_events; i++) {
8279 MonoObject *obj = mono_array_get (events, gpointer, i);
8280 MonoEvent *event = &dgclass->events [i];
8282 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8283 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8285 event->parent = klass;
8286 event->attrs = eb->attrs;
8287 event->name = mono_string_to_utf8 (eb->name);
8289 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8290 if (eb->remove_method)
8291 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8292 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8293 *event = *((MonoReflectionEvent *) obj)->event;
8296 event->add = inflate_mono_method (type, event->add, NULL);
8298 event->remove = inflate_mono_method (type, event->remove, NULL);
8300 g_assert_not_reached ();
8303 gclass->initialized = TRUE;
8307 ensure_runtime_vtable (MonoClass *klass)
8309 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8310 int i, num, j, onum;
8311 MonoMethod **overrides;
8313 if (!tb || klass->wastypebuilder)
8316 ensure_runtime_vtable (klass->parent);
8318 num = tb->ctors? mono_array_length (tb->ctors): 0;
8319 num += tb->num_methods;
8320 klass->method.count = num;
8321 klass->methods = g_new (MonoMethod*, num);
8322 num = tb->ctors? mono_array_length (tb->ctors): 0;
8323 for (i = 0; i < num; ++i)
8324 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8325 num = tb->num_methods;
8327 for (i = 0; i < num; ++i)
8328 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8330 if (tb->interfaces) {
8331 klass->interface_count = mono_array_length (tb->interfaces);
8332 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8333 for (i = 0; i < klass->interface_count; ++i) {
8334 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8335 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8339 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8340 for (i = 0; i < klass->method.count; ++i)
8341 klass->methods [i]->slot = i;
8346 for (i = 0; i < tb->num_methods; ++i) {
8347 MonoReflectionMethodBuilder *mb =
8348 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8349 if (mb->override_method)
8354 overrides = g_new0 (MonoMethod*, onum * 2);
8358 for (i = 0; i < tb->num_methods; ++i) {
8359 MonoReflectionMethodBuilder *mb =
8360 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8361 if (mb->override_method) {
8362 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8363 overrides [onum * 2] =
8364 mb->override_method->method;
8365 overrides [onum * 2 + 1] =
8368 g_assert (mb->mhandle);
8375 mono_class_setup_vtable (klass, overrides, onum);
8380 typebuilder_setup_fields (MonoClass *klass)
8382 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8383 MonoReflectionFieldBuilder *fb;
8384 MonoClassField *field;
8389 klass->field.count = tb->num_fields;
8390 klass->field.first = 0;
8391 klass->field.last = klass->field.count;
8393 if (!klass->field.count)
8396 klass->fields = g_new0 (MonoClassField, klass->field.count);
8398 for (i = 0; i < klass->field.count; ++i) {
8399 fb = mono_array_get (tb->fields, gpointer, i);
8400 field = &klass->fields [i];
8401 field->name = mono_string_to_utf8 (fb->name);
8403 /* FIXME: handle type modifiers */
8404 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8405 field->type->attrs = fb->attrs;
8407 field->type = fb->type->type;
8409 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8410 field->data = mono_array_addr (fb->rva_data, char, 0);
8411 if (fb->offset != -1)
8412 field->offset = fb->offset;
8413 field->parent = klass;
8415 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8417 if (fb->def_value) {
8418 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8419 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8420 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8421 /* Copy the data from the blob since it might get realloc-ed */
8422 p = assembly->blob.data + idx;
8423 len = mono_metadata_decode_blob_size (p, &p2);
8425 field->data = g_malloc (len);
8426 memcpy ((gpointer)field->data, p, len);
8429 mono_class_layout_fields (klass);
8433 typebuilder_setup_properties (MonoClass *klass)
8435 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8436 MonoReflectionPropertyBuilder *pb;
8439 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8440 klass->property.first = 0;
8441 klass->property.last = klass->property.count;
8443 klass->properties = g_new0 (MonoProperty, klass->property.count);
8444 for (i = 0; i < klass->property.count; ++i) {
8445 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8446 klass->properties [i].parent = klass;
8447 klass->properties [i].attrs = pb->attrs;
8448 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8450 klass->properties [i].get = pb->get_method->mhandle;
8452 klass->properties [i].set = pb->set_method->mhandle;
8456 MonoReflectionEvent *
8457 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8459 MonoEvent *event = g_new0 (MonoEvent, 1);
8463 klass = my_mono_class_from_mono_type (tb->type.type);
8465 event->parent = klass;
8466 event->attrs = eb->attrs;
8467 event->name = mono_string_to_utf8 (eb->name);
8469 event->add = eb->add_method->mhandle;
8470 if (eb->remove_method)
8471 event->remove = eb->remove_method->mhandle;
8472 if (eb->raise_method)
8473 event->raise = eb->raise_method->mhandle;
8475 if (eb->other_methods) {
8476 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8477 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8478 MonoReflectionMethodBuilder *mb =
8479 mono_array_get (eb->other_methods,
8480 MonoReflectionMethodBuilder*, j);
8481 event->other [j] = mb->mhandle;
8485 return mono_event_get_object (mono_object_domain (tb), klass, event);
8489 typebuilder_setup_events (MonoClass *klass)
8491 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8492 MonoReflectionEventBuilder *eb;
8495 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8496 klass->event.first = 0;
8497 klass->event.last = klass->event.count;
8499 klass->events = g_new0 (MonoEvent, klass->event.count);
8500 for (i = 0; i < klass->event.count; ++i) {
8501 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8502 klass->events [i].parent = klass;
8503 klass->events [i].attrs = eb->attrs;
8504 klass->events [i].name = mono_string_to_utf8 (eb->name);
8506 klass->events [i].add = eb->add_method->mhandle;
8507 if (eb->remove_method)
8508 klass->events [i].remove = eb->remove_method->mhandle;
8509 if (eb->raise_method)
8510 klass->events [i].raise = eb->raise_method->mhandle;
8512 if (eb->other_methods) {
8513 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8514 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8515 MonoReflectionMethodBuilder *mb =
8516 mono_array_get (eb->other_methods,
8517 MonoReflectionMethodBuilder*, j);
8518 klass->events [i].other [j] = mb->mhandle;
8525 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8528 MonoReflectionType* res;
8531 MONO_ARCH_SAVE_REGS;
8533 klass = my_mono_class_from_mono_type (tb->type.type);
8535 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8538 * Fields to set in klass:
8539 * the various flags: delegate/unicode/contextbound etc.
8541 klass->flags = tb->attrs;
8543 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8544 /* No need to fully construct the type */
8545 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8547 /* enums are done right away */
8548 if (!klass->enumtype)
8549 ensure_runtime_vtable (klass);
8552 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8553 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8554 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8558 /* fields and object layout */
8559 if (klass->parent) {
8560 if (!klass->parent->size_inited)
8561 mono_class_init (klass->parent);
8562 klass->instance_size += klass->parent->instance_size;
8563 klass->class_size += klass->parent->class_size;
8564 klass->min_align = klass->parent->min_align;
8566 klass->instance_size = sizeof (MonoObject);
8567 klass->min_align = 1;
8570 /* FIXME: handle packing_size and instance_size */
8571 typebuilder_setup_fields (klass);
8573 typebuilder_setup_properties (klass);
8575 typebuilder_setup_events (klass);
8577 klass->wastypebuilder = TRUE;
8579 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8580 g_assert (res != (MonoReflectionType*)tb);
8585 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8587 MonoGenericParam *param;
8590 MONO_ARCH_SAVE_REGS;
8592 param = g_new0 (MonoGenericParam, 1);
8594 if (gparam->mbuilder) {
8595 if (!gparam->mbuilder->generic_container)
8596 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8597 param->owner = gparam->mbuilder->generic_container;
8598 } else if (gparam->tbuilder) {
8599 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8600 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8605 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8606 if (gparam->index >= count)
8609 container = nesting->generic_container;
8610 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8613 g_assert (container);
8614 param->owner = container;
8617 param->method = NULL;
8618 param->name = mono_string_to_utf8 (gparam->name);
8619 param->num = gparam->index;
8621 image = &gparam->tbuilder->module->dynamic_image->image;
8622 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8624 param->pklass->reflection_info = gparam;
8626 gparam->type.type = g_new0 (MonoType, 1);
8627 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8628 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8629 gparam->type.type->data.generic_param = param;
8633 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8635 MonoDynamicImage *assembly = sig->module->dynamic_image;
8636 guint32 na = mono_array_length (sig->arguments);
8641 MONO_ARCH_SAVE_REGS;
8643 p = buf = g_malloc (10 + na * 10);
8645 mono_metadata_encode_value (0x07, p, &p);
8646 mono_metadata_encode_value (na, p, &p);
8647 for (i = 0; i < na; ++i) {
8648 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8649 encode_reflection_type (assembly, type, p, &p);
8653 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8654 p = mono_array_addr (result, char, 0);
8655 memcpy (p, buf, buflen);
8662 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8664 MonoDynamicImage *assembly = sig->module->dynamic_image;
8665 guint32 na = mono_array_length (sig->arguments);
8670 MONO_ARCH_SAVE_REGS;
8672 p = buf = g_malloc (10 + na * 10);
8674 mono_metadata_encode_value (0x06, p, &p);
8675 for (i = 0; i < na; ++i) {
8676 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8677 encode_reflection_type (assembly, type, p, &p);
8681 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8682 p = mono_array_addr (result, char, 0);
8683 memcpy (p, buf, buflen);
8690 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8692 ReflectionMethodBuilder rmb;
8693 MonoMethodSignature *sig;
8696 sig = dynamic_method_to_signature (mb);
8698 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8701 * Resolve references.
8703 rmb.nrefs = mb->nrefs;
8704 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8705 for (i = 0; i < mb->nrefs; ++i) {
8706 gpointer ref = resolve_object (mb->module->image,
8707 mono_array_get (mb->refs, MonoObject*, i));
8710 mono_raise_exception (mono_get_exception_type_load (NULL));
8717 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8721 /* ilgen is no longer needed */
8726 * mono_reflection_lookup_dynamic_token:
8728 * Finish the Builder object pointed to by TOKEN and return the corresponding
8729 * runtime structure.
8732 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8734 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8737 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8740 return resolve_object (image, obj);
8744 resolve_object (MonoImage *image, MonoObject *obj)
8746 gpointer result = NULL;
8748 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8749 result = mono_string_intern ((MonoString*)obj);
8751 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8752 MonoReflectionType *tb = (MonoReflectionType*)obj;
8753 result = mono_class_from_mono_type (tb->type);
8755 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8756 result = ((MonoReflectionMethod*)obj)->method;
8758 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8759 result = ((MonoReflectionMethod*)obj)->method;
8761 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8762 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8763 result = mb->mhandle;
8765 /* Type is not yet created */
8766 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8768 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8771 * Hopefully this has been filled in by calling CreateType() on the
8775 * TODO: This won't work if the application finishes another
8776 * TypeBuilder instance instead of this one.
8778 result = mb->mhandle;
8780 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8781 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8783 result = cb->mhandle;
8785 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8787 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8788 result = cb->mhandle;
8790 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8791 result = ((MonoReflectionField*)obj)->field;
8793 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8794 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8795 result = fb->handle;
8798 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8800 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8801 result = fb->handle;
8803 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8804 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8807 klass = tb->type.type->data.klass;
8808 if (klass->wastypebuilder) {
8809 /* Already created */
8813 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8814 result = tb->type.type->data.klass;
8817 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8818 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8819 MonoMethodSignature *sig;
8822 if (helper->arguments)
8823 nargs = mono_array_length (helper->arguments);
8827 sig = mono_metadata_signature_alloc (image, nargs);
8828 sig->explicit_this = helper->call_conv & 64;
8829 sig->hasthis = helper->call_conv & 32;
8831 if (helper->call_conv == 0) /* unmanaged */
8832 sig->call_convention = helper->unmanaged_call_conv - 1;
8834 if (helper->call_conv & 0x02)
8835 sig->call_convention = MONO_CALL_VARARG;
8837 sig->call_convention = MONO_CALL_DEFAULT;
8839 sig->param_count = nargs;
8840 /* TODO: Copy type ? */
8841 sig->ret = helper->return_type->type;
8842 for (i = 0; i < nargs; ++i) {
8843 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8844 sig->params [i] = rt->type;
8849 g_print (obj->vtable->klass->name);
8850 g_assert_not_reached ();
8856 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
8857 const static guint32 declsec_flags_map[] = {
8858 0x00000000, /* empty */
8859 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
8860 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
8861 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
8862 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
8863 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
8864 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
8865 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
8866 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
8867 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
8868 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
8869 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
8870 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
8871 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
8872 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
8873 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
8874 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
8875 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
8876 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
8880 * Returns flags that includes all available security action associated to the handle.
8881 * @token: metadata token (either for a class or a method)
8882 * @image: image where resides the metadata.
8885 mono_declsec_get_flags (MonoImage *image, guint32 token)
8887 guint32 index = mono_metadata_declsec_from_index (image, token);
8888 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
8893 for (i = index; i < t->rows; i++) {
8894 guint32 cols [MONO_DECL_SECURITY_SIZE];
8896 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
8897 if (cols [MONO_DECL_SECURITY_PARENT] != token)
8900 action = cols [MONO_DECL_SECURITY_ACTION];
8901 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
8902 result |= declsec_flags_map [action];
8904 g_assert_not_reached ();
8911 * Get the security actions (in the form of flags) associated with the specified method.
8913 * @method: The method for which we want the declarative security flags.
8914 * Return the declarative security flags for the method (only).
8916 * Note: To keep MonoMethod size down we do not cache the declarative security flags
8917 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
8920 mono_declsec_flags_from_method (MonoMethod *method)
8922 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
8923 /* FIXME: No cache (for the moment) */
8924 guint32 idx = find_method_index (method);
8925 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8926 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
8927 return mono_declsec_get_flags (method->klass->image, idx);
8933 * Get the security actions (in the form of flags) associated with the specified class.
8935 * @klass: The class for which we want the declarative security flags.
8936 * Return the declarative security flags for the class.
8938 * Note: We cache the flags inside the MonoClass structure as this will get
8939 * called very often (at least for each method).
8942 mono_declsec_flags_from_class (MonoClass *klass)
8944 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
8945 if (!klass->declsec_flags) {
8946 guint32 idx = mono_metadata_token_index (klass->type_token);
8947 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8948 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
8949 /* we cache the flags on classes */
8950 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
8952 return klass->declsec_flags;
8958 * Get the security actions (in the form of flags) associated with the specified assembly.
8960 * @assembly: The assembly for which we want the declarative security flags.
8961 * Return the declarative security flags for the assembly.
8964 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
8966 guint32 idx = 1; /* there is only one assembly */
8967 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8968 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
8969 return mono_declsec_get_flags (assembly->image, idx);
8974 * Fill actions for the specific index (which may either be an encoded class token or
8975 * an encoded method token) from the metadata image.
8976 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
8979 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions)
8981 MonoBoolean result = FALSE;
8983 guint32 cols [MONO_DECL_SECURITY_SIZE];
8984 int index = mono_metadata_declsec_from_index (image, token);
8987 t = &image->tables [MONO_TABLE_DECLSECURITY];
8988 for (i = index; i < t->rows; i++) {
8989 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
8991 if (cols [MONO_DECL_SECURITY_PARENT] != token)
8994 /* if present only replace (class) permissions with method permissions */
8995 /* if empty accept either class or method permissions */
8996 switch (cols [MONO_DECL_SECURITY_ACTION]) {
8997 case SECURITY_ACTION_DEMAND:
8998 if (!actions->demand.blob) {
8999 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9000 actions->demand.blob = (char*) (blob + 2);
9001 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9005 case SECURITY_ACTION_NONCASDEMAND:
9006 if (!actions->noncasdemand.blob) {
9007 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9008 actions->noncasdemand.blob = (char*) (blob + 2);
9009 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9013 case SECURITY_ACTION_DEMANDCHOICE:
9014 if (!actions->demandchoice.blob) {
9015 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9016 actions->demandchoice.blob = (char*) (blob + 2);
9017 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9028 * Collect all actions (that requires to generate code in mini) assigned for
9029 * the specified method.
9030 * Note: Don't use the content of actions if the function return FALSE.
9033 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9035 MonoImage *image = method->klass->image;
9036 MonoBoolean result = FALSE;
9039 /* quick exit if no declarative security is present in the metadata */
9040 if (!image->tables [MONO_TABLE_DECLSECURITY].rows)
9043 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9045 /* First we look for method-level attributes */
9046 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9047 guint32 idx = find_method_index (method);
9048 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9049 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9050 result = fill_actions_from_index (image, idx, demands);
9053 /* Next we fill holes with class-level attributes */
9054 /* Here we use (or create) the class declarative cache to look for demands */
9055 flags = mono_declsec_flags_from_class (method->klass);
9056 if (flags & (MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | MONO_DECLSEC_FLAG_DEMAND_CHOICE)) {
9057 guint32 idx = mono_metadata_token_index (method->klass->type_token);
9058 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9059 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9060 result |= fill_actions_from_index (image, idx, demands);
9063 /* The boolean return value is used as a shortcut in case nothing needs to
9064 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9069 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
9071 guint32 cols [MONO_DECL_SECURITY_SIZE];
9075 int index = mono_metadata_declsec_from_index (image, token);
9079 t = &image->tables [MONO_TABLE_DECLSECURITY];
9080 for (i = index; i < t->rows; i++) {
9081 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9083 /* shortcut - index are ordered */
9084 if (token != cols [MONO_DECL_SECURITY_PARENT])
9087 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
9088 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9089 entry->blob = (char*) (metadata + 2);
9090 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
9099 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
9101 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9102 guint32 idx = find_method_index (method);
9103 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9104 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9105 return get_declsec_action (method->klass->image, idx, action, entry);
9111 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
9114 guint32 flags = mono_declsec_flags_from_class (klass);
9115 if (declsec_flags_map [action] & flags) {
9116 guint32 idx = mono_metadata_token_index (klass->type_token);
9117 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9118 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9119 return get_declsec_action (klass->image, idx, action, entry);
9125 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
9127 guint32 idx = 1; /* there is only one assembly */
9128 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9129 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9131 return get_declsec_action (assembly->image, idx, action, entry);