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 (mono_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 mono_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->generic_type, 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->generic_type);
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 mono_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 = rmb->charset & 0xf;
1317 rmb->lasterr = rmb->charset & 0x40;
1318 rmb->native_cc = rmb->native_cc;
1319 rmb->dllentry = mb->dllentry;
1325 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1327 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1329 rmb->ilgen = mb->ilgen;
1330 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1331 rmb->parameters = mb->parameters;
1332 rmb->generic_params = NULL;
1333 rmb->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 mono_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->signature->is_inflated);
2466 imethod = (MonoMethodInflated *) method;
2467 declaring = imethod->declaring;
2469 sig = method_encode_signature (assembly, declaring->signature);
2470 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2472 if (!declaring->signature->generic_param_count)
2475 switch (mono_metadata_token_table (mtoken)) {
2476 case MONO_TABLE_MEMBERREF:
2477 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2479 case MONO_TABLE_METHOD:
2480 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2483 g_assert_not_reached ();
2486 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2488 if (assembly->save) {
2489 alloc_table (table, table->rows + 1);
2490 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2491 values [MONO_METHODSPEC_METHOD] = mtoken;
2492 values [MONO_METHODSPEC_SIGNATURE] = sig;
2495 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2502 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2504 MonoMethodInflated *imethod;
2507 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2511 g_assert (m->signature->is_inflated);
2512 imethod = (MonoMethodInflated *) m;
2514 if (imethod->declaring->signature->generic_param_count) {
2515 token = method_encode_methodspec (assembly, m);
2517 guint32 sig = method_encode_signature (
2518 assembly, imethod->declaring->signature);
2519 token = mono_image_get_memberref_token (
2520 assembly, &m->klass->byval_arg, m->name, sig);
2523 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2528 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2530 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2533 sig = method_encode_signature (assembly, imethod->declaring->signature);
2534 token = mono_image_get_memberref_token (
2535 assembly, &m->klass->byval_arg, m->name, sig);
2541 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2543 MonoDynamicTable *table;
2550 char *b = blob_size;
2554 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2555 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2556 * Because of this, we must not insert it into the `typeref' hash table.
2559 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2563 g_assert (tb->generic_params);
2564 klass = mono_class_from_mono_type (tb->type.type);
2566 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2567 encode_type (assembly, &klass->byval_arg, p, &p);
2569 count = mono_array_length (tb->generic_params);
2570 mono_metadata_encode_value (count, p, &p);
2571 for (i = 0; i < count; i++) {
2572 MonoReflectionGenericParam *gparam;
2574 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2576 encode_type (assembly, gparam->type.type, p, &p);
2579 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2580 if (assembly->save) {
2581 g_assert (p-sig < 128);
2582 mono_metadata_encode_value (p-sig, b, &b);
2583 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2584 alloc_table (table, table->rows + 1);
2585 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2586 values [MONO_TYPESPEC_SIGNATURE] = token;
2589 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2590 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2596 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2598 MonoDynamicTable *table;
2601 guint32 token, pclass, parent, sig;
2604 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2608 klass = mono_class_from_mono_type (fb->typeb->type);
2609 name = mono_string_to_utf8 (fb->name);
2611 sig = fieldref_encode_signature (assembly, fb->type->type);
2613 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2614 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2616 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2617 parent >>= MONO_TYPEDEFORREF_BITS;
2619 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2621 if (assembly->save) {
2622 alloc_table (table, table->rows + 1);
2623 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2624 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2625 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2626 values [MONO_MEMBERREF_SIGNATURE] = sig;
2629 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2631 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2636 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2644 char *b = blob_size;
2646 if (!assembly->save)
2650 g_assert (helper->type == 2);
2652 if (helper->arguments)
2653 nargs = mono_array_length (helper->arguments);
2657 size = 10 + (nargs * 10);
2659 p = buf = g_malloc (size);
2661 /* Encode calling convention */
2662 /* Change Any to Standard */
2663 if ((helper->call_conv & 0x03) == 0x03)
2664 helper->call_conv = 0x01;
2665 /* explicit_this implies has_this */
2666 if (helper->call_conv & 0x40)
2667 helper->call_conv &= 0x20;
2669 if (helper->call_conv == 0) { /* Unmanaged */
2670 *p = helper->unmanaged_call_conv - 1;
2673 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2674 if (helper->call_conv & 0x02) /* varargs */
2679 mono_metadata_encode_value (nargs, p, &p);
2680 encode_reflection_type (assembly, helper->return_type, p, &p);
2681 for (i = 0; i < nargs; ++i) {
2682 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2683 encode_reflection_type (assembly, pt, p, &p);
2686 g_assert (p - buf < size);
2687 mono_metadata_encode_value (p-buf, b, &b);
2688 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2695 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2698 MonoDynamicTable *table;
2701 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2702 idx = table->next_idx ++;
2704 alloc_table (table, table->rows);
2705 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2707 values [MONO_STAND_ALONE_SIGNATURE] =
2708 mono_reflection_encode_sighelper (assembly, helper);
2714 reflection_cc_to_file (int call_conv) {
2715 switch (call_conv & 0x3) {
2717 case 1: return MONO_CALL_DEFAULT;
2718 case 2: return MONO_CALL_VARARG;
2720 g_assert_not_reached ();
2727 MonoMethodSignature *sig;
2733 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2738 MonoMethodSignature *sig;
2741 name = mono_string_to_utf8 (m->name);
2742 nparams = mono_array_length (m->parameters);
2743 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2745 sig->sentinelpos = -1;
2746 sig->call_convention = reflection_cc_to_file (m->call_conv);
2747 sig->param_count = nparams;
2748 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2749 for (i = 0; i < nparams; ++i) {
2750 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2751 sig->params [i] = t->type;
2754 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2756 if (strcmp (name, am->name) == 0 &&
2757 mono_metadata_type_equal (am->parent, m->parent->type) &&
2758 mono_metadata_signature_equal (am->sig, sig)) {
2761 m->table_idx = am->token & 0xffffff;
2765 am = g_new0 (ArrayMethod, 1);
2768 am->parent = m->parent->type;
2769 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2770 method_encode_signature (assembly, sig));
2771 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2772 m->table_idx = am->token & 0xffffff;
2777 * Insert into the metadata tables all the info about the TypeBuilder tb.
2778 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2781 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2783 MonoDynamicTable *table;
2785 int i, is_object = 0, is_system = 0;
2788 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2789 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2790 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2791 n = mono_string_to_utf8 (tb->name);
2792 if (strcmp (n, "Object") == 0)
2794 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2796 n = mono_string_to_utf8 (tb->nspace);
2797 if (strcmp (n, "System") == 0)
2799 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2801 if (tb->parent && !(is_system && is_object) &&
2802 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2803 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2805 values [MONO_TYPEDEF_EXTENDS] = 0;
2807 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2808 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2811 * if we have explicitlayout or sequentiallayouts, output data in the
2812 * ClassLayout table.
2814 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2815 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2816 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2818 alloc_table (table, table->rows);
2819 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2820 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2821 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2822 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2825 /* handle interfaces */
2826 if (tb->interfaces) {
2827 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2829 table->rows += mono_array_length (tb->interfaces);
2830 alloc_table (table, table->rows);
2831 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2832 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2833 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2834 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2835 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2836 values += MONO_INTERFACEIMPL_SIZE;
2842 table = &assembly->tables [MONO_TABLE_FIELD];
2843 table->rows += tb->num_fields;
2844 alloc_table (table, table->rows);
2845 for (i = 0; i < tb->num_fields; ++i)
2846 mono_image_get_field_info (
2847 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2850 /* handle constructors */
2852 table = &assembly->tables [MONO_TABLE_METHOD];
2853 table->rows += mono_array_length (tb->ctors);
2854 alloc_table (table, table->rows);
2855 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2856 mono_image_get_ctor_info (domain,
2857 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2860 /* handle methods */
2862 table = &assembly->tables [MONO_TABLE_METHOD];
2863 table->rows += tb->num_methods;
2864 alloc_table (table, table->rows);
2865 for (i = 0; i < tb->num_methods; ++i)
2866 mono_image_get_method_info (
2867 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2870 /* Do the same with properties etc.. */
2871 if (tb->events && mono_array_length (tb->events)) {
2872 table = &assembly->tables [MONO_TABLE_EVENT];
2873 table->rows += mono_array_length (tb->events);
2874 alloc_table (table, table->rows);
2875 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2877 alloc_table (table, table->rows);
2878 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2879 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2880 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2881 for (i = 0; i < mono_array_length (tb->events); ++i)
2882 mono_image_get_event_info (
2883 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2885 if (tb->properties && mono_array_length (tb->properties)) {
2886 table = &assembly->tables [MONO_TABLE_PROPERTY];
2887 table->rows += mono_array_length (tb->properties);
2888 alloc_table (table, table->rows);
2889 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2891 alloc_table (table, table->rows);
2892 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2893 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2894 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2895 for (i = 0; i < mono_array_length (tb->properties); ++i)
2896 mono_image_get_property_info (
2897 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2900 /* handle generic parameters */
2901 if (tb->generic_params) {
2902 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2903 table->rows += mono_array_length (tb->generic_params);
2904 alloc_table (table, table->rows);
2905 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2906 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2908 mono_image_get_generic_param_info (
2909 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2913 mono_image_add_decl_security (assembly,
2914 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2917 MonoDynamicTable *ntable;
2919 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2920 ntable->rows += mono_array_length (tb->subtypes);
2921 alloc_table (ntable, ntable->rows);
2922 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2924 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2925 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2927 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2928 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2929 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2930 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2931 mono_string_to_utf8 (tb->name), tb->table_idx,
2932 ntable->next_idx, ntable->rows);*/
2933 values += MONO_NESTED_CLASS_SIZE;
2940 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2944 g_ptr_array_add (types, type);
2946 if (!type->subtypes)
2949 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2950 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2951 collect_types (types, subtype);
2956 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2958 if ((*type1)->table_idx < (*type2)->table_idx)
2961 if ((*type1)->table_idx > (*type2)->table_idx)
2968 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2973 for (i = 0; i < mono_array_length (pinfo); ++i) {
2974 MonoReflectionParamBuilder *pb;
2975 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2978 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2983 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2986 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2988 for (i = 0; i < tb->num_fields; ++i) {
2989 MonoReflectionFieldBuilder* fb;
2990 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2991 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2995 for (i = 0; i < mono_array_length (tb->events); ++i) {
2996 MonoReflectionEventBuilder* eb;
2997 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2998 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3001 if (tb->properties) {
3002 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3003 MonoReflectionPropertyBuilder* pb;
3004 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3005 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3009 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3010 MonoReflectionCtorBuilder* cb;
3011 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3012 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3013 params_add_cattrs (assembly, cb->pinfo);
3018 for (i = 0; i < tb->num_methods; ++i) {
3019 MonoReflectionMethodBuilder* mb;
3020 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3021 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3022 params_add_cattrs (assembly, mb->pinfo);
3027 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3028 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3033 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3036 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3038 /* no types in the module */
3042 for (i = 0; i < mb->num_types; ++i)
3043 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3047 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3049 MonoDynamicTable *table;
3053 char *b = blob_size;
3056 table = &assembly->tables [MONO_TABLE_FILE];
3058 alloc_table (table, table->rows);
3059 values = table->values + table->next_idx * MONO_FILE_SIZE;
3060 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3061 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3062 if (module->image->dynamic) {
3063 /* This depends on the fact that the main module is emitted last */
3064 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3065 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3068 path = g_strdup (module->image->name);
3070 mono_sha1_get_digest_from_file (path, hash);
3073 mono_metadata_encode_value (20, b, &b);
3074 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3075 mono_image_add_stream_data (&assembly->blob, hash, 20);
3080 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3082 MonoDynamicTable *table;
3086 table = &assembly->tables [MONO_TABLE_MODULE];
3087 mb->table_idx = table->next_idx ++;
3088 name = mono_string_to_utf8 (mb->module.name);
3089 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3091 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3094 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3095 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3096 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3100 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3101 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3103 MonoDynamicTable *table;
3107 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3108 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3111 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3113 alloc_table (table, table->rows);
3114 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3116 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3117 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3118 if (klass->nested_in)
3119 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3121 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3122 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3123 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3125 res = table->next_idx;
3129 /* Emit nested types */
3130 if (klass->nested_classes) {
3133 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3134 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3141 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3142 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3147 klass = mono_class_from_mono_type (tb->type.type);
3149 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3151 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3152 parent_index, assembly);
3156 * We need to do this ourselves since klass->nested_classes is not set up.
3159 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3160 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3165 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3166 guint32 module_index, MonoDynamicImage *assembly)
3168 MonoImage *image = module->image;
3172 t = &image->tables [MONO_TABLE_TYPEDEF];
3174 for (i = 0; i < t->rows; ++i) {
3175 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3177 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3178 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3182 #define align_pointer(base,p)\
3184 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3186 (p) += 4 - (__diff & 3);\
3190 compare_semantics (const void *a, const void *b)
3192 const guint32 *a_values = a;
3193 const guint32 *b_values = b;
3194 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3197 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3201 compare_custom_attrs (const void *a, const void *b)
3203 const guint32 *a_values = a;
3204 const guint32 *b_values = b;
3206 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3210 compare_field_marshal (const void *a, const void *b)
3212 const guint32 *a_values = a;
3213 const guint32 *b_values = b;
3215 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3219 compare_nested (const void *a, const void *b)
3221 const guint32 *a_values = a;
3222 const guint32 *b_values = b;
3224 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3228 compare_genericparam (const void *a, const void *b)
3230 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3231 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3233 if ((*b_entry)->owner == (*a_entry)->owner)
3235 (*a_entry)->gparam->type.type->data.generic_param->num -
3236 (*b_entry)->gparam->type.type->data.generic_param->num;
3238 return (*b_entry)->owner - (*a_entry)->owner;
3242 compare_declsecurity_attrs (const void *a, const void *b)
3244 const guint32 *a_values = a;
3245 const guint32 *b_values = b;
3247 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3251 pad_heap (MonoDynamicStream *sh)
3253 if (sh->index & 3) {
3254 int sz = 4 - (sh->index & 3);
3255 memset (sh->data + sh->index, 0, sz);
3262 MonoDynamicStream *stream;
3266 * build_compressed_metadata() fills in the blob of data that represents the
3267 * raw metadata as it will be saved in the PE file. The five streams are output
3268 * and the metadata tables are comnpressed from the guint32 array representation,
3269 * to the compressed on-disk format.
3272 build_compressed_metadata (MonoDynamicImage *assembly)
3274 MonoDynamicTable *table;
3276 guint64 valid_mask = 0;
3277 guint64 sorted_mask;
3278 guint32 heapt_size = 0;
3279 guint32 meta_size = 256; /* allow for header and other stuff */
3280 guint32 table_offset;
3281 guint32 ntables = 0;
3287 struct StreamDesc stream_desc [5];
3289 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3290 for (i = 0; i < assembly->gen_params->len; i++){
3291 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3292 write_generic_param_entry (assembly, entry);
3295 stream_desc [0].name = "#~";
3296 stream_desc [0].stream = &assembly->tstream;
3297 stream_desc [1].name = "#Strings";
3298 stream_desc [1].stream = &assembly->sheap;
3299 stream_desc [2].name = "#US";
3300 stream_desc [2].stream = &assembly->us;
3301 stream_desc [3].name = "#Blob";
3302 stream_desc [3].stream = &assembly->blob;
3303 stream_desc [4].name = "#GUID";
3304 stream_desc [4].stream = &assembly->guid;
3306 /* tables that are sorted */
3307 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3308 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3309 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3310 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3311 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3312 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3314 /* Compute table sizes */
3315 /* the MonoImage has already been created in mono_image_basic_init() */
3316 meta = &assembly->image;
3318 /* sizes should be multiple of 4 */
3319 pad_heap (&assembly->blob);
3320 pad_heap (&assembly->guid);
3321 pad_heap (&assembly->sheap);
3322 pad_heap (&assembly->us);
3324 /* Setup the info used by compute_sizes () */
3325 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3326 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3327 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3329 meta_size += assembly->blob.index;
3330 meta_size += assembly->guid.index;
3331 meta_size += assembly->sheap.index;
3332 meta_size += assembly->us.index;
3334 for (i=0; i < 64; ++i)
3335 meta->tables [i].rows = assembly->tables [i].rows;
3337 for (i = 0; i < 64; i++){
3338 if (meta->tables [i].rows == 0)
3340 valid_mask |= (guint64)1 << i;
3342 meta->tables [i].row_size = mono_metadata_compute_size (
3343 meta, i, &meta->tables [i].size_bitfield);
3344 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3346 heapt_size += 24; /* #~ header size */
3347 heapt_size += ntables * 4;
3348 /* make multiple of 4 */
3351 meta_size += heapt_size;
3352 meta->raw_metadata = g_malloc0 (meta_size);
3353 p = meta->raw_metadata;
3354 /* the metadata signature */
3355 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3356 /* version numbers and 4 bytes reserved */
3357 int16val = (guint16*)p;
3358 *int16val++ = GUINT16_TO_LE (1);
3359 *int16val = GUINT16_TO_LE (1);
3361 /* version string */
3362 int32val = (guint32*)p;
3363 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3365 memcpy (p, meta->version, strlen (meta->version));
3366 p += GUINT32_FROM_LE (*int32val);
3367 align_pointer (meta->raw_metadata, p);
3368 int16val = (guint16*)p;
3369 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3370 *int16val = GUINT16_TO_LE (5); /* number of streams */
3374 * write the stream info.
3376 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3377 table_offset += 3; table_offset &= ~3;
3379 assembly->tstream.index = heapt_size;
3380 for (i = 0; i < 5; ++i) {
3381 int32val = (guint32*)p;
3382 stream_desc [i].stream->offset = table_offset;
3383 *int32val++ = GUINT32_TO_LE (table_offset);
3384 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3385 table_offset += GUINT32_FROM_LE (*int32val);
3386 table_offset += 3; table_offset &= ~3;
3388 strcpy (p, stream_desc [i].name);
3389 p += strlen (stream_desc [i].name) + 1;
3390 align_pointer (meta->raw_metadata, p);
3393 * now copy the data, the table stream header and contents goes first.
3395 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3396 p = meta->raw_metadata + assembly->tstream.offset;
3397 int32val = (guint32*)p;
3398 *int32val = GUINT32_TO_LE (0); /* reserved */
3401 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3402 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3403 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3404 *p++ = 1; /* version */
3407 *p++ = 1; /* version */
3411 if (meta->idx_string_wide)
3413 if (meta->idx_guid_wide)
3415 if (meta->idx_blob_wide)
3418 *p++ = 1; /* reserved */
3419 int64val = (guint64*)p;
3420 *int64val++ = GUINT64_TO_LE (valid_mask);
3421 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3423 int32val = (guint32*)p;
3424 for (i = 0; i < 64; i++){
3425 if (meta->tables [i].rows == 0)
3427 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3429 p = (unsigned char*)int32val;
3431 /* sort the tables that still need sorting */
3432 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3434 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3435 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3437 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3438 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3440 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3441 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3443 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3444 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3445 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3447 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3449 /* compress the tables */
3450 for (i = 0; i < 64; i++){
3453 guint32 bitfield = meta->tables [i].size_bitfield;
3454 if (!meta->tables [i].rows)
3456 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3457 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3458 meta->tables [i].base = p;
3459 for (row = 1; row <= meta->tables [i].rows; ++row) {
3460 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3461 for (col = 0; col < assembly->tables [i].columns; ++col) {
3462 switch (mono_metadata_table_size (bitfield, col)) {
3464 *p++ = values [col];
3467 *p++ = values [col] & 0xff;
3468 *p++ = (values [col] >> 8) & 0xff;
3471 *p++ = values [col] & 0xff;
3472 *p++ = (values [col] >> 8) & 0xff;
3473 *p++ = (values [col] >> 16) & 0xff;
3474 *p++ = (values [col] >> 24) & 0xff;
3477 g_assert_not_reached ();
3481 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3484 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3485 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3486 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3487 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3488 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3490 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3494 * Some tables in metadata need to be sorted according to some criteria, but
3495 * when methods and fields are first created with reflection, they may be assigned a token
3496 * that doesn't correspond to the final token they will get assigned after the sorting.
3497 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3498 * with the reflection objects that represent them. Once all the tables are set up, the
3499 * reflection objects will contains the correct table index. fixup_method() will fixup the
3500 * tokens for the method with ILGenerator @ilgen.
3503 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3504 guint32 code_idx = GPOINTER_TO_UINT (value);
3505 MonoReflectionILTokenInfo *iltoken;
3506 MonoReflectionFieldBuilder *field;
3507 MonoReflectionCtorBuilder *ctor;
3508 MonoReflectionMethodBuilder *method;
3509 MonoReflectionTypeBuilder *tb;
3510 MonoReflectionArrayMethod *am;
3512 unsigned char *target;
3514 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3515 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3516 target = assembly->code.data + code_idx + iltoken->code_pos;
3517 switch (target [3]) {
3518 case MONO_TABLE_FIELD:
3519 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3520 field = (MonoReflectionFieldBuilder *)iltoken->member;
3521 idx = field->table_idx;
3522 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3523 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3524 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3526 g_assert_not_reached ();
3529 case MONO_TABLE_METHOD:
3530 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3531 method = (MonoReflectionMethodBuilder *)iltoken->member;
3532 idx = method->table_idx;
3533 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3534 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3535 idx = ctor->table_idx;
3536 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3537 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3538 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3539 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3541 g_assert_not_reached ();
3544 case MONO_TABLE_TYPEDEF:
3545 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3546 g_assert_not_reached ();
3547 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3548 idx = tb->table_idx;
3550 case MONO_TABLE_MEMBERREF:
3551 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3552 am = (MonoReflectionArrayMethod*)iltoken->member;
3553 idx = am->table_idx;
3554 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3555 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3556 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3557 g_assert (m->klass->generic_class);
3559 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3561 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3562 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3563 g_assert (f->generic_info);
3565 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3568 g_assert_not_reached ();
3571 case MONO_TABLE_METHODSPEC:
3572 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3573 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3574 g_assert (m->signature->generic_param_count);
3577 g_assert_not_reached ();
3581 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3583 target [0] = idx & 0xff;
3584 target [1] = (idx >> 8) & 0xff;
3585 target [2] = (idx >> 16) & 0xff;
3592 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3593 * value is not known when the table is emitted.
3596 fixup_cattrs (MonoDynamicImage *assembly)
3598 MonoDynamicTable *table;
3600 guint32 type, i, idx, token;
3603 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3605 for (i = 0; i < table->rows; ++i) {
3606 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3608 type = values [MONO_CUSTOM_ATTR_TYPE];
3609 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3610 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3611 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3612 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3615 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3616 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3617 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3618 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3625 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3627 MonoDynamicTable *table;
3631 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3633 alloc_table (table, table->rows);
3634 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3635 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3636 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3637 name = mono_string_to_utf8 (rsrc->name);
3638 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3640 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3645 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3647 MonoDynamicTable *table;
3651 char *b = blob_size;
3653 guint32 idx, offset;
3655 if (rsrc->filename) {
3656 name = mono_string_to_utf8 (rsrc->filename);
3657 sname = g_path_get_basename (name);
3659 table = &assembly->tables [MONO_TABLE_FILE];
3661 alloc_table (table, table->rows);
3662 values = table->values + table->next_idx * MONO_FILE_SIZE;
3663 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3664 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3667 mono_sha1_get_digest_from_file (name, hash);
3668 mono_metadata_encode_value (20, b, &b);
3669 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3670 mono_image_add_stream_data (&assembly->blob, hash, 20);
3672 idx = table->next_idx++;
3674 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3677 offset = mono_array_length (rsrc->data);
3678 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3679 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3680 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3681 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3685 * The entry should be emitted into the MANIFESTRESOURCE table of
3686 * the main module, but that needs to reference the FILE table
3687 * which isn't emitted yet.
3694 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3698 set_version_from_string (MonoString *version, guint32 *values)
3700 gchar *ver, *p, *str;
3703 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3704 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3705 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3706 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3709 ver = str = mono_string_to_utf8 (version);
3710 for (i = 0; i < 4; ++i) {
3711 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3717 /* handle Revision and Build */
3727 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3731 char *b = blob_size;
3736 len = mono_array_length (pkey);
3737 mono_metadata_encode_value (len, b, &b);
3738 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3739 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3741 /* need to get the actual value from the key type... */
3742 assembly->strong_name_size = 128;
3743 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3749 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3751 MonoDynamicTable *table;
3752 MonoDynamicImage *assembly;
3753 MonoReflectionAssemblyBuilder *assemblyb;
3758 guint32 module_index;
3760 assemblyb = moduleb->assemblyb;
3761 assembly = moduleb->dynamic_image;
3762 domain = mono_object_domain (assemblyb);
3764 /* Emit ASSEMBLY table */
3765 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3766 alloc_table (table, 1);
3767 values = table->values + MONO_ASSEMBLY_SIZE;
3768 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3769 name = mono_string_to_utf8 (assemblyb->name);
3770 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3772 if (assemblyb->culture) {
3773 name = mono_string_to_utf8 (assemblyb->culture);
3774 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3777 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3779 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3780 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3781 set_version_from_string (assemblyb->version, values);
3783 /* Emit FILE + EXPORTED_TYPE table */
3785 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3787 MonoReflectionModuleBuilder *file_module =
3788 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3789 if (file_module != moduleb) {
3790 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3792 if (file_module->types) {
3793 for (j = 0; j < file_module->num_types; ++j) {
3794 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3795 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3800 if (assemblyb->loaded_modules) {
3801 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3802 MonoReflectionModule *file_module =
3803 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3804 mono_image_fill_file_table (domain, file_module, assembly);
3806 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3810 /* Emit MANIFESTRESOURCE table */
3812 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3814 MonoReflectionModuleBuilder *file_module =
3815 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3816 /* The table for the main module is emitted later */
3817 if (file_module != moduleb) {
3819 if (file_module->resources) {
3820 int len = mono_array_length (file_module->resources);
3821 for (j = 0; j < len; ++j) {
3822 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3823 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3831 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3832 * for the modulebuilder @moduleb.
3833 * At the end of the process, method and field tokens are fixed up and the
3834 * on-disk compressed metadata representation is created.
3837 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3839 MonoDynamicTable *table;
3840 MonoDynamicImage *assembly;
3841 MonoReflectionAssemblyBuilder *assemblyb;
3846 assemblyb = moduleb->assemblyb;
3847 assembly = moduleb->dynamic_image;
3848 domain = mono_object_domain (assemblyb);
3850 if (assembly->text_rva)
3853 assembly->text_rva = START_TEXT_RVA;
3855 if (moduleb->is_main) {
3856 mono_image_emit_manifest (moduleb);
3859 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3860 table->rows = 1; /* .<Module> */
3862 alloc_table (table, table->rows);
3864 * Set the first entry.
3866 values = table->values + table->columns;
3867 values [MONO_TYPEDEF_FLAGS] = 0;
3868 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3869 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3870 values [MONO_TYPEDEF_EXTENDS] = 0;
3871 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3872 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3875 * handle global methods
3876 * FIXME: test what to do when global methods are defined in multiple modules.
3878 if (moduleb->global_methods) {
3879 table = &assembly->tables [MONO_TABLE_METHOD];
3880 table->rows += mono_array_length (moduleb->global_methods);
3881 alloc_table (table, table->rows);
3882 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3883 mono_image_get_method_info (
3884 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3886 if (moduleb->global_fields) {
3887 table = &assembly->tables [MONO_TABLE_FIELD];
3888 table->rows += mono_array_length (moduleb->global_fields);
3889 alloc_table (table, table->rows);
3890 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3891 mono_image_get_field_info (
3892 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3895 table = &assembly->tables [MONO_TABLE_MODULE];
3896 alloc_table (table, 1);
3897 mono_image_fill_module_table (domain, moduleb, assembly);
3901 /* Collect all types into a list sorted by their table_idx */
3902 GPtrArray *types = g_ptr_array_new ();
3905 for (i = 0; i < moduleb->num_types; ++i) {
3906 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3907 collect_types (types, type);
3910 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3911 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3912 table->rows += types->len;
3913 alloc_table (table, table->rows);
3915 for (i = 0; i < types->len; ++i) {
3916 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3917 mono_image_get_type_info (domain, type, assembly);
3919 g_ptr_array_free (types, TRUE);
3923 * table->rows is already set above and in mono_image_fill_module_table.
3925 /* add all the custom attributes at the end, once all the indexes are stable */
3926 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3928 /* CAS assembly permissions */
3929 if (assemblyb->permissions_minimum)
3930 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3931 if (assemblyb->permissions_optional)
3932 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3933 if (assemblyb->permissions_refused)
3934 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3936 module_add_cattrs (assembly, moduleb);
3939 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3940 fixup_cattrs (assembly);
3944 * mono_image_insert_string:
3945 * @module: module builder object
3948 * Insert @str into the user string stream of @module.
3951 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3953 MonoDynamicImage *assembly;
3958 MONO_ARCH_SAVE_REGS;
3960 if (!module->dynamic_image)
3961 mono_image_module_basic_init (module);
3963 assembly = module->dynamic_image;
3965 if (assembly->save) {
3966 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3967 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3968 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3970 char *swapped = g_malloc (2 * mono_string_length (str));
3971 const char *p = (const char*)mono_string_chars (str);
3973 swap_with_size (swapped, p, 2, mono_string_length (str));
3974 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3978 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3980 mono_image_add_stream_data (&assembly->us, "", 1);
3982 idx = assembly->us.index ++;
3985 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3987 return MONO_TOKEN_STRING | idx;
3991 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
3996 klass = obj->vtable->klass;
3997 if (strcmp (klass->name, "MonoMethod") == 0) {
3998 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3999 MonoMethodSignature *sig, *old;
4000 guint32 sig_token, parent;
4003 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
4005 nargs = mono_array_length (opt_param_types);
4006 old = method->signature;
4007 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4009 sig->hasthis = old->hasthis;
4010 sig->explicit_this = old->explicit_this;
4011 sig->call_convention = old->call_convention;
4012 sig->generic_param_count = old->generic_param_count;
4013 sig->param_count = old->param_count + nargs;
4014 sig->sentinelpos = old->param_count;
4015 sig->ret = old->ret;
4017 for (i = 0; i < old->param_count; i++)
4018 sig->params [i] = old->params [i];
4020 for (i = 0; i < nargs; i++) {
4021 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4022 sig->params [old->param_count + i] = rt->type;
4025 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4026 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4027 parent >>= MONO_TYPEDEFORREF_BITS;
4029 parent <<= MONO_MEMBERREF_PARENT_BITS;
4030 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4032 sig_token = method_encode_signature (assembly, sig);
4033 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4034 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4035 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4036 ReflectionMethodBuilder rmb;
4037 guint32 parent, sig;
4039 reflection_methodbuilder_from_method_builder (&rmb, mb);
4040 rmb.opt_types = opt_param_types;
4042 sig = method_builder_encode_signature (assembly, &rmb);
4044 parent = mono_image_create_token (assembly, obj, TRUE);
4045 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4047 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4048 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4050 token = mono_image_get_varargs_method_token (
4051 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4053 g_error ("requested method token for %s\n", klass->name);
4060 * mono_image_create_token:
4061 * @assembly: a dynamic assembly
4064 * Get a token to insert in the IL code stream for the given MemberInfo.
4065 * @obj can be one of:
4066 * ConstructorBuilder
4076 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4081 klass = obj->vtable->klass;
4082 if (strcmp (klass->name, "MethodBuilder") == 0) {
4083 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4085 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4086 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4088 token = mono_image_get_methodbuilder_token (assembly, mb);
4089 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4090 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4091 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4093 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4094 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4096 token = mono_image_get_ctorbuilder_token (assembly, mb);
4097 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4098 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4099 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4100 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4101 if (tb->generic_params) {
4102 token = mono_image_get_generic_field_token (assembly, fb);
4104 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4106 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4107 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4108 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4109 } else if (strcmp (klass->name, "MonoType") == 0 ||
4110 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4111 MonoReflectionType *tb = (MonoReflectionType *)obj;
4112 token = mono_metadata_token_from_dor (
4113 mono_image_typedef_or_ref (assembly, tb->type));
4114 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4115 MonoReflectionType *tb = (MonoReflectionType *)obj;
4116 token = mono_metadata_token_from_dor (
4117 mono_image_typedef_or_ref (assembly, tb->type));
4118 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4119 strcmp (klass->name, "MonoMethod") == 0) {
4120 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4121 if (m->method->signature->is_inflated) {
4122 if (create_methodspec)
4123 token = mono_image_get_methodspec_token (assembly, m->method);
4125 token = mono_image_get_inflated_method_token (assembly, m->method);
4126 } else if ((m->method->klass->image == &assembly->image) &&
4127 !m->method->klass->generic_class) {
4128 static guint32 method_table_idx = 0xffffff;
4129 if (m->method->klass->wastypebuilder) {
4130 /* we use the same token as the one that was assigned
4131 * to the Methodbuilder.
4132 * FIXME: do the equivalent for Fields.
4134 token = m->method->token;
4137 * Each token should have a unique index, but the indexes are
4138 * assigned by managed code, so we don't know about them. An
4139 * easy solution is to count backwards...
4141 method_table_idx --;
4142 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4145 token = mono_image_get_methodref_token (assembly, m->method);
4147 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4148 } else if (strcmp (klass->name, "MonoField") == 0) {
4149 MonoReflectionField *f = (MonoReflectionField *)obj;
4150 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4151 static guint32 field_table_idx = 0xffffff;
4153 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4155 token = mono_image_get_fieldref_token (assembly, f);
4157 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4158 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4159 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4160 token = mono_image_get_array_token (assembly, m);
4161 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4162 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4163 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4165 g_error ("requested token for %s\n", klass->name);
4168 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4174 guint32 import_lookup_table;
4178 guint32 import_address_table_rva;
4186 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4188 static MonoDynamicImage*
4189 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4191 static const guchar entrycode [16] = {0xff, 0x25, 0};
4192 MonoDynamicImage *image;
4195 const char *version = mono_get_runtime_version ();
4198 image = GC_MALLOC (sizeof (MonoDynamicImage));
4200 image = g_new0 (MonoDynamicImage, 1);
4203 /* keep in sync with image.c */
4204 image->image.name = assembly_name;
4205 image->image.assembly_name = image->image.name; /* they may be different */
4206 image->image.module_name = module_name;
4207 image->image.version = g_strdup (version);
4208 image->image.dynamic = TRUE;
4210 image->image.references = g_new0 (MonoAssembly*, 1);
4211 image->image.references [0] = NULL;
4213 mono_image_init (&image->image);
4215 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4216 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4217 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4218 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4219 image->handleref = g_hash_table_new (NULL, NULL);
4220 image->tokens = mono_g_hash_table_new (NULL, NULL);
4221 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4222 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4223 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4224 image->gen_params = g_ptr_array_new ();
4226 string_heap_init (&image->sheap);
4227 mono_image_add_stream_data (&image->us, "", 1);
4228 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4229 /* import tables... */
4230 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4231 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4232 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4233 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4234 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4235 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4236 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4237 stream_data_align (&image->code);
4239 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4241 for (i=0; i < 64; ++i) {
4242 image->tables [i].next_idx = 1;
4243 image->tables [i].columns = table_sizes [i];
4246 image->image.assembly = (MonoAssembly*)assembly;
4247 image->run = assembly->run;
4248 image->save = assembly->save;
4249 image->pe_kind = 0x1; /* ILOnly */
4250 image->machine = 0x14c; /* I386 */
4256 * mono_image_basic_init:
4257 * @assembly: an assembly builder object
4259 * Create the MonoImage that represents the assembly builder and setup some
4260 * of the helper hash table and the basic metadata streams.
4263 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4265 MonoDynamicAssembly *assembly;
4266 MonoDynamicImage *image;
4268 MONO_ARCH_SAVE_REGS;
4270 if (assemblyb->dynamic_assembly)
4274 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4276 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4279 assembly->assembly.dynamic = TRUE;
4280 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4281 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4282 if (assemblyb->culture)
4283 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4285 assembly->assembly.aname.culture = g_strdup ("");
4287 assembly->run = assemblyb->access != 2;
4288 assembly->save = assemblyb->access != 1;
4290 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4291 image->initial_image = TRUE;
4292 assembly->assembly.aname.name = image->image.name;
4293 assembly->assembly.image = &image->image;
4295 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4296 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4300 calc_section_size (MonoDynamicImage *assembly)
4304 /* alignment constraints */
4305 assembly->code.index += 3;
4306 assembly->code.index &= ~3;
4307 assembly->meta_size += 3;
4308 assembly->meta_size &= ~3;
4309 assembly->resources.index += 3;
4310 assembly->resources.index &= ~3;
4312 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4313 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4316 if (assembly->win32_res) {
4317 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4319 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4320 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4324 assembly->sections [MONO_SECTION_RELOC].size = 12;
4325 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4335 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4339 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4341 ResTreeNode *t1 = (ResTreeNode*)a;
4342 ResTreeNode *t2 = (ResTreeNode*)b;
4344 return t1->id - t2->id;
4348 * resource_tree_create:
4350 * Organize the resources into a resource tree.
4352 static ResTreeNode *
4353 resource_tree_create (MonoArray *win32_resources)
4355 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4359 tree = g_new0 (ResTreeNode, 1);
4361 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4362 MonoReflectionWin32Resource *win32_res =
4363 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4367 lang_node = g_new0 (ResTreeNode, 1);
4368 lang_node->id = win32_res->lang_id;
4369 lang_node->win32_res = win32_res;
4371 /* Create type node if neccesary */
4373 for (l = tree->children; l; l = l->next)
4374 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4375 type_node = (ResTreeNode*)l->data;
4380 type_node = g_new0 (ResTreeNode, 1);
4381 type_node->id = win32_res->res_type;
4384 * The resource types have to be sorted otherwise
4385 * Windows Explorer can't display the version information.
4387 tree->children = g_slist_insert_sorted (tree->children,
4388 type_node, resource_tree_compare_by_id);
4391 /* Create res node if neccesary */
4393 for (l = type_node->children; l; l = l->next)
4394 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4395 res_node = (ResTreeNode*)l->data;
4400 res_node = g_new0 (ResTreeNode, 1);
4401 res_node->id = win32_res->res_id;
4402 type_node->children = g_slist_append (type_node->children, res_node);
4405 res_node->children = g_slist_append (res_node->children, lang_node);
4412 * resource_tree_encode:
4414 * Encode the resource tree into the format used in the PE file.
4417 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4420 MonoPEResourceDir dir;
4421 MonoPEResourceDirEntry dir_entry;
4422 MonoPEResourceDataEntry data_entry;
4426 * For the format of the resource directory, see the article
4427 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4431 memset (&dir, 0, sizeof (dir));
4432 memset (&dir_entry, 0, sizeof (dir_entry));
4433 memset (&data_entry, 0, sizeof (data_entry));
4435 g_assert (sizeof (dir) == 16);
4436 g_assert (sizeof (dir_entry) == 8);
4437 g_assert (sizeof (data_entry) == 16);
4439 node->offset = p - begin;
4441 /* IMAGE_RESOURCE_DIRECTORY */
4442 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4444 memcpy (p, &dir, sizeof (dir));
4447 /* Reserve space for entries */
4449 p += sizeof (dir_entry) * dir.res_id_entries;
4451 /* Write children */
4452 for (l = node->children; l; l = l->next) {
4453 ResTreeNode *child = (ResTreeNode*)l->data;
4455 if (child->win32_res) {
4457 child->offset = p - begin;
4459 /* IMAGE_RESOURCE_DATA_ENTRY */
4460 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4461 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4463 memcpy (p, &data_entry, sizeof (data_entry));
4464 p += sizeof (data_entry);
4466 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4467 p += data_entry.rde_size;
4469 resource_tree_encode (child, begin, p, &p);
4473 /* IMAGE_RESOURCE_ENTRY */
4474 for (l = node->children; l; l = l->next) {
4475 ResTreeNode *child = (ResTreeNode*)l->data;
4476 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4478 dir_entry.is_dir = child->win32_res ? 0 : 1;
4479 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4481 memcpy (entries, &dir_entry, sizeof (dir_entry));
4482 entries += sizeof (dir_entry);
4489 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4494 MonoReflectionWin32Resource *win32_res;
4497 if (!assemblyb->win32_resources)
4501 * Resources are stored in a three level tree inside the PE file.
4502 * - level one contains a node for each type of resource
4503 * - level two contains a node for each resource
4504 * - level three contains a node for each instance of a resource for a
4505 * specific language.
4508 tree = resource_tree_create (assemblyb->win32_resources);
4510 /* Estimate the size of the encoded tree */
4512 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4513 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4514 size += mono_array_length (win32_res->res_data);
4516 /* Directory structure */
4517 size += mono_array_length (assemblyb->win32_resources) * 256;
4518 p = buf = g_malloc (size);
4520 resource_tree_encode (tree, p, p, &p);
4522 g_assert (p - buf < size);
4524 assembly->win32_res = g_malloc (p - buf);
4525 assembly->win32_res_size = p - buf;
4526 memcpy (assembly->win32_res, buf, p - buf);
4532 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4534 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4537 p += sizeof (MonoPEResourceDir);
4538 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4539 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4540 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4541 if (dir_entry->is_dir) {
4542 fixup_resource_directory (res_section, child, rva);
4544 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4545 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4548 p += sizeof (MonoPEResourceDirEntry);
4553 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4556 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4557 g_error ("WriteFile returned %d\n", GetLastError ());
4561 * mono_image_create_pefile:
4562 * @mb: a module builder object
4564 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4565 * assembly->pefile where it can be easily retrieved later in chunks.
4568 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4569 MonoMSDOSHeader *msdos;
4570 MonoDotNetHeader *header;
4571 MonoSectionTable *section;
4572 MonoCLIHeader *cli_header;
4573 guint32 size, image_size, virtual_base, text_offset;
4574 guint32 header_start, section_start, file_offset, virtual_offset;
4575 MonoDynamicImage *assembly;
4576 MonoReflectionAssemblyBuilder *assemblyb;
4577 MonoDynamicStream pefile_stream = {0};
4578 MonoDynamicStream *pefile = &pefile_stream;
4580 guint32 *rva, value;
4582 static const unsigned char msheader[] = {
4583 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4584 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4587 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4588 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4589 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4590 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4593 assemblyb = mb->assemblyb;
4595 mono_image_basic_init (assemblyb);
4596 assembly = mb->dynamic_image;
4598 assembly->pe_kind = assemblyb->pe_kind;
4599 assembly->machine = assemblyb->machine;
4600 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4601 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4603 mono_image_build_metadata (mb);
4605 if (mb->is_main && assemblyb->resources) {
4606 int len = mono_array_length (assemblyb->resources);
4607 for (i = 0; i < len; ++i)
4608 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4611 if (mb->resources) {
4612 int len = mono_array_length (mb->resources);
4613 for (i = 0; i < len; ++i)
4614 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4617 build_compressed_metadata (assembly);
4620 assembly_add_win32_resources (assembly, assemblyb);
4622 nsections = calc_section_size (assembly);
4624 /* The DOS header and stub */
4625 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4626 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4628 /* the dotnet header */
4629 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4631 /* the section tables */
4632 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4634 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4635 virtual_offset = VIRT_ALIGN;
4638 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4639 if (!assembly->sections [i].size)
4642 file_offset += FILE_ALIGN - 1;
4643 file_offset &= ~(FILE_ALIGN - 1);
4644 virtual_offset += VIRT_ALIGN - 1;
4645 virtual_offset &= ~(VIRT_ALIGN - 1);
4647 assembly->sections [i].offset = file_offset;
4648 assembly->sections [i].rva = virtual_offset;
4650 file_offset += assembly->sections [i].size;
4651 virtual_offset += assembly->sections [i].size;
4652 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4655 file_offset += FILE_ALIGN - 1;
4656 file_offset &= ~(FILE_ALIGN - 1);
4658 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4660 /* back-patch info */
4661 msdos = (MonoMSDOSHeader*)pefile->data;
4662 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4663 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4664 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4666 header = (MonoDotNetHeader*)(pefile->data + header_start);
4667 header->pesig [0] = 'P';
4668 header->pesig [1] = 'E';
4670 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4671 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4672 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4673 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4674 if (assemblyb->pekind == 1) {
4676 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4679 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4682 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4684 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4685 header->pe.pe_major = 6;
4686 header->pe.pe_minor = 0;
4687 size = assembly->sections [MONO_SECTION_TEXT].size;
4688 size += FILE_ALIGN - 1;
4689 size &= ~(FILE_ALIGN - 1);
4690 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4691 size = assembly->sections [MONO_SECTION_RSRC].size;
4692 size += FILE_ALIGN - 1;
4693 size &= ~(FILE_ALIGN - 1);
4694 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4695 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4696 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4697 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4698 /* pe_rva_entry_point always at the beginning of the text section */
4699 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4701 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4702 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4703 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4704 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4705 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4706 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4707 size = section_start;
4708 size += FILE_ALIGN - 1;
4709 size &= ~(FILE_ALIGN - 1);
4710 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4712 size += VIRT_ALIGN - 1;
4713 size &= ~(VIRT_ALIGN - 1);
4714 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4717 // Translate the PEFileKind value to the value expected by the Windows loader
4723 // PEFileKinds.Dll == 1
4724 // PEFileKinds.ConsoleApplication == 2
4725 // PEFileKinds.WindowApplication == 3
4728 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4729 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4731 if (assemblyb->pekind == 3)
4736 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4738 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4739 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4740 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4741 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4742 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4743 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4745 /* fill data directory entries */
4747 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4748 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4750 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4751 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4753 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4754 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4755 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4756 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4757 /* patch entrypoint name */
4758 if (assemblyb->pekind == 1)
4759 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4761 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4762 /* patch imported function RVA name */
4763 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4764 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4766 /* the import table */
4767 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4768 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4769 /* patch imported dll RVA name and other entries in the dir */
4770 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4771 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4772 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4773 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4774 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4775 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4777 p = (assembly->code.data + assembly->ilt_offset);
4778 value = (assembly->text_rva + assembly->imp_names_offset);
4779 *p++ = (value) & 0xff;
4780 *p++ = (value >> 8) & (0xff);
4781 *p++ = (value >> 16) & (0xff);
4782 *p++ = (value >> 24) & (0xff);
4784 /* the CLI header info */
4785 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4786 cli_header->ch_size = GUINT32_FROM_LE (72);
4787 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4788 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4789 if (assemblyb->entry_point) {
4790 guint32 table_idx = 0;
4791 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4792 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4793 table_idx = methodb->table_idx;
4795 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4797 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4799 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4801 /* The embedded managed resources */
4802 text_offset = assembly->text_rva + assembly->code.index;
4803 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4804 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4805 text_offset += assembly->resources.index;
4806 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4807 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4808 text_offset += assembly->meta_size;
4809 if (assembly->strong_name_size) {
4810 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4811 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4812 text_offset += assembly->strong_name_size;
4815 /* write the section tables and section content */
4816 section = (MonoSectionTable*)(pefile->data + section_start);
4817 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4818 static const char *section_names [] = {
4819 ".text", ".rsrc", ".reloc"
4821 if (!assembly->sections [i].size)
4823 strcpy (section->st_name, section_names [i]);
4824 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4825 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4826 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4827 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4828 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4829 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4830 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4834 checked_write_file (file, pefile->data, pefile->index);
4836 mono_dynamic_stream_reset (pefile);
4838 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4839 if (!assembly->sections [i].size)
4842 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4843 g_error ("SetFilePointer returned %d\n", GetLastError ());
4846 case MONO_SECTION_TEXT:
4847 /* patch entry point */
4848 p = (assembly->code.data + 2);
4849 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4850 *p++ = (value) & 0xff;
4851 *p++ = (value >> 8) & 0xff;
4852 *p++ = (value >> 16) & 0xff;
4853 *p++ = (value >> 24) & 0xff;
4855 checked_write_file (file, assembly->code.data, assembly->code.index);
4856 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4857 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4858 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4861 g_free (assembly->image.raw_metadata);
4863 case MONO_SECTION_RELOC: {
4867 guint16 type_and_offset;
4871 g_assert (sizeof (reloc) == 12);
4873 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4874 reloc.block_size = GUINT32_FROM_LE (12);
4877 * the entrypoint is always at the start of the text section
4878 * 3 is IMAGE_REL_BASED_HIGHLOW
4879 * 2 is patch_size_rva - text_rva
4881 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4884 checked_write_file (file, &reloc, sizeof (reloc));
4888 case MONO_SECTION_RSRC:
4889 if (assembly->win32_res) {
4891 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4892 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4893 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
4897 g_assert_not_reached ();
4901 /* check that the file is properly padded */
4902 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4903 g_error ("SetFilePointer returned %d\n", GetLastError ());
4904 if (! SetEndOfFile (file))
4905 g_error ("SetEndOfFile returned %d\n", GetLastError ());
4907 mono_dynamic_stream_reset (&assembly->code);
4908 mono_dynamic_stream_reset (&assembly->us);
4909 mono_dynamic_stream_reset (&assembly->blob);
4910 mono_dynamic_stream_reset (&assembly->guid);
4911 string_heap_free (&assembly->sheap);
4913 mono_g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
4914 mono_g_hash_table_destroy (assembly->blob_cache);
4917 MonoReflectionModule *
4918 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4922 MonoImageOpenStatus status;
4923 MonoDynamicAssembly *assembly;
4924 guint32 module_count;
4925 MonoImage **new_modules;
4927 name = mono_string_to_utf8 (fileName);
4929 image = mono_image_open (name, &status);
4932 if (status == MONO_IMAGE_ERROR_ERRNO)
4933 exc = mono_get_exception_file_not_found (fileName);
4935 exc = mono_get_exception_bad_image_format (name);
4937 mono_raise_exception (exc);
4942 assembly = ab->dynamic_assembly;
4943 image->assembly = (MonoAssembly*)assembly;
4945 module_count = image->assembly->image->module_count;
4946 new_modules = g_new0 (MonoImage *, module_count + 1);
4948 if (image->assembly->image->modules)
4949 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4950 new_modules [module_count] = image;
4952 g_free (image->assembly->image->modules);
4953 image->assembly->image->modules = new_modules;
4954 image->assembly->image->module_count ++;
4956 mono_assembly_load_references (image, &status);
4958 mono_image_close (image);
4959 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4962 return mono_module_get_object (mono_domain_get (), image);
4966 * We need to return always the same object for MethodInfo, FieldInfo etc..
4967 * but we need to consider the reflected type.
4968 * type uses a different hash, since it uses custom hash/equal functions.
4973 MonoClass *refclass;
4977 reflected_equal (gconstpointer a, gconstpointer b) {
4978 const ReflectedEntry *ea = a;
4979 const ReflectedEntry *eb = b;
4981 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4985 reflected_hash (gconstpointer a) {
4986 const ReflectedEntry *ea = a;
4987 return GPOINTER_TO_UINT (ea->item);
4990 #define CHECK_OBJECT(t,p,k) \
4996 mono_domain_lock (domain); \
4997 if (!domain->refobject_hash) \
4998 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4999 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5000 mono_domain_unlock (domain); \
5006 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5008 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5011 #define CACHE_OBJECT(p,o,k) \
5013 ReflectedEntry *e = ALLOC_REFENTRY; \
5015 e->refclass = (k); \
5016 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5017 mono_domain_unlock (domain); \
5021 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5023 /* this is done only once */
5024 mono_domain_lock (domain);
5025 CACHE_OBJECT (assembly, res, NULL);
5029 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5031 /* this is done only once */
5032 mono_domain_lock (domain);
5033 CACHE_OBJECT (module, res, NULL);
5037 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5039 MonoDynamicImage *image = moduleb->dynamic_image;
5040 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5043 * FIXME: we already created an image in mono_image_basic_init (), but
5044 * we don't know which module it belongs to, since that is only
5045 * determined at assembly save time.
5047 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5048 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5050 moduleb->module.image = &image->image;
5051 moduleb->dynamic_image = image;
5052 register_module (mono_object_domain (moduleb), moduleb, image);
5057 * mono_assembly_get_object:
5058 * @domain: an app domain
5059 * @assembly: an assembly
5061 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5063 MonoReflectionAssembly*
5064 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5066 static MonoClass *System_Reflection_Assembly;
5067 MonoReflectionAssembly *res;
5069 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5070 if (!System_Reflection_Assembly)
5071 System_Reflection_Assembly = mono_class_from_name (
5072 mono_defaults.corlib, "System.Reflection", "Assembly");
5073 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5074 res->assembly = assembly;
5075 CACHE_OBJECT (assembly, res, NULL);
5081 MonoReflectionModule*
5082 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5084 static MonoClass *System_Reflection_Module;
5085 MonoReflectionModule *res;
5088 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5089 if (!System_Reflection_Module)
5090 System_Reflection_Module = mono_class_from_name (
5091 mono_defaults.corlib, "System.Reflection", "Module");
5092 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5095 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5097 res->fqname = mono_string_new (domain, image->name);
5098 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5099 res->scopename = mono_string_new (domain, image->module_name);
5103 if (image->assembly->image == image) {
5104 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5107 g_assert (image->assembly->image->modules);
5109 for (i = 0; i < image->assembly->image->module_count; i++) {
5110 if (image->assembly->image->modules [i] == image)
5111 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5113 g_assert (res->token);
5116 mono_image_addref (image);
5118 CACHE_OBJECT (image, res, NULL);
5122 MonoReflectionModule*
5123 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5125 static MonoClass *System_Reflection_Module;
5126 MonoReflectionModule *res;
5127 MonoTableInfo *table;
5128 guint32 cols [MONO_FILE_SIZE];
5130 guint32 i, name_idx;
5133 if (!System_Reflection_Module)
5134 System_Reflection_Module = mono_class_from_name (
5135 mono_defaults.corlib, "System.Reflection", "Module");
5136 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5138 table = &image->tables [MONO_TABLE_FILE];
5139 g_assert (table_index < table->rows);
5140 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5143 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5144 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5146 /* Check whenever the row has a corresponding row in the moduleref table */
5147 table = &image->tables [MONO_TABLE_MODULEREF];
5148 for (i = 0; i < table->rows; ++i) {
5149 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5150 val = mono_metadata_string_heap (image, name_idx);
5151 if (strcmp (val, name) == 0)
5152 res->image = image->modules [i];
5155 res->fqname = mono_string_new (domain, name);
5156 res->name = mono_string_new (domain, name);
5157 res->scopename = mono_string_new (domain, name);
5158 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5159 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5165 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5167 if ((t1->type != t2->type) ||
5168 (t1->byref != t2->byref))
5172 case MONO_TYPE_VOID:
5173 case MONO_TYPE_BOOLEAN:
5174 case MONO_TYPE_CHAR:
5185 case MONO_TYPE_STRING:
5188 case MONO_TYPE_OBJECT:
5189 case MONO_TYPE_TYPEDBYREF:
5191 case MONO_TYPE_VALUETYPE:
5192 case MONO_TYPE_CLASS:
5193 case MONO_TYPE_SZARRAY:
5194 return t1->data.klass == t2->data.klass;
5196 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5197 case MONO_TYPE_ARRAY:
5198 if (t1->data.array->rank != t2->data.array->rank)
5200 return t1->data.array->eklass == t2->data.array->eklass;
5201 case MONO_TYPE_GENERICINST: {
5203 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5205 if (!mono_metadata_type_equal (t1->data.generic_class->generic_type, t2->data.generic_class->generic_type))
5207 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5208 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5214 case MONO_TYPE_MVAR:
5215 return t1->data.generic_param == t2->data.generic_param;
5217 g_error ("implement type compare for %0x!", t1->type);
5225 mymono_metadata_type_hash (MonoType *t1)
5231 hash |= t1->byref << 6; /* do not collide with t1->type values */
5233 case MONO_TYPE_VALUETYPE:
5234 case MONO_TYPE_CLASS:
5235 case MONO_TYPE_SZARRAY:
5236 /* check if the distribution is good enough */
5237 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5239 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5244 static MonoReflectionGenericClass*
5245 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5247 static MonoClass *System_Reflection_MonoGenericClass;
5248 MonoReflectionGenericClass *res;
5249 MonoGenericClass *gclass;
5252 if (!System_Reflection_MonoGenericClass) {
5253 System_Reflection_MonoGenericClass = mono_class_from_name (
5254 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5255 g_assert (System_Reflection_MonoGenericClass);
5258 gclass = geninst->data.generic_class;
5259 gklass = mono_class_from_mono_type (gclass->generic_type);
5261 mono_class_init (gclass->klass);
5263 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5265 res->type.type = geninst;
5266 if (gklass->wastypebuilder && gklass->reflection_info)
5267 res->generic_type = gklass->reflection_info;
5269 res->generic_type = mono_type_get_object (domain, gclass->generic_type);
5275 * mono_type_get_object:
5276 * @domain: an app domain
5279 * Return an System.MonoType object representing the type @type.
5282 mono_type_get_object (MonoDomain *domain, MonoType *type)
5284 MonoReflectionType *res;
5285 MonoClass *klass = mono_class_from_mono_type (type);
5287 mono_domain_lock (domain);
5288 if (!domain->type_hash)
5289 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5290 (GCompareFunc)mymono_metadata_type_equal);
5291 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5292 mono_domain_unlock (domain);
5295 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5296 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5297 mono_g_hash_table_insert (domain->type_hash, type, res);
5298 mono_domain_unlock (domain);
5301 if (klass->reflection_info && !klass->wastypebuilder) {
5302 /* g_assert_not_reached (); */
5303 /* should this be considered an error condition? */
5305 mono_domain_unlock (domain);
5306 return klass->reflection_info;
5309 mono_class_init (klass);
5310 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5312 mono_g_hash_table_insert (domain->type_hash, type, res);
5313 mono_domain_unlock (domain);
5318 * mono_method_get_object:
5319 * @domain: an app domain
5321 * @refclass: the reflected type (can be NULL)
5323 * Return an System.Reflection.MonoMethod object representing the method @method.
5325 MonoReflectionMethod*
5326 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5329 * We use the same C representation for methods and constructors, but the type
5330 * name in C# is different.
5334 MonoReflectionMethod *ret;
5337 refclass = method->klass;
5339 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5340 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5341 cname = "MonoCMethod";
5343 cname = "MonoMethod";
5344 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5346 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5347 ret->method = method;
5348 ret->name = mono_string_new (domain, method->name);
5349 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5350 CACHE_OBJECT (method, ret, refclass);
5355 * mono_field_get_object:
5356 * @domain: an app domain
5360 * Return an System.Reflection.MonoField object representing the field @field
5363 MonoReflectionField*
5364 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5366 MonoReflectionField *res;
5369 CHECK_OBJECT (MonoReflectionField *, field, klass);
5370 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5371 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5374 res->name = mono_string_new (domain, field->name);
5375 if (field->generic_info)
5376 res->attrs = field->generic_info->generic_type->attrs;
5378 res->attrs = field->type->attrs;
5379 res->type = mono_type_get_object (domain, field->type);
5380 CACHE_OBJECT (field, res, klass);
5385 * mono_property_get_object:
5386 * @domain: an app domain
5388 * @property: a property
5390 * Return an System.Reflection.MonoProperty object representing the property @property
5393 MonoReflectionProperty*
5394 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5396 MonoReflectionProperty *res;
5399 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5400 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5401 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5403 res->property = property;
5404 CACHE_OBJECT (property, res, klass);
5409 * mono_event_get_object:
5410 * @domain: an app domain
5414 * Return an System.Reflection.MonoEvent object representing the event @event
5417 MonoReflectionEvent*
5418 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5420 MonoReflectionEvent *res;
5423 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5424 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5425 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5428 CACHE_OBJECT (event, res, klass);
5433 * mono_param_get_objects:
5434 * @domain: an app domain
5437 * Return an System.Reflection.ParameterInfo array object representing the parameters
5438 * in the method @method.
5441 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5443 static MonoClass *System_Reflection_ParameterInfo;
5444 MonoArray *res = NULL;
5445 MonoReflectionMethod *member = NULL;
5446 MonoReflectionParameter *param = NULL;
5447 char **names, **blobs = NULL;
5448 MonoObject *dbnull = mono_get_dbnull_object (domain);
5449 MonoMarshalSpec **mspecs;
5452 if (!System_Reflection_ParameterInfo)
5453 System_Reflection_ParameterInfo = mono_class_from_name (
5454 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5456 if (!method->signature->param_count)
5457 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5459 /* Note: the cache is based on the address of the signature into the method
5460 * since we already cache MethodInfos with the method as keys.
5462 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5464 member = mono_method_get_object (domain, method, NULL);
5465 names = g_new (char *, method->signature->param_count);
5466 mono_method_get_param_names (method, (const char **) names);
5468 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5469 mono_method_get_marshal_info (method, mspecs);
5471 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5472 for (i = 0; i < method->signature->param_count; ++i) {
5473 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5474 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5475 param->MemberImpl = (MonoObject*)member;
5476 param->NameImpl = mono_string_new (domain, names [i]);
5477 param->PositionImpl = i;
5478 param->AttrsImpl = method->signature->params [i]->attrs;
5480 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5481 param->DefaultValueImpl = dbnull;
5483 MonoType *type = param->ClassImpl->type;
5486 blobs = g_new0 (char *, method->signature->param_count);
5487 get_default_param_value_blobs (method, blobs);
5490 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5492 if (!param->DefaultValueImpl) {
5493 param->DefaultValueImpl = dbnull;
5498 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5500 mono_array_set (res, gpointer, i, param);
5505 for (i = method->signature->param_count; i >= 0; i--)
5507 mono_metadata_free_marshal_spec (mspecs [i]);
5510 CACHE_OBJECT (&(method->signature), res, NULL);
5515 * mono_method_body_get_object:
5516 * @domain: an app domain
5519 * Return an System.Reflection.MethodBody object representing the method @method.
5521 MonoReflectionMethodBody*
5522 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5524 static MonoClass *System_Reflection_MethodBody = NULL;
5525 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5526 MonoReflectionMethodBody *ret;
5527 MonoMethodNormal *mn;
5528 MonoMethodHeader *header;
5531 if (!System_Reflection_MethodBody)
5532 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5533 if (!System_Reflection_LocalVariableInfo)
5534 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5536 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5538 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5539 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5541 mn = (MonoMethodNormal *)method;
5542 header = mono_method_get_header (method);
5544 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5545 /* FIXME: Other fields */
5546 ret->init_locals = header->init_locals;
5547 ret->max_stack = header->max_stack;
5548 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5549 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5550 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5551 for (i = 0; i < header->num_locals; ++i) {
5552 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5553 info->local_type = mono_type_get_object (domain, header->locals [i]);
5554 info->is_pinned = header->locals [i]->pinned;
5555 info->local_index = 0;
5558 CACHE_OBJECT (method, ret, NULL);
5563 mono_get_dbnull_object (MonoDomain *domain)
5567 static MonoClassField *dbnull_value_field = NULL;
5569 if (!dbnull_value_field) {
5570 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5571 mono_class_init (klass);
5572 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5573 g_assert (dbnull_value_field);
5575 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5582 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5584 guint32 param_index, i, lastp, crow = 0;
5585 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5588 MonoClass *klass = method->klass;
5589 MonoImage *image = klass->image;
5590 MonoMethodSignature *methodsig = method->signature;
5592 MonoTableInfo *constt;
5593 MonoTableInfo *methodt;
5594 MonoTableInfo *paramt;
5596 if (!methodsig->param_count)
5599 if (klass->generic_class) {
5600 return; /* FIXME - ??? */
5603 mono_class_init (klass);
5605 if (klass->image->dynamic) {
5606 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5607 if (aux && aux->param_defaults)
5608 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5612 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5613 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5614 constt = &image->tables [MONO_TABLE_CONSTANT];
5616 for (i = 0; i < klass->method.count; ++i) {
5617 if (method == klass->methods [i]) {
5618 idx = klass->method.first + i;
5623 g_assert (idx != -1);
5625 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5626 if (idx + 1 < methodt->rows)
5627 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5629 lastp = paramt->rows + 1;
5631 for (i = param_index; i < lastp; ++i) {
5634 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5635 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5637 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5640 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5645 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5646 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5653 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5662 klass = mono_class_from_mono_type (type);
5663 if (klass->valuetype) {
5664 object = mono_object_new (domain, klass);
5665 retval = ((gchar *) object + sizeof (MonoObject));
5670 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5677 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5681 memset (assembly, 0, sizeof (MonoAssemblyName));
5683 assembly->culture = "";
5684 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5686 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5689 while (g_ascii_isspace (*p) || *p == ',') {
5698 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5700 assembly->major = strtoul (p, &s, 10);
5701 if (s == p || *s != '.')
5704 assembly->minor = strtoul (p, &s, 10);
5705 if (s == p || *s != '.')
5708 assembly->build = strtoul (p, &s, 10);
5709 if (s == p || *s != '.')
5712 assembly->revision = strtoul (p, &s, 10);
5716 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5718 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5719 assembly->culture = "";
5722 assembly->culture = p;
5723 while (*p && *p != ',') {
5727 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5729 if (strncmp (p, "null", 4) == 0) {
5734 while (*p && *p != ',') {
5737 len = (p - start + 1);
5738 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5739 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5740 g_strlcpy (assembly->public_key_token, start, len);
5743 while (*p && *p != ',')
5747 while (g_ascii_isspace (*p) || *p == ',') {
5761 * mono_reflection_parse_type:
5764 * Parse a type name as accepted by the GetType () method and output the info
5765 * extracted in the info structure.
5766 * the name param will be mangled, so, make a copy before passing it to this function.
5767 * The fields in info will be valid until the memory pointed to by name is valid.
5769 * See also mono_type_get_name () below.
5771 * Returns: 0 on parse error.
5774 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5776 char *start, *p, *w, *last_point, *startn;
5777 int in_modifiers = 0;
5778 int isbyref = 0, rank;
5780 start = p = w = name;
5782 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5783 info->name = info->name_space = NULL;
5784 info->nested = NULL;
5785 info->modifiers = NULL;
5787 /* last_point separates the namespace from the name */
5793 *p = 0; /* NULL terminate the name */
5795 info->nested = g_list_append (info->nested, startn);
5796 /* we have parsed the nesting namespace + name */
5800 info->name_space = start;
5802 info->name = last_point + 1;
5804 info->name_space = (char *)"";
5830 info->name_space = start;
5832 info->name = last_point + 1;
5834 info->name_space = (char *)"";
5841 if (isbyref) /* only one level allowed by the spec */
5844 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5848 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5859 else if (*p != '*') /* '*' means unknown lower bound */
5865 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5870 if (g_ascii_isspace (*p)) {
5877 return 0; /* missing assembly name */
5878 if (!assembly_name_to_aname (&info->assembly, p))
5885 if (info->assembly.name)
5888 *w = 0; /* terminate class name */
5889 if (!info->name || !*info->name)
5891 /* add other consistency checks */
5896 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5903 image = mono_defaults.corlib;
5906 klass = mono_class_from_name_case (image, info->name_space, info->name);
5908 klass = mono_class_from_name (image, info->name_space, info->name);
5911 for (mod = info->nested; mod; mod = mod->next) {
5914 mono_class_init (klass);
5915 nested = klass->nested_classes;
5918 klass = nested->data;
5920 if (g_strcasecmp (klass->name, mod->data) == 0)
5923 if (strcmp (klass->name, mod->data) == 0)
5927 nested = nested->next;
5934 mono_class_init (klass);
5935 for (mod = info->modifiers; mod; mod = mod->next) {
5936 modval = GPOINTER_TO_UINT (mod->data);
5937 if (!modval) { /* byref: must be last modifier */
5938 return &klass->this_arg;
5939 } else if (modval == -1) {
5940 klass = mono_ptr_class_get (&klass->byval_arg);
5941 } else { /* array rank */
5942 klass = mono_array_class_get (klass, modval);
5944 mono_class_init (klass);
5947 return &klass->byval_arg;
5951 * mono_reflection_get_type:
5952 * @image: a metadata context
5953 * @info: type description structure
5954 * @ignorecase: flag for case-insensitive string compares
5955 * @type_resolve: whenever type resolve was already tried
5957 * Build a MonoType from the type description in @info.
5962 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5965 MonoReflectionAssembly *assembly;
5969 type = mono_reflection_get_type_internal (image, info, ignorecase);
5972 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5979 *type_resolve = TRUE;
5982 /* Reconstruct the type name */
5983 fullName = g_string_new ("");
5984 if (info->name_space && (info->name_space [0] != '\0'))
5985 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5987 g_string_printf (fullName, info->name);
5988 for (mod = info->nested; mod; mod = mod->next)
5989 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5991 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5993 if (assembly->assembly->dynamic) {
5994 /* Enumerate all modules */
5995 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5999 if (abuilder->modules) {
6000 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6001 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6002 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6008 if (!type && abuilder->loaded_modules) {
6009 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6010 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6011 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6018 type = mono_reflection_get_type_internal (assembly->assembly->image,
6021 g_string_free (fullName, TRUE);
6026 * mono_reflection_type_from_name:
6028 * @image: a metadata context (can be NULL).
6030 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6031 * it defaults to get the type from @image or, if @image is NULL or loading
6032 * from it fails, uses corlib.
6036 mono_reflection_type_from_name (char *name, MonoImage *image)
6039 MonoTypeNameParse info;
6040 MonoAssembly *assembly;
6042 gboolean type_resolve = FALSE;
6044 /* Make a copy since parse_type modifies its argument */
6045 tmp = g_strdup (name);
6047 /*g_print ("requested type %s\n", str);*/
6048 if (!mono_reflection_parse_type (tmp, &info)) {
6050 g_list_free (info.modifiers);
6051 g_list_free (info.nested);
6055 if (info.assembly.name) {
6056 assembly = mono_assembly_loaded (&info.assembly);
6058 /* then we must load the assembly ourselve - see #60439 */
6059 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6062 g_list_free (info.modifiers);
6063 g_list_free (info.nested);
6067 image = assembly->image;
6068 } else if (image == NULL) {
6069 image = mono_defaults.corlib;
6072 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6073 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6074 image = mono_defaults.corlib;
6075 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6079 g_list_free (info.modifiers);
6080 g_list_free (info.nested);
6085 * mono_reflection_get_token:
6087 * Return the metadata token of OBJ which should be an object
6088 * representing a metadata element.
6091 mono_reflection_get_token (MonoObject *obj)
6096 klass = obj->vtable->klass;
6098 if (strcmp (klass->name, "MethodBuilder") == 0) {
6099 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6101 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6102 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6103 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6105 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6106 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6107 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6108 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6109 if (tb->generic_params) {
6110 g_assert_not_reached ();
6112 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6114 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6115 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6116 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6117 } else if (strcmp (klass->name, "MonoType") == 0) {
6118 MonoReflectionType *tb = (MonoReflectionType *)obj;
6119 token = mono_class_from_mono_type (tb->type)->type_token;
6120 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6121 strcmp (klass->name, "MonoMethod") == 0) {
6122 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6123 if (m->method->signature->is_inflated) {
6124 g_assert_not_reached ();
6125 } else if (m->method->signature->generic_param_count) {
6126 g_assert_not_reached ();
6127 } else if (m->method->klass->generic_class) {
6128 g_assert_not_reached ();
6130 token = m->method->token;
6132 } else if (strcmp (klass->name, "MonoField") == 0) {
6133 MonoReflectionField *f = (MonoReflectionField*)obj;
6135 token = mono_class_get_field_token (f->field);
6136 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6137 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6139 token = mono_class_get_property_token (p->property);
6140 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6141 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6143 token = mono_class_get_event_token (p->event);
6144 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6145 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6147 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6148 } else if (strcmp (klass->name, "Module") == 0) {
6149 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6152 } else if (strcmp (klass->name, "Assembly") == 0) {
6153 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6155 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6156 MonoException *ex = mono_get_exception_not_implemented (msg);
6158 mono_raise_exception (ex);
6165 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6167 int slen, type = t->type;
6172 case MONO_TYPE_BOOLEAN: {
6173 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6178 case MONO_TYPE_CHAR:
6180 case MONO_TYPE_I2: {
6181 guint16 *val = g_malloc (sizeof (guint16));
6186 #if SIZEOF_VOID_P == 4
6192 case MONO_TYPE_I4: {
6193 guint32 *val = g_malloc (sizeof (guint32));
6198 #if SIZEOF_VOID_P == 8
6199 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6204 case MONO_TYPE_I8: {
6205 guint64 *val = g_malloc (sizeof (guint64));
6210 case MONO_TYPE_VALUETYPE:
6211 if (t->data.klass->enumtype) {
6212 type = t->data.klass->enum_basetype->type;
6215 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6218 case MONO_TYPE_STRING:
6219 if (*p == (char)0xFF) {
6223 slen = mono_metadata_decode_value (p, &p);
6225 return mono_string_new_len (mono_domain_get (), p, slen);
6226 case MONO_TYPE_CLASS: {
6229 if (*p == (char)0xFF) {
6234 slen = mono_metadata_decode_value (p, &p);
6235 n = g_memdup (p, slen + 1);
6237 t = mono_reflection_type_from_name (n, image);
6239 g_warning ("Cannot load type '%s'", n);
6243 return mono_type_get_object (mono_domain_get (), t);
6247 case MONO_TYPE_OBJECT: {
6250 MonoClass *subc = NULL;
6255 } else if (subt == 0x0E) {
6256 type = MONO_TYPE_STRING;
6258 } else if (subt == 0x55) {
6261 slen = mono_metadata_decode_value (p, &p);
6262 n = g_memdup (p, slen + 1);
6264 t = mono_reflection_type_from_name (n, image);
6266 g_warning ("Cannot load type '%s'", n);
6269 subc = mono_class_from_mono_type (t);
6270 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6271 MonoType simple_type = {{0}};
6272 simple_type.type = subt;
6273 subc = mono_class_from_mono_type (&simple_type);
6275 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6277 val = load_cattr_value (image, &subc->byval_arg, p, end);
6278 obj = mono_object_new (mono_domain_get (), subc);
6279 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6283 case MONO_TYPE_SZARRAY: {
6285 guint32 i, alen, basetype;
6288 if (alen == 0xffffffff) {
6292 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6293 basetype = t->data.klass->byval_arg.type;
6298 case MONO_TYPE_BOOLEAN:
6299 for (i = 0; i < alen; i++) {
6300 MonoBoolean val = *p++;
6301 mono_array_set (arr, MonoBoolean, i, val);
6304 case MONO_TYPE_CHAR:
6307 for (i = 0; i < alen; i++) {
6308 guint16 val = read16 (p);
6309 mono_array_set (arr, guint16, i, val);
6316 for (i = 0; i < alen; i++) {
6317 guint32 val = read32 (p);
6318 mono_array_set (arr, guint32, i, val);
6325 for (i = 0; i < alen; i++) {
6326 guint64 val = read64 (p);
6327 mono_array_set (arr, guint64, i, val);
6331 case MONO_TYPE_CLASS:
6332 case MONO_TYPE_OBJECT:
6333 case MONO_TYPE_STRING:
6334 for (i = 0; i < alen; i++) {
6335 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6336 mono_array_set (arr, gpointer, i, item);
6340 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6346 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6352 type_is_reference (MonoType *type)
6354 switch (type->type) {
6355 case MONO_TYPE_BOOLEAN:
6356 case MONO_TYPE_CHAR:
6369 case MONO_TYPE_VALUETYPE:
6377 free_param_data (MonoMethodSignature *sig, void **params) {
6379 for (i = 0; i < sig->param_count; ++i) {
6380 if (!type_is_reference (sig->params [i]))
6381 g_free (params [i]);
6386 * Find the method index in the metadata methodDef table.
6387 * Later put these three helper methods in metadata and export them.
6390 find_method_index (MonoMethod *method) {
6391 MonoClass *klass = method->klass;
6394 for (i = 0; i < klass->method.count; ++i) {
6395 if (method == klass->methods [i])
6396 return klass->method.first + 1 + i;
6402 * Find the field index in the metadata FieldDef table.
6405 find_field_index (MonoClass *klass, MonoClassField *field) {
6408 for (i = 0; i < klass->field.count; ++i) {
6409 if (field == &klass->fields [i])
6410 return klass->field.first + 1 + i;
6416 * Find the property index in the metadata Property table.
6419 find_property_index (MonoClass *klass, MonoProperty *property) {
6422 for (i = 0; i < klass->property.count; ++i) {
6423 if (property == &klass->properties [i])
6424 return klass->property.first + 1 + i;
6430 * Find the event index in the metadata Event table.
6433 find_event_index (MonoClass *klass, MonoEvent *event) {
6436 for (i = 0; i < klass->event.count; ++i) {
6437 if (event == &klass->events [i])
6438 return klass->event.first + 1 + i;
6444 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6446 const char *p = data;
6448 guint32 i, j, num_named;
6452 mono_class_init (method->klass);
6455 attr = mono_object_new (mono_domain_get (), method->klass);
6456 mono_runtime_invoke (method, attr, NULL, NULL);
6460 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6463 /*g_print ("got attr %s\n", method->klass->name);*/
6465 params = g_new (void*, method->signature->param_count);
6469 for (i = 0; i < method->signature->param_count; ++i) {
6470 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6474 attr = mono_object_new (mono_domain_get (), method->klass);
6475 mono_runtime_invoke (method, attr, params, NULL);
6476 free_param_data (method->signature, params);
6478 num_named = read16 (named);
6480 for (j = 0; j < num_named; j++) {
6482 char *name, named_type, data_type;
6483 named_type = *named++;
6484 data_type = *named++; /* type of data */
6485 if (data_type == 0x55) {
6488 type_len = mono_metadata_decode_blob_size (named, &named);
6489 type_name = g_malloc (type_len + 1);
6490 memcpy (type_name, named, type_len);
6491 type_name [type_len] = 0;
6493 /* FIXME: lookup the type and check type consistency */
6494 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6495 /* this seems to be the type of the element of the array */
6496 /* g_print ("skipping 0x%02x after prop\n", *named); */
6499 name_len = mono_metadata_decode_blob_size (named, &named);
6500 name = g_malloc (name_len + 1);
6501 memcpy (name, named, name_len);
6502 name [name_len] = 0;
6504 if (named_type == 0x53) {
6505 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6506 void *val = load_cattr_value (image, field->type, named, &named);
6507 mono_field_set_value (attr, field, val);
6508 if (!type_is_reference (field->type))
6510 } else if (named_type == 0x54) {
6513 MonoType *prop_type;
6515 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6516 /* can we have more that 1 arg in a custom attr named property? */
6517 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6518 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6519 mono_property_set_value (prop, attr, pparams, NULL);
6520 if (!type_is_reference (prop_type))
6521 g_free (pparams [0]);
6530 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6537 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6538 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6539 for (i = 0; i < cinfo->num_attrs; ++i) {
6540 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6541 mono_array_set (result, gpointer, i, attr);
6547 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6549 guint32 mtoken, i, len;
6550 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6552 MonoCustomAttrInfo *ainfo;
6553 GList *tmp, *list = NULL;
6556 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6558 i = mono_metadata_custom_attrs_from_index (image, idx);
6562 while (i < ca->rows) {
6563 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6565 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6568 len = g_list_length (list);
6571 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6572 ainfo->num_attrs = len;
6573 ainfo->image = image;
6574 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6575 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6576 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6577 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6578 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6579 mtoken |= MONO_TOKEN_METHOD_DEF;
6581 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6582 mtoken |= MONO_TOKEN_MEMBER_REF;
6585 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6588 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6589 if (!ainfo->attrs [i].ctor)
6590 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6591 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6592 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6593 ainfo->attrs [i].data = data;
6601 mono_custom_attrs_from_method (MonoMethod *method)
6603 MonoCustomAttrInfo *cinfo;
6606 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6608 idx = find_method_index (method);
6609 idx <<= MONO_CUSTOM_ATTR_BITS;
6610 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6611 return mono_custom_attrs_from_index (method->klass->image, idx);
6615 mono_custom_attrs_from_class (MonoClass *klass)
6617 MonoCustomAttrInfo *cinfo;
6620 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6622 idx = mono_metadata_token_index (klass->type_token);
6623 idx <<= MONO_CUSTOM_ATTR_BITS;
6624 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6625 return mono_custom_attrs_from_index (klass->image, idx);
6629 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6631 MonoCustomAttrInfo *cinfo;
6634 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6636 idx = 1; /* there is only one assembly */
6637 idx <<= MONO_CUSTOM_ATTR_BITS;
6638 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6639 return mono_custom_attrs_from_index (assembly->image, idx);
6642 static MonoCustomAttrInfo*
6643 mono_custom_attrs_from_module (MonoImage *image)
6645 MonoCustomAttrInfo *cinfo;
6648 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6650 idx = 1; /* there is only one module */
6651 idx <<= MONO_CUSTOM_ATTR_BITS;
6652 idx |= MONO_CUSTOM_ATTR_MODULE;
6653 return mono_custom_attrs_from_index (image, idx);
6657 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6659 MonoCustomAttrInfo *cinfo;
6662 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6664 idx = find_property_index (klass, property);
6665 idx <<= MONO_CUSTOM_ATTR_BITS;
6666 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6667 return mono_custom_attrs_from_index (klass->image, idx);
6671 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6673 MonoCustomAttrInfo *cinfo;
6676 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6678 idx = find_event_index (klass, event);
6679 idx <<= MONO_CUSTOM_ATTR_BITS;
6680 idx |= MONO_CUSTOM_ATTR_EVENT;
6681 return mono_custom_attrs_from_index (klass->image, idx);
6685 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6687 MonoCustomAttrInfo *cinfo;
6690 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6692 idx = find_field_index (klass, field);
6693 idx <<= MONO_CUSTOM_ATTR_BITS;
6694 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6695 return mono_custom_attrs_from_index (klass->image, idx);
6699 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6702 guint32 i, idx, method_index;
6703 guint32 param_list, param_last, param_pos, found;
6705 MonoReflectionMethodAux *aux;
6707 if (method->klass->image->dynamic) {
6708 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6709 if (!aux || !aux->param_cattr)
6711 return aux->param_cattr [param];
6714 image = method->klass->image;
6715 method_index = find_method_index (method);
6716 ca = &image->tables [MONO_TABLE_METHOD];
6718 if (method->klass->generic_class || method->klass->generic_container ||
6719 method->signature->generic_param_count) {
6720 /* FIXME FIXME FIXME */
6724 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6725 if (method_index == ca->rows) {
6726 ca = &image->tables [MONO_TABLE_PARAM];
6727 param_last = ca->rows + 1;
6729 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6730 ca = &image->tables [MONO_TABLE_PARAM];
6733 for (i = param_list; i < param_last; ++i) {
6734 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6735 if (param_pos == param) {
6743 idx <<= MONO_CUSTOM_ATTR_BITS;
6744 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6745 return mono_custom_attrs_from_index (image, idx);
6749 * mono_reflection_get_custom_attrs:
6750 * @obj: a reflection object handle
6752 * Return an array with all the custom attributes defined of the
6753 * reflection handle @obj. The objects are fully build.
6756 mono_reflection_get_custom_attrs (MonoObject *obj)
6760 MonoCustomAttrInfo *cinfo = NULL;
6762 MONO_ARCH_SAVE_REGS;
6764 klass = obj->vtable->klass;
6765 if (klass == mono_defaults.monotype_class) {
6766 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6767 klass = mono_class_from_mono_type (rtype->type);
6768 cinfo = mono_custom_attrs_from_class (klass);
6769 } else if (strcmp ("Assembly", klass->name) == 0) {
6770 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6771 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6772 } else if (strcmp ("Module", klass->name) == 0) {
6773 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6774 cinfo = mono_custom_attrs_from_module (module->image);
6775 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6776 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6777 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6778 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6779 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6780 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6781 } else if (strcmp ("MonoField", klass->name) == 0) {
6782 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6783 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6784 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6785 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6786 cinfo = mono_custom_attrs_from_method (rmethod->method);
6787 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6788 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6789 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6790 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6791 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6792 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6793 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6794 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6795 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6796 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6797 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
6798 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
6799 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
6800 } else { /* handle other types here... */
6801 g_error ("get custom attrs not yet supported for %s", klass->name);
6805 result = mono_custom_attrs_construct (cinfo);
6807 mono_custom_attrs_free (cinfo);
6809 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6810 result = mono_array_new (mono_domain_get (), klass, 0);
6816 static MonoMethodSignature*
6817 parameters_to_signature (MonoArray *parameters) {
6818 MonoMethodSignature *sig;
6821 count = parameters? mono_array_length (parameters): 0;
6823 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6824 sig->param_count = count;
6825 sig->sentinelpos = -1; /* FIXME */
6826 for (i = 0; i < count; ++i) {
6827 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6828 sig->params [i] = pt->type;
6833 static MonoMethodSignature*
6834 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6835 MonoMethodSignature *sig;
6837 sig = parameters_to_signature (ctor->parameters);
6838 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6839 sig->ret = &mono_defaults.void_class->byval_arg;
6843 static MonoMethodSignature*
6844 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6845 MonoMethodSignature *sig;
6847 sig = parameters_to_signature (method->parameters);
6848 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6849 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6850 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6854 static MonoMethodSignature*
6855 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6856 MonoMethodSignature *sig;
6858 sig = parameters_to_signature (method->parameters);
6859 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6860 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6861 sig->generic_param_count = 0;
6866 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6868 MonoClass *klass = mono_object_class (prop);
6869 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6870 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6871 *name = mono_string_to_utf8 (pb->name);
6872 *type = pb->type->type;
6874 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6875 *name = g_strdup (p->property->name);
6876 if (p->property->get)
6877 *type = p->property->get->signature->ret;
6879 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6884 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6886 MonoClass *klass = mono_object_class (field);
6887 if (strcmp (klass->name, "FieldBuilder") == 0) {
6888 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6889 *name = mono_string_to_utf8 (fb->name);
6890 *type = fb->type->type;
6892 MonoReflectionField *f = (MonoReflectionField *)field;
6893 *name = g_strdup (f->field->name);
6894 *type = f->field->type;
6899 * Encode a value in a custom attribute stream of bytes.
6900 * The value to encode is either supplied as an object in argument val
6901 * (valuetypes are boxed), or as a pointer to the data in the
6903 * @type represents the type of the value
6904 * @buffer is the start of the buffer
6905 * @p the current position in the buffer
6906 * @buflen contains the size of the buffer and is used to return the new buffer size
6907 * if this needs to be realloced.
6908 * @retbuffer and @retp return the start and the position of the buffer
6911 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6913 MonoTypeEnum simple_type;
6915 if ((p-buffer) + 10 >= *buflen) {
6918 newbuf = g_realloc (buffer, *buflen);
6919 p = newbuf + (p-buffer);
6923 argval = ((char*)arg + sizeof (MonoObject));
6924 simple_type = type->type;
6926 switch (simple_type) {
6927 case MONO_TYPE_BOOLEAN:
6932 case MONO_TYPE_CHAR:
6935 swap_with_size (p, argval, 2, 1);
6941 swap_with_size (p, argval, 4, 1);
6947 swap_with_size (p, argval, 8, 1);
6950 case MONO_TYPE_VALUETYPE:
6951 if (type->data.klass->enumtype) {
6952 simple_type = type->data.klass->enum_basetype->type;
6955 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6958 case MONO_TYPE_STRING: {
6965 str = mono_string_to_utf8 ((MonoString*)arg);
6966 slen = strlen (str);
6967 if ((p-buffer) + 10 + slen >= *buflen) {
6971 newbuf = g_realloc (buffer, *buflen);
6972 p = newbuf + (p-buffer);
6975 mono_metadata_encode_value (slen, p, &p);
6976 memcpy (p, str, slen);
6981 case MONO_TYPE_CLASS: {
6989 k = mono_object_class (arg);
6990 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6991 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6992 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6994 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6995 slen = strlen (str);
6996 if ((p-buffer) + 10 + slen >= *buflen) {
7000 newbuf = g_realloc (buffer, *buflen);
7001 p = newbuf + (p-buffer);
7004 mono_metadata_encode_value (slen, p, &p);
7005 memcpy (p, str, slen);
7010 case MONO_TYPE_SZARRAY: {
7012 MonoClass *eclass, *arg_eclass;
7015 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7018 len = mono_array_length ((MonoArray*)arg);
7020 *p++ = (len >> 8) & 0xff;
7021 *p++ = (len >> 16) & 0xff;
7022 *p++ = (len >> 24) & 0xff;
7024 *retbuffer = buffer;
7025 eclass = type->data.klass;
7026 arg_eclass = mono_object_class (arg)->element_class;
7027 if (eclass->valuetype && arg_eclass->valuetype) {
7028 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7029 int elsize = mono_class_array_element_size (eclass);
7030 for (i = 0; i < len; ++i) {
7031 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7035 for (i = 0; i < len; ++i) {
7036 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7041 /* it may be a boxed value or a Type */
7042 case MONO_TYPE_OBJECT: {
7043 MonoClass *klass = mono_object_class (arg);
7047 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7050 } else if (klass->enumtype) {
7052 } else if (klass == mono_defaults.string_class) {
7053 simple_type = MONO_TYPE_STRING;
7056 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7057 *p++ = simple_type = klass->byval_arg.type;
7060 g_error ("unhandled type in custom attr");
7062 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7063 slen = strlen (str);
7064 if ((p-buffer) + 10 + slen >= *buflen) {
7068 newbuf = g_realloc (buffer, *buflen);
7069 p = newbuf + (p-buffer);
7072 mono_metadata_encode_value (slen, p, &p);
7073 memcpy (p, str, slen);
7076 simple_type = klass->enum_basetype->type;
7080 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7083 *retbuffer = buffer;
7087 * mono_reflection_get_custom_attrs_blob:
7088 * @ctor: custom attribute constructor
7089 * @ctorArgs: arguments o the constructor
7095 * Creates the blob of data that needs to be saved in the metadata and that represents
7096 * the custom attributed described by @ctor, @ctorArgs etc.
7097 * Returns: a Byte array representing the blob of data.
7100 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7103 MonoMethodSignature *sig;
7108 MONO_ARCH_SAVE_REGS;
7110 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7111 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7113 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7115 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7117 p = buffer = g_malloc (buflen);
7118 /* write the prolog */
7121 for (i = 0; i < sig->param_count; ++i) {
7122 arg = mono_array_get (ctorArgs, MonoObject*, i);
7123 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7127 i += mono_array_length (properties);
7129 i += mono_array_length (fields);
7131 *p++ = (i >> 8) & 0xff;
7134 for (i = 0; i < mono_array_length (properties); ++i) {
7139 prop = mono_array_get (properties, gpointer, i);
7140 get_prop_name_and_type (prop, &pname, &ptype);
7141 *p++ = 0x54; /* PROPERTY signature */
7143 /* Preallocate a large enough buffer */
7144 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7145 char *str = type_get_qualified_name (ptype, NULL);
7151 len += strlen (pname);
7153 if ((p-buffer) + 20 + len >= buflen) {
7157 newbuf = g_realloc (buffer, buflen);
7158 p = newbuf + (p-buffer);
7162 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7163 char *str = type_get_qualified_name (ptype, NULL);
7164 int slen = strlen (str);
7168 * This seems to be optional...
7171 mono_metadata_encode_value (slen, p, &p);
7172 memcpy (p, str, slen);
7176 mono_metadata_encode_value (ptype->type, p, &p);
7177 if (ptype->type == MONO_TYPE_SZARRAY)
7178 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7180 len = strlen (pname);
7181 mono_metadata_encode_value (len, p, &p);
7182 memcpy (p, pname, len);
7184 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7191 for (i = 0; i < mono_array_length (fields); ++i) {
7196 field = mono_array_get (fields, gpointer, i);
7197 get_field_name_and_type (field, &fname, &ftype);
7198 *p++ = 0x53; /* FIELD signature */
7199 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7200 char *str = type_get_qualified_name (ftype, NULL);
7201 int slen = strlen (str);
7202 if ((p-buffer) + 10 + slen >= buflen) {
7206 newbuf = g_realloc (buffer, buflen);
7207 p = newbuf + (p-buffer);
7212 * This seems to be optional...
7215 mono_metadata_encode_value (slen, p, &p);
7216 memcpy (p, str, slen);
7220 mono_metadata_encode_value (ftype->type, p, &p);
7221 if (ftype->type == MONO_TYPE_SZARRAY)
7222 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7224 len = strlen (fname);
7225 mono_metadata_encode_value (len, p, &p);
7226 memcpy (p, fname, len);
7228 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7233 g_assert (p - buffer <= buflen);
7234 buflen = p - buffer;
7235 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7236 p = mono_array_addr (result, char, 0);
7237 memcpy (p, buffer, buflen);
7239 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7245 * mono_reflection_setup_internal_class:
7246 * @tb: a TypeBuilder object
7248 * Creates a MonoClass that represents the TypeBuilder.
7249 * This is a trick that lets us simplify a lot of reflection code
7250 * (and will allow us to support Build and Run assemblies easier).
7253 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7255 MonoClass *klass, *parent;
7257 MONO_ARCH_SAVE_REGS;
7260 /* check so we can compile corlib correctly */
7261 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7262 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7263 parent = tb->parent->type->data.klass;
7265 parent = my_mono_class_from_mono_type (tb->parent->type);
7271 /* the type has already being created: it means we just have to change the parent */
7272 if (tb->type.type) {
7273 klass = mono_class_from_mono_type (tb->type.type);
7274 klass->parent = NULL;
7275 /* fool mono_class_setup_parent */
7276 g_free (klass->supertypes);
7277 klass->supertypes = NULL;
7278 mono_class_setup_parent (klass, parent);
7279 mono_class_setup_mono_type (klass);
7283 klass = g_new0 (MonoClass, 1);
7285 klass->image = &tb->module->dynamic_image->image;
7287 klass->inited = 1; /* we lie to the runtime */
7288 klass->name = mono_string_to_utf8 (tb->name);
7289 klass->name_space = mono_string_to_utf8 (tb->nspace);
7290 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7291 klass->flags = tb->attrs;
7293 klass->element_class = klass;
7294 klass->reflection_info = tb; /* need to pin. */
7296 /* Put into cache so mono_class_get () will find it */
7297 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7299 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7300 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7302 if (parent != NULL) {
7303 mono_class_setup_parent (klass, parent);
7304 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7305 const char *old_n = klass->name;
7306 /* trick to get relative numbering right when compiling corlib */
7307 klass->name = "BuildingObject";
7308 mono_class_setup_parent (klass, mono_defaults.object_class);
7309 klass->name = old_n;
7312 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7313 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7314 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7315 klass->instance_size = sizeof (MonoObject);
7316 klass->size_inited = 1;
7317 mono_class_setup_vtable (klass, NULL, 0);
7320 mono_class_setup_mono_type (klass);
7322 mono_class_setup_supertypes (klass);
7325 * FIXME: handle interfaces.
7328 tb->type.type = &klass->byval_arg;
7330 if (tb->nesting_type) {
7331 g_assert (tb->nesting_type->type);
7332 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7335 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7339 * mono_reflection_setup_generic_class:
7340 * @tb: a TypeBuilder object
7342 * Setup the generic class before adding the first generic parameter.
7345 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7349 MONO_ARCH_SAVE_REGS;
7351 klass = my_mono_class_from_mono_type (tb->type.type);
7352 if (tb->generic_container)
7355 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7356 tb->generic_container->klass = klass;
7358 tb->generic_container->context = g_new0 (MonoGenericContext, 1);
7359 tb->generic_container->context->container = tb->generic_container;
7363 * mono_reflection_create_generic_class:
7364 * @tb: a TypeBuilder object
7366 * Creates the generic class after all generic parameters have been added.
7369 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7374 MONO_ARCH_SAVE_REGS;
7376 klass = my_mono_class_from_mono_type (tb->type.type);
7378 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7380 if (klass->generic_container || (count == 0))
7383 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7385 klass->generic_container = tb->generic_container;
7387 klass->generic_container->type_argc = count;
7388 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7390 for (i = 0; i < count; i++) {
7391 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7392 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7393 g_assert (klass->generic_container->type_params [i].owner);
7398 * mono_reflection_create_internal_class:
7399 * @tb: a TypeBuilder object
7401 * Actually create the MonoClass that is associated with the TypeBuilder.
7404 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7408 MONO_ARCH_SAVE_REGS;
7410 klass = my_mono_class_from_mono_type (tb->type.type);
7412 if (klass->enumtype && klass->enum_basetype == NULL) {
7413 MonoReflectionFieldBuilder *fb;
7416 g_assert (tb->fields != NULL);
7417 g_assert (mono_array_length (tb->fields) >= 1);
7419 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7421 klass->enum_basetype = fb->type->type;
7422 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7423 if (!klass->element_class)
7424 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7427 * get the element_class from the current corlib.
7429 ec = default_class_from_mono_type (klass->enum_basetype);
7430 klass->instance_size = ec->instance_size;
7431 klass->size_inited = 1;
7433 * this is almost safe to do with enums and it's needed to be able
7434 * to create objects of the enum type (for use in SetConstant).
7436 /* FIXME: Does this mean enums can't have method overrides ? */
7437 mono_class_setup_vtable (klass, NULL, 0);
7441 static MonoMarshalSpec*
7442 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7443 MonoReflectionMarshal *minfo)
7445 MonoMarshalSpec *res;
7447 res = g_new0 (MonoMarshalSpec, 1);
7448 res->native = minfo->type;
7450 switch (minfo->type) {
7451 case MONO_NATIVE_LPARRAY:
7452 res->data.array_data.elem_type = minfo->eltype;
7453 res->data.array_data.param_num = 0; /* Not yet */
7454 res->data.array_data.num_elem = minfo->count;
7457 case MONO_NATIVE_BYVALTSTR:
7458 case MONO_NATIVE_BYVALARRAY:
7459 res->data.array_data.num_elem = minfo->count;
7462 case MONO_NATIVE_CUSTOM:
7463 if (minfo->marshaltyperef)
7464 res->data.custom_data.custom_name =
7465 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7467 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7477 MonoReflectionMarshal*
7478 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7479 MonoMarshalSpec *spec)
7481 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7482 MonoReflectionMarshal *minfo;
7485 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7486 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7487 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7488 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7491 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7492 minfo->type = spec->native;
7494 switch (minfo->type) {
7495 case MONO_NATIVE_LPARRAY:
7496 minfo->eltype = spec->data.array_data.elem_type;
7497 minfo->count = spec->data.array_data.num_elem;
7500 case MONO_NATIVE_BYVALTSTR:
7501 case MONO_NATIVE_BYVALARRAY:
7502 minfo->count = spec->data.array_data.num_elem;
7505 case MONO_NATIVE_CUSTOM:
7506 if (spec->data.custom_data.custom_name) {
7507 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7509 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7511 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7513 if (spec->data.custom_data.cookie)
7514 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7525 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7526 ReflectionMethodBuilder *rmb,
7527 MonoMethodSignature *sig)
7530 MonoMethodNormal *pm;
7531 MonoMarshalSpec **specs;
7532 MonoReflectionMethodAux *method_aux;
7535 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7536 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7537 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7539 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7541 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7543 pm = (MonoMethodNormal*)m;
7546 m->flags = rmb->attrs;
7547 m->iflags = rmb->iattrs;
7548 m->name = mono_string_to_utf8 (rmb->name);
7552 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7554 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7555 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7558 m->signature->pinvoke = 1;
7559 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7560 m->signature->pinvoke = 1;
7562 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7564 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7565 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7567 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7569 if (klass->image->dynamic)
7570 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7573 } else if (!m->klass->dummy &&
7574 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7575 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7576 MonoMethodHeader *header;
7578 gint32 max_stack, i;
7579 gint32 num_locals = 0;
7580 gint32 num_clauses = 0;
7584 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7585 code_size = rmb->ilgen->code_len;
7586 max_stack = rmb->ilgen->max_stack;
7587 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7588 if (rmb->ilgen->ex_handlers)
7589 num_clauses = method_count_clauses (rmb->ilgen);
7592 code = mono_array_addr (rmb->code, guint8, 0);
7593 code_size = mono_array_length (rmb->code);
7594 /* we probably need to run a verifier on the code... */
7604 header = g_malloc0 (sizeof (MonoMethodHeader) +
7605 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7606 header->code_size = code_size;
7607 header->code = g_malloc (code_size);
7608 memcpy ((char*)header->code, code, code_size);
7609 header->max_stack = max_stack;
7610 header->init_locals = rmb->init_locals;
7611 header->num_locals = num_locals;
7613 for (i = 0; i < num_locals; ++i) {
7614 MonoReflectionLocalBuilder *lb =
7615 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7617 header->locals [i] = g_new0 (MonoType, 1);
7618 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7621 header->num_clauses = num_clauses;
7623 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7624 rmb->ilgen, num_clauses);
7627 pm->header = header;
7630 if (rmb->generic_params) {
7631 int count = mono_array_length (rmb->generic_params);
7632 MonoGenericContainer *container;
7634 pm->generic_container = container = rmb->generic_container;
7635 container->type_argc = count;
7636 container->type_params = g_new0 (MonoGenericParam, count);
7638 for (i = 0; i < count; i++) {
7639 MonoReflectionGenericParam *gp =
7640 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7642 container->type_params [i] = *gp->type.type->data.generic_param;
7647 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7650 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7652 for (i = 0; i < rmb->nrefs; ++i)
7653 mw->data = g_list_append (mw->data, rmb->refs [i]);
7658 /* Parameter info */
7661 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7662 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7663 for (i = 0; i <= m->signature->param_count; ++i) {
7664 MonoReflectionParamBuilder *pb;
7665 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7667 m->signature->params [i - 1]->attrs = pb->attrs;
7669 if (pb->def_value) {
7670 MonoDynamicImage *assembly;
7671 guint32 idx, def_type, len;
7675 if (!method_aux->param_defaults)
7676 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7677 assembly = (MonoDynamicImage*)klass->image;
7678 idx = encode_constant (assembly, pb->def_value, &def_type);
7679 /* Copy the data from the blob since it might get realloc-ed */
7680 p = assembly->blob.data + idx;
7681 len = mono_metadata_decode_blob_size (p, &p2);
7683 method_aux->param_defaults [i] = g_malloc (len);
7684 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7688 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7690 if (!method_aux->param_cattr)
7691 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7692 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7698 /* Parameter marshalling */
7701 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7702 MonoReflectionParamBuilder *pb;
7703 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7704 if (pb->marshal_info) {
7706 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7707 specs [pb->position] =
7708 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7712 if (specs != NULL) {
7714 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7715 method_aux->param_marshall = specs;
7718 if (klass->image->dynamic && method_aux)
7719 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7725 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7727 ReflectionMethodBuilder rmb;
7728 MonoMethodSignature *sig;
7730 sig = ctor_builder_to_signature (mb);
7732 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7734 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7735 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7737 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7738 /* ilgen is no longer needed */
7746 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7748 ReflectionMethodBuilder rmb;
7749 MonoMethodSignature *sig;
7751 sig = method_builder_to_signature (mb);
7753 reflection_methodbuilder_from_method_builder (&rmb, mb);
7755 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7756 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7758 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7759 /* ilgen is no longer needed */
7765 static MonoClassField*
7766 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7768 MonoClassField *field;
7775 field = g_new0 (MonoClassField, 1);
7777 field->name = mono_string_to_utf8 (fb->name);
7779 /* FIXME: handle type modifiers */
7780 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7781 field->type->attrs = fb->attrs;
7783 field->type = fb->type->type;
7785 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7786 field->data = mono_array_addr (fb->rva_data, char, 0);
7787 if (fb->offset != -1)
7788 field->offset = fb->offset;
7789 field->parent = klass;
7791 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7793 if (fb->def_value) {
7794 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7795 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7796 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7797 /* Copy the data from the blob since it might get realloc-ed */
7798 p = assembly->blob.data + idx;
7799 len = mono_metadata_decode_blob_size (p, &p2);
7801 field->data = g_malloc (len);
7802 memcpy ((gpointer)field->data, p, len);
7809 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
7812 MonoClass *klass, *gklass;
7813 MonoReflectionTypeBuilder *tb = NULL;
7814 MonoGenericClass *gclass, *cached;
7819 klass = mono_class_from_mono_type (type->type);
7820 if (!klass->generic_container && !klass->generic_class &&
7821 !(klass->nested_in && klass->nested_in->generic_container))
7824 mono_loader_lock ();
7826 domain = mono_object_domain (type);
7828 gclass = g_new0 (MonoGenericClass, 1);
7829 gclass->inst = g_new0 (MonoGenericInst, 1);
7831 gclass->inst->type_argc = type_argc;
7832 gclass->inst->type_argv = types;
7834 for (i = 0; i < gclass->inst->type_argc; ++i) {
7835 if (!gclass->inst->is_open)
7836 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
7839 gclass->generic_type = &klass->byval_arg;
7841 if (klass->generic_class) {
7842 MonoGenericClass *kgclass = klass->generic_class;
7843 MonoGenericClass *ogclass = gclass;
7845 ogclass->context = g_new0 (MonoGenericContext, 1);
7846 ogclass->context->gclass = ogclass;
7848 gclass = g_new0 (MonoGenericClass, 1);
7849 gclass->inst = g_new0 (MonoGenericInst, 1);
7851 gclass->inst->type_argc = kgclass->inst->type_argc;
7852 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
7854 for (i = 0; i < gclass->inst->type_argc; i++) {
7855 MonoType *t = kgclass->inst->type_argv [i];
7857 t = mono_class_inflate_generic_type (t, ogclass->context);
7859 if (!gclass->inst->is_open)
7860 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
7862 gclass->inst->type_argv [i] = t;
7865 gclass->generic_type = kgclass->generic_type;
7868 geninst = g_new0 (MonoType, 1);
7869 geninst->type = MONO_TYPE_GENERICINST;
7871 cached = mono_metadata_lookup_generic_class (gclass);
7874 mono_loader_unlock ();
7875 geninst->data.generic_class = cached;
7879 gklass = mono_class_from_mono_type (gclass->generic_type);
7880 g_assert ((gclass->container = gklass->generic_container) != NULL);
7882 geninst->data.generic_class = gclass;
7884 gclass->parent = parent;
7886 gclass->context = g_new0 (MonoGenericContext, 1);
7887 gclass->context->gclass = gclass;
7889 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7890 tb = (MonoReflectionTypeBuilder *) type;
7892 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7893 gclass->is_dynamic = TRUE;
7894 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
7895 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
7896 MonoReflectionType *rgt = rgi->generic_type;
7898 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7899 tb = (MonoReflectionTypeBuilder *) rgt;
7901 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7902 gclass->is_dynamic = TRUE;
7904 icount = klass->interface_count;
7907 gclass->ifaces = g_new0 (MonoType *, icount);
7908 gclass->count_ifaces = icount;
7910 for (i = 0; i < icount; i++) {
7911 MonoReflectionType *itype;
7914 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7916 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7917 gclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7918 if (!gclass->ifaces [i])
7919 gclass->ifaces [i] = itype->type;
7922 mono_class_create_generic (gclass);
7923 mono_class_create_generic_2 (gclass);
7925 mono_loader_unlock ();
7931 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7933 MonoClass *klass, *pklass = NULL;
7934 MonoReflectionType *parent = NULL;
7935 MonoType *the_parent = NULL, *geninst;
7936 MonoReflectionTypeBuilder *tb = NULL;
7937 MonoGenericClass *gclass;
7940 domain = mono_object_domain (type);
7941 klass = mono_class_from_mono_type (type->type);
7943 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7944 tb = (MonoReflectionTypeBuilder *) type;
7947 parent = tb->parent;
7948 pklass = mono_class_from_mono_type (parent->type);
7951 pklass = klass->parent;
7953 parent = mono_type_get_object (domain, &pklass->byval_arg);
7954 else if (klass->generic_class && klass->generic_class->parent) {
7955 parent = mono_type_get_object (domain, klass->generic_class->parent);
7956 pklass = mono_class_from_mono_type (klass->generic_class->parent);
7960 if (pklass && pklass->generic_class)
7961 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7963 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
7967 gclass = geninst->data.generic_class;
7973 dup_type (const MonoType *original)
7975 MonoType *r = g_new0 (MonoType, 1);
7977 r->attrs = original->attrs;
7978 r->byref = original->byref;
7979 mono_stats.generics_metadata_size += sizeof (MonoType);
7983 MonoReflectionMethod*
7984 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7986 MonoMethod *method, *inflated;
7987 MonoReflectionMethodBuilder *mb = NULL;
7988 MonoGenericContainer *container;
7989 MonoGenericMethod *gmethod;
7990 MonoGenericContext *context;
7991 MonoGenericInst *ginst;
7994 MONO_ARCH_SAVE_REGS;
7995 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7996 MonoReflectionTypeBuilder *tb;
7999 mb = (MonoReflectionMethodBuilder *) rmethod;
8000 tb = (MonoReflectionTypeBuilder *) mb->type;
8001 klass = mono_class_from_mono_type (tb->type.type);
8003 method = methodbuilder_to_mono_method (klass, mb);
8005 method = rmethod->method;
8008 count = method->signature->generic_param_count;
8009 if (count != mono_array_length (types))
8012 container = ((MonoMethodNormal*) method)->generic_container;
8013 g_assert (container);
8015 if (!container->method_hash)
8016 container->method_hash = g_hash_table_new (
8017 (GHashFunc) mono_metadata_generic_method_hash,
8018 (GCompareFunc) mono_metadata_generic_method_equal);
8020 ginst = g_new0 (MonoGenericInst,1 );
8021 ginst->type_argc = count;
8022 ginst->type_argv = g_new0 (MonoType *, count);
8023 for (i = 0; i < count; i++) {
8024 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8025 ginst->type_argv [i] = dup_type (garg->type);
8027 if (!ginst->is_open)
8028 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8030 ginst = mono_metadata_lookup_generic_inst (ginst);
8032 gmethod = g_new0 (MonoGenericMethod, 1);
8033 gmethod->inst = ginst;
8035 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8039 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8042 gmethod->reflection_info = rmethod;
8044 context = g_new0 (MonoGenericContext, 1);
8045 context->gclass = method->klass->generic_class;
8046 context->gmethod = gmethod;
8048 inflated = mono_class_inflate_generic_method (method, context, NULL);
8049 g_hash_table_insert (container->method_hash, gmethod, inflated);
8051 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8055 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8057 MonoGenericMethod *gmethod;
8058 MonoGenericClass *gclass;
8059 MonoGenericContext *context;
8062 gclass = type->type.type->data.generic_class;
8064 gmethod = g_new0 (MonoGenericMethod, 1);
8065 gmethod->inst = g_new0 (MonoGenericInst, 1);
8066 gmethod->reflection_info = obj;
8068 gmethod->inst->type_argc = method->signature->generic_param_count;
8069 gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8071 for (i = 0; i < gmethod->inst->type_argc; i++) {
8072 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8073 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8075 g_assert (gparam->pklass);
8076 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8079 context = g_new0 (MonoGenericContext, 1);
8080 context->gclass = gclass;
8081 context->gmethod = gmethod;
8083 return mono_class_inflate_generic_method (method, context, gclass->klass);
8087 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8092 klass = mono_class_from_mono_type (type->type.type);
8094 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8095 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8096 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8097 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8098 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8099 method = ((MonoReflectionMethod *) obj)->method;
8101 method = NULL; /* prevent compiler warning */
8102 g_assert_not_reached ();
8105 return inflate_mono_method (type, method, obj);
8109 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8110 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8113 MonoGenericClass *gclass;
8114 MonoDynamicGenericClass *dgclass;
8115 MonoClass *klass, *gklass, *pklass;
8118 MONO_ARCH_SAVE_REGS;
8120 klass = mono_class_from_mono_type (type->type.type);
8121 gclass = type->type.type->data.generic_class;
8123 if (gclass->initialized)
8126 dgclass = gclass->dynamic_info = g_new0 (MonoDynamicGenericClass, 1);
8128 gklass = mono_class_from_mono_type (gclass->generic_type);
8129 mono_class_init (gklass);
8132 pklass = mono_class_from_mono_type (gclass->parent);
8134 pklass = gklass->parent;
8136 mono_class_setup_parent (klass, pklass);
8138 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8139 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8140 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8141 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8142 dgclass->count_events = events ? mono_array_length (events) : 0;
8144 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8145 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8146 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8147 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8148 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8150 for (i = 0; i < dgclass->count_methods; i++) {
8151 MonoObject *obj = mono_array_get (methods, gpointer, i);
8153 dgclass->methods [i] = inflate_method (type, obj);
8156 for (i = 0; i < dgclass->count_ctors; i++) {
8157 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8159 dgclass->ctors [i] = inflate_method (type, obj);
8162 for (i = 0; i < dgclass->count_fields; i++) {
8163 MonoObject *obj = mono_array_get (fields, gpointer, i);
8164 MonoClassField *field;
8165 MonoInflatedField *ifield;
8167 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8168 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8169 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8170 field = ((MonoReflectionField *) obj)->field;
8172 field = NULL; /* prevent compiler warning */
8173 g_assert_not_reached ();
8176 ifield = g_new0 (MonoInflatedField, 1);
8177 ifield->generic_type = field->type;
8178 ifield->reflection_info = obj;
8180 dgclass->fields [i] = *field;
8181 dgclass->fields [i].generic_info = ifield;
8182 dgclass->fields [i].type = mono_class_inflate_generic_type (field->type, gclass->context);
8185 for (i = 0; i < dgclass->count_properties; i++) {
8186 MonoObject *obj = mono_array_get (properties, gpointer, i);
8187 MonoProperty *property = &dgclass->properties [i];
8189 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8190 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8192 property->parent = klass;
8193 property->attrs = pb->attrs;
8194 property->name = mono_string_to_utf8 (pb->name);
8196 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8198 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8199 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8200 *property = *((MonoReflectionProperty *) obj)->property;
8203 property->get = inflate_mono_method (type, property->get, NULL);
8205 property->set = inflate_mono_method (type, property->set, NULL);
8207 g_assert_not_reached ();
8210 for (i = 0; i < dgclass->count_events; i++) {
8211 MonoObject *obj = mono_array_get (events, gpointer, i);
8212 MonoEvent *event = &dgclass->events [i];
8214 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8215 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8217 event->parent = klass;
8218 event->attrs = eb->attrs;
8219 event->name = mono_string_to_utf8 (eb->name);
8221 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8222 if (eb->remove_method)
8223 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8224 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8225 *event = *((MonoReflectionEvent *) obj)->event;
8228 event->add = inflate_mono_method (type, event->add, NULL);
8230 event->remove = inflate_mono_method (type, event->remove, NULL);
8232 g_assert_not_reached ();
8235 gclass->initialized = TRUE;
8239 ensure_runtime_vtable (MonoClass *klass)
8241 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8242 int i, num, j, onum;
8243 MonoMethod **overrides;
8245 if (!tb || klass->wastypebuilder)
8248 ensure_runtime_vtable (klass->parent);
8250 num = tb->ctors? mono_array_length (tb->ctors): 0;
8251 num += tb->num_methods;
8252 klass->method.count = num;
8253 klass->methods = g_new (MonoMethod*, num);
8254 num = tb->ctors? mono_array_length (tb->ctors): 0;
8255 for (i = 0; i < num; ++i)
8256 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8257 num = tb->num_methods;
8259 for (i = 0; i < num; ++i)
8260 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8262 if (tb->interfaces) {
8263 klass->interface_count = mono_array_length (tb->interfaces);
8264 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8265 for (i = 0; i < klass->interface_count; ++i) {
8266 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8267 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8271 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8272 for (i = 0; i < klass->method.count; ++i)
8273 klass->methods [i]->slot = i;
8278 for (i = 0; i < tb->num_methods; ++i) {
8279 MonoReflectionMethodBuilder *mb =
8280 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8281 if (mb->override_method)
8286 overrides = g_new0 (MonoMethod*, onum * 2);
8290 for (i = 0; i < tb->num_methods; ++i) {
8291 MonoReflectionMethodBuilder *mb =
8292 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8293 if (mb->override_method) {
8294 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8295 overrides [onum * 2] =
8296 mb->override_method->method;
8297 overrides [onum * 2 + 1] =
8300 g_assert (mb->mhandle);
8307 mono_class_setup_vtable (klass, overrides, onum);
8312 typebuilder_setup_fields (MonoClass *klass)
8314 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8315 MonoReflectionFieldBuilder *fb;
8316 MonoClassField *field;
8321 klass->field.count = tb->num_fields;
8322 klass->field.first = 0;
8323 klass->field.last = klass->field.count;
8325 if (!klass->field.count)
8328 klass->fields = g_new0 (MonoClassField, klass->field.count);
8330 for (i = 0; i < klass->field.count; ++i) {
8331 fb = mono_array_get (tb->fields, gpointer, i);
8332 field = &klass->fields [i];
8333 field->name = mono_string_to_utf8 (fb->name);
8335 /* FIXME: handle type modifiers */
8336 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8337 field->type->attrs = fb->attrs;
8339 field->type = fb->type->type;
8341 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8342 field->data = mono_array_addr (fb->rva_data, char, 0);
8343 if (fb->offset != -1)
8344 field->offset = fb->offset;
8345 field->parent = klass;
8347 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8349 if (fb->def_value) {
8350 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8351 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8352 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8353 /* Copy the data from the blob since it might get realloc-ed */
8354 p = assembly->blob.data + idx;
8355 len = mono_metadata_decode_blob_size (p, &p2);
8357 field->data = g_malloc (len);
8358 memcpy ((gpointer)field->data, p, len);
8361 mono_class_layout_fields (klass);
8365 typebuilder_setup_properties (MonoClass *klass)
8367 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8368 MonoReflectionPropertyBuilder *pb;
8371 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8372 klass->property.first = 0;
8373 klass->property.last = klass->property.count;
8375 klass->properties = g_new0 (MonoProperty, klass->property.count);
8376 for (i = 0; i < klass->property.count; ++i) {
8377 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8378 klass->properties [i].parent = klass;
8379 klass->properties [i].attrs = pb->attrs;
8380 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8382 klass->properties [i].get = pb->get_method->mhandle;
8384 klass->properties [i].set = pb->set_method->mhandle;
8388 MonoReflectionEvent *
8389 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8391 MonoEvent *event = g_new0 (MonoEvent, 1);
8395 klass = my_mono_class_from_mono_type (tb->type.type);
8397 event->parent = klass;
8398 event->attrs = eb->attrs;
8399 event->name = mono_string_to_utf8 (eb->name);
8401 event->add = eb->add_method->mhandle;
8402 if (eb->remove_method)
8403 event->remove = eb->remove_method->mhandle;
8404 if (eb->raise_method)
8405 event->raise = eb->raise_method->mhandle;
8407 if (eb->other_methods) {
8408 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8409 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8410 MonoReflectionMethodBuilder *mb =
8411 mono_array_get (eb->other_methods,
8412 MonoReflectionMethodBuilder*, j);
8413 event->other [j] = mb->mhandle;
8417 return mono_event_get_object (mono_object_domain (tb), klass, event);
8421 typebuilder_setup_events (MonoClass *klass)
8423 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8424 MonoReflectionEventBuilder *eb;
8427 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8428 klass->event.first = 0;
8429 klass->event.last = klass->event.count;
8431 klass->events = g_new0 (MonoEvent, klass->event.count);
8432 for (i = 0; i < klass->event.count; ++i) {
8433 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8434 klass->events [i].parent = klass;
8435 klass->events [i].attrs = eb->attrs;
8436 klass->events [i].name = mono_string_to_utf8 (eb->name);
8438 klass->events [i].add = eb->add_method->mhandle;
8439 if (eb->remove_method)
8440 klass->events [i].remove = eb->remove_method->mhandle;
8441 if (eb->raise_method)
8442 klass->events [i].raise = eb->raise_method->mhandle;
8444 if (eb->other_methods) {
8445 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8446 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8447 MonoReflectionMethodBuilder *mb =
8448 mono_array_get (eb->other_methods,
8449 MonoReflectionMethodBuilder*, j);
8450 klass->events [i].other [j] = mb->mhandle;
8457 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8460 MonoReflectionType* res;
8463 MONO_ARCH_SAVE_REGS;
8465 klass = my_mono_class_from_mono_type (tb->type.type);
8467 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8470 * Fields to set in klass:
8471 * the various flags: delegate/unicode/contextbound etc.
8473 klass->flags = tb->attrs;
8475 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8476 /* No need to fully construct the type */
8477 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8479 /* enums are done right away */
8480 if (!klass->enumtype)
8481 ensure_runtime_vtable (klass);
8484 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8485 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8486 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8490 /* fields and object layout */
8491 if (klass->parent) {
8492 if (!klass->parent->size_inited)
8493 mono_class_init (klass->parent);
8494 klass->instance_size += klass->parent->instance_size;
8495 klass->class_size += klass->parent->class_size;
8496 klass->min_align = klass->parent->min_align;
8498 klass->instance_size = sizeof (MonoObject);
8499 klass->min_align = 1;
8502 /* FIXME: handle packing_size and instance_size */
8503 typebuilder_setup_fields (klass);
8505 typebuilder_setup_properties (klass);
8507 typebuilder_setup_events (klass);
8509 klass->wastypebuilder = TRUE;
8511 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8512 g_assert (res != (MonoReflectionType*)tb);
8517 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8519 MonoGenericParam *param;
8522 MONO_ARCH_SAVE_REGS;
8524 param = g_new0 (MonoGenericParam, 1);
8526 if (gparam->mbuilder) {
8527 if (!gparam->mbuilder->generic_container)
8528 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8529 param->owner = gparam->mbuilder->generic_container;
8530 } else if (gparam->tbuilder) {
8531 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8532 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8537 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8538 if (gparam->index >= count)
8541 container = nesting->generic_container;
8542 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8545 g_assert (container);
8546 param->owner = container;
8549 param->method = NULL;
8550 param->name = mono_string_to_utf8 (gparam->name);
8551 param->num = gparam->index;
8553 image = &gparam->tbuilder->module->dynamic_image->image;
8554 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8556 param->pklass->reflection_info = gparam;
8558 gparam->type.type = g_new0 (MonoType, 1);
8559 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8560 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8561 gparam->type.type->data.generic_param = param;
8565 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8567 MonoDynamicImage *assembly = sig->module->dynamic_image;
8568 guint32 na = mono_array_length (sig->arguments);
8573 MONO_ARCH_SAVE_REGS;
8575 p = buf = g_malloc (10 + na * 10);
8577 mono_metadata_encode_value (0x07, p, &p);
8578 mono_metadata_encode_value (na, p, &p);
8579 for (i = 0; i < na; ++i) {
8580 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8581 encode_reflection_type (assembly, type, p, &p);
8585 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8586 p = mono_array_addr (result, char, 0);
8587 memcpy (p, buf, buflen);
8594 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8596 MonoDynamicImage *assembly = sig->module->dynamic_image;
8597 guint32 na = mono_array_length (sig->arguments);
8602 MONO_ARCH_SAVE_REGS;
8604 p = buf = g_malloc (10 + na * 10);
8606 mono_metadata_encode_value (0x06, p, &p);
8607 for (i = 0; i < na; ++i) {
8608 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8609 encode_reflection_type (assembly, type, p, &p);
8613 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8614 p = mono_array_addr (result, char, 0);
8615 memcpy (p, buf, buflen);
8622 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8624 ReflectionMethodBuilder rmb;
8625 MonoMethodSignature *sig;
8628 sig = dynamic_method_to_signature (mb);
8630 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8633 * Resolve references.
8635 rmb.nrefs = mb->nrefs;
8636 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8637 for (i = 0; i < mb->nrefs; ++i) {
8638 gpointer ref = resolve_object (mb->module->image,
8639 mono_array_get (mb->refs, MonoObject*, i));
8642 mono_raise_exception (mono_get_exception_type_load (NULL));
8649 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8653 /* ilgen is no longer needed */
8658 * mono_reflection_lookup_dynamic_token:
8660 * Finish the Builder object pointed to by TOKEN and return the corresponding
8661 * runtime structure.
8664 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8666 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8669 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8672 return resolve_object (image, obj);
8676 resolve_object (MonoImage *image, MonoObject *obj)
8678 gpointer result = NULL;
8680 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8681 result = mono_string_intern ((MonoString*)obj);
8683 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8684 MonoReflectionType *tb = (MonoReflectionType*)obj;
8685 result = mono_class_from_mono_type (tb->type);
8687 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8688 result = ((MonoReflectionMethod*)obj)->method;
8690 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8691 result = ((MonoReflectionMethod*)obj)->method;
8693 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8694 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8695 result = mb->mhandle;
8697 /* Type is not yet created */
8698 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8700 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8703 * Hopefully this has been filled in by calling CreateType() on the
8707 * TODO: This won't work if the application finishes another
8708 * TypeBuilder instance instead of this one.
8710 result = mb->mhandle;
8712 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8713 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8715 result = cb->mhandle;
8717 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8719 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8720 result = cb->mhandle;
8722 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8723 result = ((MonoReflectionField*)obj)->field;
8725 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8726 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8727 result = fb->handle;
8730 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8732 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8733 result = fb->handle;
8735 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8736 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8739 klass = tb->type.type->data.klass;
8740 if (klass->wastypebuilder) {
8741 /* Already created */
8745 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8746 result = tb->type.type->data.klass;
8749 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8750 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8751 MonoMethodSignature *sig;
8754 if (helper->arguments)
8755 nargs = mono_array_length (helper->arguments);
8759 sig = mono_metadata_signature_alloc (image, nargs);
8760 sig->explicit_this = helper->call_conv & 64;
8761 sig->hasthis = helper->call_conv & 32;
8763 if (helper->call_conv == 0) /* unmanaged */
8764 sig->call_convention = helper->unmanaged_call_conv - 1;
8766 if (helper->call_conv & 0x02)
8767 sig->call_convention = MONO_CALL_VARARG;
8769 sig->call_convention = MONO_CALL_DEFAULT;
8771 sig->param_count = nargs;
8772 /* TODO: Copy type ? */
8773 sig->ret = helper->return_type->type;
8774 for (i = 0; i < nargs; ++i) {
8775 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8776 sig->params [i] = rt->type;
8781 g_print (obj->vtable->klass->name);
8782 g_assert_not_reached ();
8788 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
8789 const static guint32 declsec_flags_map[] = {
8790 0x00000000, /* empty */
8791 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
8792 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
8793 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
8794 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
8795 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
8796 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
8797 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
8798 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
8799 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
8800 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
8801 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
8802 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
8803 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
8804 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
8805 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
8806 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
8807 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
8808 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
8812 * Returns flags that includes all available security action associated to the handle.
8813 * @token: metadata token (either for a class or a method)
8814 * @image: image where resides the metadata.
8817 mono_declsec_get_flags (MonoImage *image, guint32 token)
8819 guint32 index = mono_metadata_declsec_from_index (image, token);
8820 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
8825 for (i = index; i < t->rows; i++) {
8826 guint32 cols [MONO_DECL_SECURITY_SIZE];
8828 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
8829 if (cols [MONO_DECL_SECURITY_PARENT] != token)
8832 action = cols [MONO_DECL_SECURITY_ACTION];
8833 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
8834 result |= declsec_flags_map [action];
8836 g_assert_not_reached ();
8843 * Get the security actions (in the form of flags) associated with the specified method.
8845 * @method: The method for which we want the declarative security flags.
8846 * Return the declarative security flags for the method (only).
8848 * Note: To keep MonoMethod size down we do not cache the declarative security flags
8849 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
8852 mono_declsec_flags_from_method (MonoMethod *method)
8854 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
8855 /* FIXME: No cache (for the moment) */
8856 guint32 idx = find_method_index (method);
8857 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8858 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
8859 return mono_declsec_get_flags (method->klass->image, idx);
8865 * Get the security actions (in the form of flags) associated with the specified class.
8867 * @klass: The class for which we want the declarative security flags.
8868 * Return the declarative security flags for the class.
8870 * Note: We cache the flags inside the MonoClass structure as this will get
8871 * called very often (at least for each method).
8874 mono_declsec_flags_from_class (MonoClass *klass)
8876 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
8877 if (!klass->declsec_flags) {
8878 guint32 idx = mono_metadata_token_index (klass->type_token);
8879 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8880 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
8881 /* we cache the flags on classes */
8882 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
8884 return klass->declsec_flags;
8890 * Get the security actions (in the form of flags) associated with the specified assembly.
8892 * @assembly: The assembly for which we want the declarative security flags.
8893 * Return the declarative security flags for the assembly.
8896 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
8898 guint32 idx = 1; /* there is only one assembly */
8899 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8900 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
8901 return mono_declsec_get_flags (assembly->image, idx);