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 (*a_entry)->owner - (*b_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 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4281 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4282 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4283 if (assemblyb->culture)
4284 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4286 assembly->assembly.aname.culture = g_strdup ("");
4288 assembly->run = assemblyb->access != 2;
4289 assembly->save = assemblyb->access != 1;
4291 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4292 image->initial_image = TRUE;
4293 assembly->assembly.aname.name = image->image.name;
4294 assembly->assembly.image = &image->image;
4296 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4297 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4301 calc_section_size (MonoDynamicImage *assembly)
4305 /* alignment constraints */
4306 assembly->code.index += 3;
4307 assembly->code.index &= ~3;
4308 assembly->meta_size += 3;
4309 assembly->meta_size &= ~3;
4310 assembly->resources.index += 3;
4311 assembly->resources.index &= ~3;
4313 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4314 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4317 if (assembly->win32_res) {
4318 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4320 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4321 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4325 assembly->sections [MONO_SECTION_RELOC].size = 12;
4326 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4336 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4340 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4342 ResTreeNode *t1 = (ResTreeNode*)a;
4343 ResTreeNode *t2 = (ResTreeNode*)b;
4345 return t1->id - t2->id;
4349 * resource_tree_create:
4351 * Organize the resources into a resource tree.
4353 static ResTreeNode *
4354 resource_tree_create (MonoArray *win32_resources)
4356 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4360 tree = g_new0 (ResTreeNode, 1);
4362 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4363 MonoReflectionWin32Resource *win32_res =
4364 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4368 lang_node = g_new0 (ResTreeNode, 1);
4369 lang_node->id = win32_res->lang_id;
4370 lang_node->win32_res = win32_res;
4372 /* Create type node if neccesary */
4374 for (l = tree->children; l; l = l->next)
4375 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4376 type_node = (ResTreeNode*)l->data;
4381 type_node = g_new0 (ResTreeNode, 1);
4382 type_node->id = win32_res->res_type;
4385 * The resource types have to be sorted otherwise
4386 * Windows Explorer can't display the version information.
4388 tree->children = g_slist_insert_sorted (tree->children,
4389 type_node, resource_tree_compare_by_id);
4392 /* Create res node if neccesary */
4394 for (l = type_node->children; l; l = l->next)
4395 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4396 res_node = (ResTreeNode*)l->data;
4401 res_node = g_new0 (ResTreeNode, 1);
4402 res_node->id = win32_res->res_id;
4403 type_node->children = g_slist_append (type_node->children, res_node);
4406 res_node->children = g_slist_append (res_node->children, lang_node);
4413 * resource_tree_encode:
4415 * Encode the resource tree into the format used in the PE file.
4418 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4421 MonoPEResourceDir dir;
4422 MonoPEResourceDirEntry dir_entry;
4423 MonoPEResourceDataEntry data_entry;
4427 * For the format of the resource directory, see the article
4428 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4432 memset (&dir, 0, sizeof (dir));
4433 memset (&dir_entry, 0, sizeof (dir_entry));
4434 memset (&data_entry, 0, sizeof (data_entry));
4436 g_assert (sizeof (dir) == 16);
4437 g_assert (sizeof (dir_entry) == 8);
4438 g_assert (sizeof (data_entry) == 16);
4440 node->offset = p - begin;
4442 /* IMAGE_RESOURCE_DIRECTORY */
4443 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4445 memcpy (p, &dir, sizeof (dir));
4448 /* Reserve space for entries */
4450 p += sizeof (dir_entry) * dir.res_id_entries;
4452 /* Write children */
4453 for (l = node->children; l; l = l->next) {
4454 ResTreeNode *child = (ResTreeNode*)l->data;
4456 if (child->win32_res) {
4458 child->offset = p - begin;
4460 /* IMAGE_RESOURCE_DATA_ENTRY */
4461 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4462 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4464 memcpy (p, &data_entry, sizeof (data_entry));
4465 p += sizeof (data_entry);
4467 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4468 p += data_entry.rde_size;
4470 resource_tree_encode (child, begin, p, &p);
4474 /* IMAGE_RESOURCE_ENTRY */
4475 for (l = node->children; l; l = l->next) {
4476 ResTreeNode *child = (ResTreeNode*)l->data;
4477 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4479 dir_entry.is_dir = child->win32_res ? 0 : 1;
4480 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4482 memcpy (entries, &dir_entry, sizeof (dir_entry));
4483 entries += sizeof (dir_entry);
4490 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4495 MonoReflectionWin32Resource *win32_res;
4498 if (!assemblyb->win32_resources)
4502 * Resources are stored in a three level tree inside the PE file.
4503 * - level one contains a node for each type of resource
4504 * - level two contains a node for each resource
4505 * - level three contains a node for each instance of a resource for a
4506 * specific language.
4509 tree = resource_tree_create (assemblyb->win32_resources);
4511 /* Estimate the size of the encoded tree */
4513 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4514 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4515 size += mono_array_length (win32_res->res_data);
4517 /* Directory structure */
4518 size += mono_array_length (assemblyb->win32_resources) * 256;
4519 p = buf = g_malloc (size);
4521 resource_tree_encode (tree, p, p, &p);
4523 g_assert (p - buf < size);
4525 assembly->win32_res = g_malloc (p - buf);
4526 assembly->win32_res_size = p - buf;
4527 memcpy (assembly->win32_res, buf, p - buf);
4533 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4535 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4538 p += sizeof (MonoPEResourceDir);
4539 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4540 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4541 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4542 if (dir_entry->is_dir) {
4543 fixup_resource_directory (res_section, child, rva);
4545 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4546 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4549 p += sizeof (MonoPEResourceDirEntry);
4554 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4557 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4558 g_error ("WriteFile returned %d\n", GetLastError ());
4562 * mono_image_create_pefile:
4563 * @mb: a module builder object
4565 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4566 * assembly->pefile where it can be easily retrieved later in chunks.
4569 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4570 MonoMSDOSHeader *msdos;
4571 MonoDotNetHeader *header;
4572 MonoSectionTable *section;
4573 MonoCLIHeader *cli_header;
4574 guint32 size, image_size, virtual_base, text_offset;
4575 guint32 header_start, section_start, file_offset, virtual_offset;
4576 MonoDynamicImage *assembly;
4577 MonoReflectionAssemblyBuilder *assemblyb;
4578 MonoDynamicStream pefile_stream = {0};
4579 MonoDynamicStream *pefile = &pefile_stream;
4581 guint32 *rva, value;
4583 static const unsigned char msheader[] = {
4584 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4585 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4588 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4589 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4590 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4591 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4594 assemblyb = mb->assemblyb;
4596 mono_image_basic_init (assemblyb);
4597 assembly = mb->dynamic_image;
4599 assembly->pe_kind = assemblyb->pe_kind;
4600 assembly->machine = assemblyb->machine;
4601 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4602 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4604 mono_image_build_metadata (mb);
4606 if (mb->is_main && assemblyb->resources) {
4607 int len = mono_array_length (assemblyb->resources);
4608 for (i = 0; i < len; ++i)
4609 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4612 if (mb->resources) {
4613 int len = mono_array_length (mb->resources);
4614 for (i = 0; i < len; ++i)
4615 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4618 build_compressed_metadata (assembly);
4621 assembly_add_win32_resources (assembly, assemblyb);
4623 nsections = calc_section_size (assembly);
4625 /* The DOS header and stub */
4626 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4627 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4629 /* the dotnet header */
4630 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4632 /* the section tables */
4633 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4635 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4636 virtual_offset = VIRT_ALIGN;
4639 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4640 if (!assembly->sections [i].size)
4643 file_offset += FILE_ALIGN - 1;
4644 file_offset &= ~(FILE_ALIGN - 1);
4645 virtual_offset += VIRT_ALIGN - 1;
4646 virtual_offset &= ~(VIRT_ALIGN - 1);
4648 assembly->sections [i].offset = file_offset;
4649 assembly->sections [i].rva = virtual_offset;
4651 file_offset += assembly->sections [i].size;
4652 virtual_offset += assembly->sections [i].size;
4653 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4656 file_offset += FILE_ALIGN - 1;
4657 file_offset &= ~(FILE_ALIGN - 1);
4659 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4661 /* back-patch info */
4662 msdos = (MonoMSDOSHeader*)pefile->data;
4663 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4664 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4665 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4667 header = (MonoDotNetHeader*)(pefile->data + header_start);
4668 header->pesig [0] = 'P';
4669 header->pesig [1] = 'E';
4671 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4672 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4673 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4674 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4675 if (assemblyb->pekind == 1) {
4677 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4680 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4683 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4685 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4686 header->pe.pe_major = 6;
4687 header->pe.pe_minor = 0;
4688 size = assembly->sections [MONO_SECTION_TEXT].size;
4689 size += FILE_ALIGN - 1;
4690 size &= ~(FILE_ALIGN - 1);
4691 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4692 size = assembly->sections [MONO_SECTION_RSRC].size;
4693 size += FILE_ALIGN - 1;
4694 size &= ~(FILE_ALIGN - 1);
4695 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4696 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4697 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4698 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4699 /* pe_rva_entry_point always at the beginning of the text section */
4700 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4702 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4703 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4704 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4705 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4706 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4707 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4708 size = section_start;
4709 size += FILE_ALIGN - 1;
4710 size &= ~(FILE_ALIGN - 1);
4711 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4713 size += VIRT_ALIGN - 1;
4714 size &= ~(VIRT_ALIGN - 1);
4715 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4718 // Translate the PEFileKind value to the value expected by the Windows loader
4724 // PEFileKinds.Dll == 1
4725 // PEFileKinds.ConsoleApplication == 2
4726 // PEFileKinds.WindowApplication == 3
4729 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4730 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4732 if (assemblyb->pekind == 3)
4737 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4739 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4740 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4741 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4742 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4743 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4744 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4746 /* fill data directory entries */
4748 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4749 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4751 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4752 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4754 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4755 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4756 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4757 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4758 /* patch entrypoint name */
4759 if (assemblyb->pekind == 1)
4760 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4762 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4763 /* patch imported function RVA name */
4764 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4765 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4767 /* the import table */
4768 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4769 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4770 /* patch imported dll RVA name and other entries in the dir */
4771 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4772 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4773 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4774 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4775 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4776 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4778 p = (assembly->code.data + assembly->ilt_offset);
4779 value = (assembly->text_rva + assembly->imp_names_offset);
4780 *p++ = (value) & 0xff;
4781 *p++ = (value >> 8) & (0xff);
4782 *p++ = (value >> 16) & (0xff);
4783 *p++ = (value >> 24) & (0xff);
4785 /* the CLI header info */
4786 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4787 cli_header->ch_size = GUINT32_FROM_LE (72);
4788 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4789 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4790 if (assemblyb->entry_point) {
4791 guint32 table_idx = 0;
4792 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4793 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4794 table_idx = methodb->table_idx;
4796 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4798 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4800 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4802 /* The embedded managed resources */
4803 text_offset = assembly->text_rva + assembly->code.index;
4804 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4805 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4806 text_offset += assembly->resources.index;
4807 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4808 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4809 text_offset += assembly->meta_size;
4810 if (assembly->strong_name_size) {
4811 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4812 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4813 text_offset += assembly->strong_name_size;
4816 /* write the section tables and section content */
4817 section = (MonoSectionTable*)(pefile->data + section_start);
4818 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4819 static const char *section_names [] = {
4820 ".text", ".rsrc", ".reloc"
4822 if (!assembly->sections [i].size)
4824 strcpy (section->st_name, section_names [i]);
4825 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4826 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4827 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4828 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4829 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4830 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4831 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4835 checked_write_file (file, pefile->data, pefile->index);
4837 mono_dynamic_stream_reset (pefile);
4839 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4840 if (!assembly->sections [i].size)
4843 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4844 g_error ("SetFilePointer returned %d\n", GetLastError ());
4847 case MONO_SECTION_TEXT:
4848 /* patch entry point */
4849 p = (assembly->code.data + 2);
4850 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4851 *p++ = (value) & 0xff;
4852 *p++ = (value >> 8) & 0xff;
4853 *p++ = (value >> 16) & 0xff;
4854 *p++ = (value >> 24) & 0xff;
4856 checked_write_file (file, assembly->code.data, assembly->code.index);
4857 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4858 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4859 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4862 g_free (assembly->image.raw_metadata);
4864 case MONO_SECTION_RELOC: {
4868 guint16 type_and_offset;
4872 g_assert (sizeof (reloc) == 12);
4874 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4875 reloc.block_size = GUINT32_FROM_LE (12);
4878 * the entrypoint is always at the start of the text section
4879 * 3 is IMAGE_REL_BASED_HIGHLOW
4880 * 2 is patch_size_rva - text_rva
4882 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4885 checked_write_file (file, &reloc, sizeof (reloc));
4889 case MONO_SECTION_RSRC:
4890 if (assembly->win32_res) {
4892 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4893 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4894 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
4898 g_assert_not_reached ();
4902 /* check that the file is properly padded */
4903 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4904 g_error ("SetFilePointer returned %d\n", GetLastError ());
4905 if (! SetEndOfFile (file))
4906 g_error ("SetEndOfFile returned %d\n", GetLastError ());
4908 mono_dynamic_stream_reset (&assembly->code);
4909 mono_dynamic_stream_reset (&assembly->us);
4910 mono_dynamic_stream_reset (&assembly->blob);
4911 mono_dynamic_stream_reset (&assembly->guid);
4912 string_heap_free (&assembly->sheap);
4914 mono_g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
4915 mono_g_hash_table_destroy (assembly->blob_cache);
4918 MonoReflectionModule *
4919 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4923 MonoImageOpenStatus status;
4924 MonoDynamicAssembly *assembly;
4925 guint32 module_count;
4926 MonoImage **new_modules;
4928 name = mono_string_to_utf8 (fileName);
4930 image = mono_image_open (name, &status);
4933 if (status == MONO_IMAGE_ERROR_ERRNO)
4934 exc = mono_get_exception_file_not_found (fileName);
4936 exc = mono_get_exception_bad_image_format (name);
4938 mono_raise_exception (exc);
4943 assembly = ab->dynamic_assembly;
4944 image->assembly = (MonoAssembly*)assembly;
4946 module_count = image->assembly->image->module_count;
4947 new_modules = g_new0 (MonoImage *, module_count + 1);
4949 if (image->assembly->image->modules)
4950 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4951 new_modules [module_count] = image;
4953 g_free (image->assembly->image->modules);
4954 image->assembly->image->modules = new_modules;
4955 image->assembly->image->module_count ++;
4957 mono_assembly_load_references (image, &status);
4959 mono_image_close (image);
4960 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4963 return mono_module_get_object (mono_domain_get (), image);
4967 * We need to return always the same object for MethodInfo, FieldInfo etc..
4968 * but we need to consider the reflected type.
4969 * type uses a different hash, since it uses custom hash/equal functions.
4974 MonoClass *refclass;
4978 reflected_equal (gconstpointer a, gconstpointer b) {
4979 const ReflectedEntry *ea = a;
4980 const ReflectedEntry *eb = b;
4982 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4986 reflected_hash (gconstpointer a) {
4987 const ReflectedEntry *ea = a;
4988 return GPOINTER_TO_UINT (ea->item);
4991 #define CHECK_OBJECT(t,p,k) \
4997 mono_domain_lock (domain); \
4998 if (!domain->refobject_hash) \
4999 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5000 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5001 mono_domain_unlock (domain); \
5007 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5009 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5012 #define CACHE_OBJECT(p,o,k) \
5014 ReflectedEntry *e = ALLOC_REFENTRY; \
5016 e->refclass = (k); \
5017 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5018 mono_domain_unlock (domain); \
5022 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5024 /* this is done only once */
5025 mono_domain_lock (domain);
5026 CACHE_OBJECT (assembly, res, NULL);
5030 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5032 /* this is done only once */
5033 mono_domain_lock (domain);
5034 CACHE_OBJECT (module, res, NULL);
5038 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5040 MonoDynamicImage *image = moduleb->dynamic_image;
5041 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5044 * FIXME: we already created an image in mono_image_basic_init (), but
5045 * we don't know which module it belongs to, since that is only
5046 * determined at assembly save time.
5048 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5049 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5051 moduleb->module.image = &image->image;
5052 moduleb->dynamic_image = image;
5053 register_module (mono_object_domain (moduleb), moduleb, image);
5058 * mono_assembly_get_object:
5059 * @domain: an app domain
5060 * @assembly: an assembly
5062 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5064 MonoReflectionAssembly*
5065 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5067 static MonoClass *System_Reflection_Assembly;
5068 MonoReflectionAssembly *res;
5070 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5071 if (!System_Reflection_Assembly)
5072 System_Reflection_Assembly = mono_class_from_name (
5073 mono_defaults.corlib, "System.Reflection", "Assembly");
5074 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5075 res->assembly = assembly;
5077 CACHE_OBJECT (assembly, res, NULL);
5083 MonoReflectionModule*
5084 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5086 static MonoClass *System_Reflection_Module;
5087 MonoReflectionModule *res;
5090 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5091 if (!System_Reflection_Module)
5092 System_Reflection_Module = mono_class_from_name (
5093 mono_defaults.corlib, "System.Reflection", "Module");
5094 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5097 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5099 res->fqname = mono_string_new (domain, image->name);
5100 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5101 res->scopename = mono_string_new (domain, image->module_name);
5105 if (image->assembly->image == image) {
5106 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5109 g_assert (image->assembly->image->modules);
5111 for (i = 0; i < image->assembly->image->module_count; i++) {
5112 if (image->assembly->image->modules [i] == image)
5113 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5115 g_assert (res->token);
5118 mono_image_addref (image);
5120 CACHE_OBJECT (image, res, NULL);
5124 MonoReflectionModule*
5125 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5127 static MonoClass *System_Reflection_Module;
5128 MonoReflectionModule *res;
5129 MonoTableInfo *table;
5130 guint32 cols [MONO_FILE_SIZE];
5132 guint32 i, name_idx;
5135 if (!System_Reflection_Module)
5136 System_Reflection_Module = mono_class_from_name (
5137 mono_defaults.corlib, "System.Reflection", "Module");
5138 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5140 table = &image->tables [MONO_TABLE_FILE];
5141 g_assert (table_index < table->rows);
5142 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5145 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5146 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5148 /* Check whenever the row has a corresponding row in the moduleref table */
5149 table = &image->tables [MONO_TABLE_MODULEREF];
5150 for (i = 0; i < table->rows; ++i) {
5151 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5152 val = mono_metadata_string_heap (image, name_idx);
5153 if (strcmp (val, name) == 0)
5154 res->image = image->modules [i];
5157 res->fqname = mono_string_new (domain, name);
5158 res->name = mono_string_new (domain, name);
5159 res->scopename = mono_string_new (domain, name);
5160 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5161 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5167 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5169 if ((t1->type != t2->type) ||
5170 (t1->byref != t2->byref))
5174 case MONO_TYPE_VOID:
5175 case MONO_TYPE_BOOLEAN:
5176 case MONO_TYPE_CHAR:
5187 case MONO_TYPE_STRING:
5190 case MONO_TYPE_OBJECT:
5191 case MONO_TYPE_TYPEDBYREF:
5193 case MONO_TYPE_VALUETYPE:
5194 case MONO_TYPE_CLASS:
5195 case MONO_TYPE_SZARRAY:
5196 return t1->data.klass == t2->data.klass;
5198 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5199 case MONO_TYPE_ARRAY:
5200 if (t1->data.array->rank != t2->data.array->rank)
5202 return t1->data.array->eklass == t2->data.array->eklass;
5203 case MONO_TYPE_GENERICINST: {
5205 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5207 if (!mono_metadata_type_equal (t1->data.generic_class->generic_type, t2->data.generic_class->generic_type))
5209 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5210 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5216 case MONO_TYPE_MVAR:
5217 return t1->data.generic_param == t2->data.generic_param;
5219 g_error ("implement type compare for %0x!", t1->type);
5227 mymono_metadata_type_hash (MonoType *t1)
5233 hash |= t1->byref << 6; /* do not collide with t1->type values */
5235 case MONO_TYPE_VALUETYPE:
5236 case MONO_TYPE_CLASS:
5237 case MONO_TYPE_SZARRAY:
5238 /* check if the distribution is good enough */
5239 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5241 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5246 static MonoReflectionGenericClass*
5247 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5249 static MonoClass *System_Reflection_MonoGenericClass;
5250 MonoReflectionGenericClass *res;
5251 MonoGenericClass *gclass;
5254 if (!System_Reflection_MonoGenericClass) {
5255 System_Reflection_MonoGenericClass = mono_class_from_name (
5256 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5257 g_assert (System_Reflection_MonoGenericClass);
5260 gclass = geninst->data.generic_class;
5261 gklass = mono_class_from_mono_type (gclass->generic_type);
5263 mono_class_init (gclass->klass);
5265 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5267 res->type.type = geninst;
5268 if (gklass->wastypebuilder && gklass->reflection_info)
5269 res->generic_type = gklass->reflection_info;
5271 res->generic_type = mono_type_get_object (domain, gclass->generic_type);
5277 * mono_type_get_object:
5278 * @domain: an app domain
5281 * Return an System.MonoType object representing the type @type.
5284 mono_type_get_object (MonoDomain *domain, MonoType *type)
5286 MonoReflectionType *res;
5287 MonoClass *klass = mono_class_from_mono_type (type);
5289 mono_domain_lock (domain);
5290 if (!domain->type_hash)
5291 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5292 (GCompareFunc)mymono_metadata_type_equal);
5293 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5294 mono_domain_unlock (domain);
5297 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5298 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5299 mono_g_hash_table_insert (domain->type_hash, type, res);
5300 mono_domain_unlock (domain);
5303 if (klass->reflection_info && !klass->wastypebuilder) {
5304 /* g_assert_not_reached (); */
5305 /* should this be considered an error condition? */
5307 mono_domain_unlock (domain);
5308 return klass->reflection_info;
5311 mono_class_init (klass);
5312 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5314 mono_g_hash_table_insert (domain->type_hash, type, res);
5315 mono_domain_unlock (domain);
5320 * mono_method_get_object:
5321 * @domain: an app domain
5323 * @refclass: the reflected type (can be NULL)
5325 * Return an System.Reflection.MonoMethod object representing the method @method.
5327 MonoReflectionMethod*
5328 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5331 * We use the same C representation for methods and constructors, but the type
5332 * name in C# is different.
5336 MonoReflectionMethod *ret;
5339 refclass = method->klass;
5341 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5342 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5343 cname = "MonoCMethod";
5345 cname = "MonoMethod";
5346 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5348 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5349 ret->method = method;
5350 ret->name = mono_string_new (domain, method->name);
5351 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5352 CACHE_OBJECT (method, ret, refclass);
5357 * mono_field_get_object:
5358 * @domain: an app domain
5362 * Return an System.Reflection.MonoField object representing the field @field
5365 MonoReflectionField*
5366 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5368 MonoReflectionField *res;
5371 CHECK_OBJECT (MonoReflectionField *, field, klass);
5372 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5373 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5376 res->name = mono_string_new (domain, field->name);
5377 if (field->generic_info)
5378 res->attrs = field->generic_info->generic_type->attrs;
5380 res->attrs = field->type->attrs;
5381 res->type = mono_type_get_object (domain, field->type);
5382 CACHE_OBJECT (field, res, klass);
5387 * mono_property_get_object:
5388 * @domain: an app domain
5390 * @property: a property
5392 * Return an System.Reflection.MonoProperty object representing the property @property
5395 MonoReflectionProperty*
5396 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5398 MonoReflectionProperty *res;
5401 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5402 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5403 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5405 res->property = property;
5406 CACHE_OBJECT (property, res, klass);
5411 * mono_event_get_object:
5412 * @domain: an app domain
5416 * Return an System.Reflection.MonoEvent object representing the event @event
5419 MonoReflectionEvent*
5420 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5422 MonoReflectionEvent *res;
5425 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5426 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5427 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5430 CACHE_OBJECT (event, res, klass);
5435 * mono_param_get_objects:
5436 * @domain: an app domain
5439 * Return an System.Reflection.ParameterInfo array object representing the parameters
5440 * in the method @method.
5443 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5445 static MonoClass *System_Reflection_ParameterInfo;
5446 MonoArray *res = NULL;
5447 MonoReflectionMethod *member = NULL;
5448 MonoReflectionParameter *param = NULL;
5449 char **names, **blobs = NULL;
5450 MonoObject *dbnull = mono_get_dbnull_object (domain);
5451 MonoMarshalSpec **mspecs;
5454 if (!System_Reflection_ParameterInfo)
5455 System_Reflection_ParameterInfo = mono_class_from_name (
5456 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5458 if (!method->signature->param_count)
5459 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5461 /* Note: the cache is based on the address of the signature into the method
5462 * since we already cache MethodInfos with the method as keys.
5464 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5466 member = mono_method_get_object (domain, method, NULL);
5467 names = g_new (char *, method->signature->param_count);
5468 mono_method_get_param_names (method, (const char **) names);
5470 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5471 mono_method_get_marshal_info (method, mspecs);
5473 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5474 for (i = 0; i < method->signature->param_count; ++i) {
5475 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5476 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5477 param->MemberImpl = (MonoObject*)member;
5478 param->NameImpl = mono_string_new (domain, names [i]);
5479 param->PositionImpl = i;
5480 param->AttrsImpl = method->signature->params [i]->attrs;
5482 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5483 param->DefaultValueImpl = dbnull;
5485 MonoType *type = param->ClassImpl->type;
5488 blobs = g_new0 (char *, method->signature->param_count);
5489 get_default_param_value_blobs (method, blobs);
5492 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5494 if (!param->DefaultValueImpl) {
5495 param->DefaultValueImpl = dbnull;
5500 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5502 mono_array_set (res, gpointer, i, param);
5507 for (i = method->signature->param_count; i >= 0; i--)
5509 mono_metadata_free_marshal_spec (mspecs [i]);
5512 CACHE_OBJECT (&(method->signature), res, NULL);
5517 * mono_method_body_get_object:
5518 * @domain: an app domain
5521 * Return an System.Reflection.MethodBody object representing the method @method.
5523 MonoReflectionMethodBody*
5524 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5526 static MonoClass *System_Reflection_MethodBody = NULL;
5527 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5528 MonoReflectionMethodBody *ret;
5529 MonoMethodNormal *mn;
5530 MonoMethodHeader *header;
5533 if (!System_Reflection_MethodBody)
5534 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5535 if (!System_Reflection_LocalVariableInfo)
5536 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5538 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5540 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5541 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5543 mn = (MonoMethodNormal *)method;
5544 header = mono_method_get_header (method);
5546 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5547 /* FIXME: Other fields */
5548 ret->init_locals = header->init_locals;
5549 ret->max_stack = header->max_stack;
5550 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5551 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5552 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5553 for (i = 0; i < header->num_locals; ++i) {
5554 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5555 info->local_type = mono_type_get_object (domain, header->locals [i]);
5556 info->is_pinned = header->locals [i]->pinned;
5557 info->local_index = 0;
5560 CACHE_OBJECT (method, ret, NULL);
5565 mono_get_dbnull_object (MonoDomain *domain)
5569 static MonoClassField *dbnull_value_field = NULL;
5571 if (!dbnull_value_field) {
5572 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5573 mono_class_init (klass);
5574 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5575 g_assert (dbnull_value_field);
5577 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5584 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5586 guint32 param_index, i, lastp, crow = 0;
5587 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5590 MonoClass *klass = method->klass;
5591 MonoImage *image = klass->image;
5592 MonoMethodSignature *methodsig = method->signature;
5594 MonoTableInfo *constt;
5595 MonoTableInfo *methodt;
5596 MonoTableInfo *paramt;
5598 if (!methodsig->param_count)
5601 if (klass->generic_class) {
5602 return; /* FIXME - ??? */
5605 mono_class_init (klass);
5607 if (klass->image->dynamic) {
5608 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5609 if (aux && aux->param_defaults)
5610 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5614 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5615 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5616 constt = &image->tables [MONO_TABLE_CONSTANT];
5618 for (i = 0; i < klass->method.count; ++i) {
5619 if (method == klass->methods [i]) {
5620 idx = klass->method.first + i;
5625 g_assert (idx != -1);
5627 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5628 if (idx + 1 < methodt->rows)
5629 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5631 lastp = paramt->rows + 1;
5633 for (i = param_index; i < lastp; ++i) {
5636 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5637 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5639 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5642 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5647 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5648 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5655 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5664 klass = mono_class_from_mono_type (type);
5665 if (klass->valuetype) {
5666 object = mono_object_new (domain, klass);
5667 retval = ((gchar *) object + sizeof (MonoObject));
5672 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5679 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5683 memset (assembly, 0, sizeof (MonoAssemblyName));
5685 assembly->culture = "";
5686 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5688 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5691 while (g_ascii_isspace (*p) || *p == ',') {
5700 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5702 assembly->major = strtoul (p, &s, 10);
5703 if (s == p || *s != '.')
5706 assembly->minor = strtoul (p, &s, 10);
5707 if (s == p || *s != '.')
5710 assembly->build = strtoul (p, &s, 10);
5711 if (s == p || *s != '.')
5714 assembly->revision = strtoul (p, &s, 10);
5718 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5720 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5721 assembly->culture = "";
5724 assembly->culture = p;
5725 while (*p && *p != ',') {
5729 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5731 if (strncmp (p, "null", 4) == 0) {
5736 while (*p && *p != ',') {
5739 len = (p - start + 1);
5740 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5741 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5742 g_strlcpy (assembly->public_key_token, start, len);
5745 while (*p && *p != ',')
5749 while (g_ascii_isspace (*p) || *p == ',') {
5763 * mono_reflection_parse_type:
5766 * Parse a type name as accepted by the GetType () method and output the info
5767 * extracted in the info structure.
5768 * the name param will be mangled, so, make a copy before passing it to this function.
5769 * The fields in info will be valid until the memory pointed to by name is valid.
5771 * See also mono_type_get_name () below.
5773 * Returns: 0 on parse error.
5776 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5778 char *start, *p, *w, *last_point, *startn;
5779 int in_modifiers = 0;
5780 int isbyref = 0, rank;
5782 start = p = w = name;
5784 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5785 info->name = info->name_space = NULL;
5786 info->nested = NULL;
5787 info->modifiers = NULL;
5789 /* last_point separates the namespace from the name */
5795 *p = 0; /* NULL terminate the name */
5797 info->nested = g_list_append (info->nested, startn);
5798 /* we have parsed the nesting namespace + name */
5802 info->name_space = start;
5804 info->name = last_point + 1;
5806 info->name_space = (char *)"";
5832 info->name_space = start;
5834 info->name = last_point + 1;
5836 info->name_space = (char *)"";
5843 if (isbyref) /* only one level allowed by the spec */
5846 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5850 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5861 else if (*p != '*') /* '*' means unknown lower bound */
5867 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5872 if (g_ascii_isspace (*p)) {
5879 return 0; /* missing assembly name */
5880 if (!assembly_name_to_aname (&info->assembly, p))
5887 if (info->assembly.name)
5890 *w = 0; /* terminate class name */
5891 if (!info->name || !*info->name)
5893 /* add other consistency checks */
5898 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5905 image = mono_defaults.corlib;
5908 klass = mono_class_from_name_case (image, info->name_space, info->name);
5910 klass = mono_class_from_name (image, info->name_space, info->name);
5913 for (mod = info->nested; mod; mod = mod->next) {
5916 mono_class_init (klass);
5917 nested = klass->nested_classes;
5920 klass = nested->data;
5922 if (g_strcasecmp (klass->name, mod->data) == 0)
5925 if (strcmp (klass->name, mod->data) == 0)
5929 nested = nested->next;
5936 mono_class_init (klass);
5937 for (mod = info->modifiers; mod; mod = mod->next) {
5938 modval = GPOINTER_TO_UINT (mod->data);
5939 if (!modval) { /* byref: must be last modifier */
5940 return &klass->this_arg;
5941 } else if (modval == -1) {
5942 klass = mono_ptr_class_get (&klass->byval_arg);
5943 } else { /* array rank */
5944 klass = mono_array_class_get (klass, modval);
5946 mono_class_init (klass);
5949 return &klass->byval_arg;
5953 * mono_reflection_get_type:
5954 * @image: a metadata context
5955 * @info: type description structure
5956 * @ignorecase: flag for case-insensitive string compares
5957 * @type_resolve: whenever type resolve was already tried
5959 * Build a MonoType from the type description in @info.
5964 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5967 MonoReflectionAssembly *assembly;
5971 type = mono_reflection_get_type_internal (image, info, ignorecase);
5974 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5981 *type_resolve = TRUE;
5984 /* Reconstruct the type name */
5985 fullName = g_string_new ("");
5986 if (info->name_space && (info->name_space [0] != '\0'))
5987 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5989 g_string_printf (fullName, info->name);
5990 for (mod = info->nested; mod; mod = mod->next)
5991 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5993 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5995 if (assembly->assembly->dynamic) {
5996 /* Enumerate all modules */
5997 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6001 if (abuilder->modules) {
6002 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6003 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6004 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6010 if (!type && abuilder->loaded_modules) {
6011 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6012 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6013 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6020 type = mono_reflection_get_type_internal (assembly->assembly->image,
6023 g_string_free (fullName, TRUE);
6028 * mono_reflection_type_from_name:
6030 * @image: a metadata context (can be NULL).
6032 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6033 * it defaults to get the type from @image or, if @image is NULL or loading
6034 * from it fails, uses corlib.
6038 mono_reflection_type_from_name (char *name, MonoImage *image)
6041 MonoTypeNameParse info;
6042 MonoAssembly *assembly;
6044 gboolean type_resolve = FALSE;
6046 /* Make a copy since parse_type modifies its argument */
6047 tmp = g_strdup (name);
6049 /*g_print ("requested type %s\n", str);*/
6050 if (!mono_reflection_parse_type (tmp, &info)) {
6052 g_list_free (info.modifiers);
6053 g_list_free (info.nested);
6057 if (info.assembly.name) {
6058 assembly = mono_assembly_loaded (&info.assembly);
6060 /* then we must load the assembly ourselve - see #60439 */
6061 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6064 g_list_free (info.modifiers);
6065 g_list_free (info.nested);
6069 image = assembly->image;
6070 } else if (image == NULL) {
6071 image = mono_defaults.corlib;
6074 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6075 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6076 image = mono_defaults.corlib;
6077 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6081 g_list_free (info.modifiers);
6082 g_list_free (info.nested);
6087 * mono_reflection_get_token:
6089 * Return the metadata token of OBJ which should be an object
6090 * representing a metadata element.
6093 mono_reflection_get_token (MonoObject *obj)
6098 klass = obj->vtable->klass;
6100 if (strcmp (klass->name, "MethodBuilder") == 0) {
6101 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6103 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6104 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6105 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6107 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6108 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6109 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6110 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6111 if (tb->generic_params) {
6112 g_assert_not_reached ();
6114 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6116 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6117 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6118 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6119 } else if (strcmp (klass->name, "MonoType") == 0) {
6120 MonoReflectionType *tb = (MonoReflectionType *)obj;
6121 token = mono_class_from_mono_type (tb->type)->type_token;
6122 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6123 strcmp (klass->name, "MonoMethod") == 0) {
6124 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6125 if (m->method->signature->is_inflated) {
6126 g_assert_not_reached ();
6127 } else if (m->method->signature->generic_param_count) {
6128 g_assert_not_reached ();
6129 } else if (m->method->klass->generic_class) {
6130 g_assert_not_reached ();
6132 token = m->method->token;
6134 } else if (strcmp (klass->name, "MonoField") == 0) {
6135 MonoReflectionField *f = (MonoReflectionField*)obj;
6137 token = mono_class_get_field_token (f->field);
6138 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6139 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6141 token = mono_class_get_property_token (p->property);
6142 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6143 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6145 token = mono_class_get_event_token (p->event);
6146 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6147 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6149 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6150 } else if (strcmp (klass->name, "Module") == 0) {
6151 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6154 } else if (strcmp (klass->name, "Assembly") == 0) {
6155 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6157 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6158 MonoException *ex = mono_get_exception_not_implemented (msg);
6160 mono_raise_exception (ex);
6167 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6169 int slen, type = t->type;
6174 case MONO_TYPE_BOOLEAN: {
6175 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6180 case MONO_TYPE_CHAR:
6182 case MONO_TYPE_I2: {
6183 guint16 *val = g_malloc (sizeof (guint16));
6188 #if SIZEOF_VOID_P == 4
6194 case MONO_TYPE_I4: {
6195 guint32 *val = g_malloc (sizeof (guint32));
6200 #if SIZEOF_VOID_P == 8
6201 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6206 case MONO_TYPE_I8: {
6207 guint64 *val = g_malloc (sizeof (guint64));
6212 case MONO_TYPE_VALUETYPE:
6213 if (t->data.klass->enumtype) {
6214 type = t->data.klass->enum_basetype->type;
6217 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6220 case MONO_TYPE_STRING:
6221 if (*p == (char)0xFF) {
6225 slen = mono_metadata_decode_value (p, &p);
6227 return mono_string_new_len (mono_domain_get (), p, slen);
6228 case MONO_TYPE_CLASS: {
6231 if (*p == (char)0xFF) {
6236 slen = mono_metadata_decode_value (p, &p);
6237 n = g_memdup (p, slen + 1);
6239 t = mono_reflection_type_from_name (n, image);
6241 g_warning ("Cannot load type '%s'", n);
6245 return mono_type_get_object (mono_domain_get (), t);
6249 case MONO_TYPE_OBJECT: {
6252 MonoClass *subc = NULL;
6257 } else if (subt == 0x0E) {
6258 type = MONO_TYPE_STRING;
6260 } else if (subt == 0x55) {
6263 slen = mono_metadata_decode_value (p, &p);
6264 n = g_memdup (p, slen + 1);
6266 t = mono_reflection_type_from_name (n, image);
6268 g_warning ("Cannot load type '%s'", n);
6271 subc = mono_class_from_mono_type (t);
6272 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6273 MonoType simple_type = {{0}};
6274 simple_type.type = subt;
6275 subc = mono_class_from_mono_type (&simple_type);
6277 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6279 val = load_cattr_value (image, &subc->byval_arg, p, end);
6280 obj = mono_object_new (mono_domain_get (), subc);
6281 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6285 case MONO_TYPE_SZARRAY: {
6287 guint32 i, alen, basetype;
6290 if (alen == 0xffffffff) {
6294 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6295 basetype = t->data.klass->byval_arg.type;
6300 case MONO_TYPE_BOOLEAN:
6301 for (i = 0; i < alen; i++) {
6302 MonoBoolean val = *p++;
6303 mono_array_set (arr, MonoBoolean, i, val);
6306 case MONO_TYPE_CHAR:
6309 for (i = 0; i < alen; i++) {
6310 guint16 val = read16 (p);
6311 mono_array_set (arr, guint16, i, val);
6318 for (i = 0; i < alen; i++) {
6319 guint32 val = read32 (p);
6320 mono_array_set (arr, guint32, i, val);
6327 for (i = 0; i < alen; i++) {
6328 guint64 val = read64 (p);
6329 mono_array_set (arr, guint64, i, val);
6333 case MONO_TYPE_CLASS:
6334 case MONO_TYPE_OBJECT:
6335 case MONO_TYPE_STRING:
6336 for (i = 0; i < alen; i++) {
6337 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6338 mono_array_set (arr, gpointer, i, item);
6342 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6348 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6354 type_is_reference (MonoType *type)
6356 switch (type->type) {
6357 case MONO_TYPE_BOOLEAN:
6358 case MONO_TYPE_CHAR:
6371 case MONO_TYPE_VALUETYPE:
6379 free_param_data (MonoMethodSignature *sig, void **params) {
6381 for (i = 0; i < sig->param_count; ++i) {
6382 if (!type_is_reference (sig->params [i]))
6383 g_free (params [i]);
6388 * Find the method index in the metadata methodDef table.
6389 * Later put these three helper methods in metadata and export them.
6392 find_method_index (MonoMethod *method) {
6393 MonoClass *klass = method->klass;
6396 for (i = 0; i < klass->method.count; ++i) {
6397 if (method == klass->methods [i])
6398 return klass->method.first + 1 + i;
6404 * Find the field index in the metadata FieldDef table.
6407 find_field_index (MonoClass *klass, MonoClassField *field) {
6410 for (i = 0; i < klass->field.count; ++i) {
6411 if (field == &klass->fields [i])
6412 return klass->field.first + 1 + i;
6418 * Find the property index in the metadata Property table.
6421 find_property_index (MonoClass *klass, MonoProperty *property) {
6424 for (i = 0; i < klass->property.count; ++i) {
6425 if (property == &klass->properties [i])
6426 return klass->property.first + 1 + i;
6432 * Find the event index in the metadata Event table.
6435 find_event_index (MonoClass *klass, MonoEvent *event) {
6438 for (i = 0; i < klass->event.count; ++i) {
6439 if (event == &klass->events [i])
6440 return klass->event.first + 1 + i;
6446 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6448 const char *p = data;
6450 guint32 i, j, num_named;
6454 mono_class_init (method->klass);
6457 attr = mono_object_new (mono_domain_get (), method->klass);
6458 mono_runtime_invoke (method, attr, NULL, NULL);
6462 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6465 /*g_print ("got attr %s\n", method->klass->name);*/
6467 params = g_new (void*, method->signature->param_count);
6471 for (i = 0; i < method->signature->param_count; ++i) {
6472 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6476 attr = mono_object_new (mono_domain_get (), method->klass);
6477 mono_runtime_invoke (method, attr, params, NULL);
6478 free_param_data (method->signature, params);
6480 num_named = read16 (named);
6482 for (j = 0; j < num_named; j++) {
6484 char *name, named_type, data_type;
6485 named_type = *named++;
6486 data_type = *named++; /* type of data */
6487 if (data_type == 0x55) {
6490 type_len = mono_metadata_decode_blob_size (named, &named);
6491 type_name = g_malloc (type_len + 1);
6492 memcpy (type_name, named, type_len);
6493 type_name [type_len] = 0;
6495 /* FIXME: lookup the type and check type consistency */
6496 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6497 /* this seems to be the type of the element of the array */
6498 /* g_print ("skipping 0x%02x after prop\n", *named); */
6501 name_len = mono_metadata_decode_blob_size (named, &named);
6502 name = g_malloc (name_len + 1);
6503 memcpy (name, named, name_len);
6504 name [name_len] = 0;
6506 if (named_type == 0x53) {
6507 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6508 void *val = load_cattr_value (image, field->type, named, &named);
6509 mono_field_set_value (attr, field, val);
6510 if (!type_is_reference (field->type))
6512 } else if (named_type == 0x54) {
6515 MonoType *prop_type;
6517 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6518 /* can we have more that 1 arg in a custom attr named property? */
6519 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6520 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6521 mono_property_set_value (prop, attr, pparams, NULL);
6522 if (!type_is_reference (prop_type))
6523 g_free (pparams [0]);
6532 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6539 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6540 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6541 for (i = 0; i < cinfo->num_attrs; ++i) {
6542 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6543 mono_array_set (result, gpointer, i, attr);
6549 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6551 guint32 mtoken, i, len;
6552 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6554 MonoCustomAttrInfo *ainfo;
6555 GList *tmp, *list = NULL;
6558 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6560 i = mono_metadata_custom_attrs_from_index (image, idx);
6564 while (i < ca->rows) {
6565 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6567 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6570 len = g_list_length (list);
6573 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6574 ainfo->num_attrs = len;
6575 ainfo->image = image;
6576 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6577 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6578 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6579 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6580 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6581 mtoken |= MONO_TOKEN_METHOD_DEF;
6583 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6584 mtoken |= MONO_TOKEN_MEMBER_REF;
6587 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6590 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6591 if (!ainfo->attrs [i].ctor)
6592 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6593 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6594 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6595 ainfo->attrs [i].data = data;
6603 mono_custom_attrs_from_method (MonoMethod *method)
6605 MonoCustomAttrInfo *cinfo;
6608 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6610 idx = find_method_index (method);
6611 idx <<= MONO_CUSTOM_ATTR_BITS;
6612 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6613 return mono_custom_attrs_from_index (method->klass->image, idx);
6617 mono_custom_attrs_from_class (MonoClass *klass)
6619 MonoCustomAttrInfo *cinfo;
6622 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6624 idx = mono_metadata_token_index (klass->type_token);
6625 idx <<= MONO_CUSTOM_ATTR_BITS;
6626 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6627 return mono_custom_attrs_from_index (klass->image, idx);
6631 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6633 MonoCustomAttrInfo *cinfo;
6636 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6638 idx = 1; /* there is only one assembly */
6639 idx <<= MONO_CUSTOM_ATTR_BITS;
6640 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6641 return mono_custom_attrs_from_index (assembly->image, idx);
6644 static MonoCustomAttrInfo*
6645 mono_custom_attrs_from_module (MonoImage *image)
6647 MonoCustomAttrInfo *cinfo;
6650 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6652 idx = 1; /* there is only one module */
6653 idx <<= MONO_CUSTOM_ATTR_BITS;
6654 idx |= MONO_CUSTOM_ATTR_MODULE;
6655 return mono_custom_attrs_from_index (image, idx);
6659 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6661 MonoCustomAttrInfo *cinfo;
6664 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6666 idx = find_property_index (klass, property);
6667 idx <<= MONO_CUSTOM_ATTR_BITS;
6668 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6669 return mono_custom_attrs_from_index (klass->image, idx);
6673 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6675 MonoCustomAttrInfo *cinfo;
6678 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6680 idx = find_event_index (klass, event);
6681 idx <<= MONO_CUSTOM_ATTR_BITS;
6682 idx |= MONO_CUSTOM_ATTR_EVENT;
6683 return mono_custom_attrs_from_index (klass->image, idx);
6687 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6689 MonoCustomAttrInfo *cinfo;
6692 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6694 idx = find_field_index (klass, field);
6695 idx <<= MONO_CUSTOM_ATTR_BITS;
6696 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6697 return mono_custom_attrs_from_index (klass->image, idx);
6701 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6704 guint32 i, idx, method_index;
6705 guint32 param_list, param_last, param_pos, found;
6707 MonoReflectionMethodAux *aux;
6709 if (method->klass->image->dynamic) {
6710 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6711 if (!aux || !aux->param_cattr)
6713 return aux->param_cattr [param];
6716 image = method->klass->image;
6717 method_index = find_method_index (method);
6718 ca = &image->tables [MONO_TABLE_METHOD];
6720 if (method->klass->generic_class || method->klass->generic_container ||
6721 method->signature->generic_param_count) {
6722 /* FIXME FIXME FIXME */
6726 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6727 if (method_index == ca->rows) {
6728 ca = &image->tables [MONO_TABLE_PARAM];
6729 param_last = ca->rows + 1;
6731 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6732 ca = &image->tables [MONO_TABLE_PARAM];
6735 for (i = param_list; i < param_last; ++i) {
6736 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6737 if (param_pos == param) {
6745 idx <<= MONO_CUSTOM_ATTR_BITS;
6746 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6747 return mono_custom_attrs_from_index (image, idx);
6751 * mono_reflection_get_custom_attrs:
6752 * @obj: a reflection object handle
6754 * Return an array with all the custom attributes defined of the
6755 * reflection handle @obj. The objects are fully build.
6758 mono_reflection_get_custom_attrs (MonoObject *obj)
6762 MonoCustomAttrInfo *cinfo = NULL;
6764 MONO_ARCH_SAVE_REGS;
6766 klass = obj->vtable->klass;
6767 if (klass == mono_defaults.monotype_class) {
6768 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6769 klass = mono_class_from_mono_type (rtype->type);
6770 cinfo = mono_custom_attrs_from_class (klass);
6771 } else if (strcmp ("Assembly", klass->name) == 0) {
6772 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6773 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6774 } else if (strcmp ("Module", klass->name) == 0) {
6775 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6776 cinfo = mono_custom_attrs_from_module (module->image);
6777 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6778 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6779 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6780 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6781 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6782 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6783 } else if (strcmp ("MonoField", klass->name) == 0) {
6784 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6785 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6786 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6787 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6788 cinfo = mono_custom_attrs_from_method (rmethod->method);
6789 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6790 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6791 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6792 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6793 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6794 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6795 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6796 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6797 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6798 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6799 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
6800 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
6801 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
6802 } else { /* handle other types here... */
6803 g_error ("get custom attrs not yet supported for %s", klass->name);
6807 result = mono_custom_attrs_construct (cinfo);
6809 mono_custom_attrs_free (cinfo);
6811 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6812 result = mono_array_new (mono_domain_get (), klass, 0);
6818 static MonoMethodSignature*
6819 parameters_to_signature (MonoArray *parameters) {
6820 MonoMethodSignature *sig;
6823 count = parameters? mono_array_length (parameters): 0;
6825 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6826 sig->param_count = count;
6827 sig->sentinelpos = -1; /* FIXME */
6828 for (i = 0; i < count; ++i) {
6829 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6830 sig->params [i] = pt->type;
6835 static MonoMethodSignature*
6836 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6837 MonoMethodSignature *sig;
6839 sig = parameters_to_signature (ctor->parameters);
6840 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6841 sig->ret = &mono_defaults.void_class->byval_arg;
6845 static MonoMethodSignature*
6846 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6847 MonoMethodSignature *sig;
6849 sig = parameters_to_signature (method->parameters);
6850 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6851 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6852 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6856 static MonoMethodSignature*
6857 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6858 MonoMethodSignature *sig;
6860 sig = parameters_to_signature (method->parameters);
6861 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6862 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6863 sig->generic_param_count = 0;
6868 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6870 MonoClass *klass = mono_object_class (prop);
6871 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6872 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6873 *name = mono_string_to_utf8 (pb->name);
6874 *type = pb->type->type;
6876 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6877 *name = g_strdup (p->property->name);
6878 if (p->property->get)
6879 *type = p->property->get->signature->ret;
6881 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6886 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6888 MonoClass *klass = mono_object_class (field);
6889 if (strcmp (klass->name, "FieldBuilder") == 0) {
6890 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6891 *name = mono_string_to_utf8 (fb->name);
6892 *type = fb->type->type;
6894 MonoReflectionField *f = (MonoReflectionField *)field;
6895 *name = g_strdup (f->field->name);
6896 *type = f->field->type;
6901 * Encode a value in a custom attribute stream of bytes.
6902 * The value to encode is either supplied as an object in argument val
6903 * (valuetypes are boxed), or as a pointer to the data in the
6905 * @type represents the type of the value
6906 * @buffer is the start of the buffer
6907 * @p the current position in the buffer
6908 * @buflen contains the size of the buffer and is used to return the new buffer size
6909 * if this needs to be realloced.
6910 * @retbuffer and @retp return the start and the position of the buffer
6913 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6915 MonoTypeEnum simple_type;
6917 if ((p-buffer) + 10 >= *buflen) {
6920 newbuf = g_realloc (buffer, *buflen);
6921 p = newbuf + (p-buffer);
6925 argval = ((char*)arg + sizeof (MonoObject));
6926 simple_type = type->type;
6928 switch (simple_type) {
6929 case MONO_TYPE_BOOLEAN:
6934 case MONO_TYPE_CHAR:
6937 swap_with_size (p, argval, 2, 1);
6943 swap_with_size (p, argval, 4, 1);
6949 swap_with_size (p, argval, 8, 1);
6952 case MONO_TYPE_VALUETYPE:
6953 if (type->data.klass->enumtype) {
6954 simple_type = type->data.klass->enum_basetype->type;
6957 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6960 case MONO_TYPE_STRING: {
6967 str = mono_string_to_utf8 ((MonoString*)arg);
6968 slen = strlen (str);
6969 if ((p-buffer) + 10 + slen >= *buflen) {
6973 newbuf = g_realloc (buffer, *buflen);
6974 p = newbuf + (p-buffer);
6977 mono_metadata_encode_value (slen, p, &p);
6978 memcpy (p, str, slen);
6983 case MONO_TYPE_CLASS: {
6991 k = mono_object_class (arg);
6992 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6993 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6994 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6996 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6997 slen = strlen (str);
6998 if ((p-buffer) + 10 + slen >= *buflen) {
7002 newbuf = g_realloc (buffer, *buflen);
7003 p = newbuf + (p-buffer);
7006 mono_metadata_encode_value (slen, p, &p);
7007 memcpy (p, str, slen);
7012 case MONO_TYPE_SZARRAY: {
7014 MonoClass *eclass, *arg_eclass;
7017 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7020 len = mono_array_length ((MonoArray*)arg);
7022 *p++ = (len >> 8) & 0xff;
7023 *p++ = (len >> 16) & 0xff;
7024 *p++ = (len >> 24) & 0xff;
7026 *retbuffer = buffer;
7027 eclass = type->data.klass;
7028 arg_eclass = mono_object_class (arg)->element_class;
7029 if (eclass->valuetype && arg_eclass->valuetype) {
7030 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7031 int elsize = mono_class_array_element_size (eclass);
7032 for (i = 0; i < len; ++i) {
7033 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7037 for (i = 0; i < len; ++i) {
7038 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7043 /* it may be a boxed value or a Type */
7044 case MONO_TYPE_OBJECT: {
7050 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7055 klass = mono_object_class (arg);
7057 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7060 } else if (klass->enumtype) {
7062 } else if (klass == mono_defaults.string_class) {
7063 simple_type = MONO_TYPE_STRING;
7066 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7067 *p++ = simple_type = klass->byval_arg.type;
7070 g_error ("unhandled type in custom attr");
7072 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7073 slen = strlen (str);
7074 if ((p-buffer) + 10 + slen >= *buflen) {
7078 newbuf = g_realloc (buffer, *buflen);
7079 p = newbuf + (p-buffer);
7082 mono_metadata_encode_value (slen, p, &p);
7083 memcpy (p, str, slen);
7086 simple_type = klass->enum_basetype->type;
7090 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7093 *retbuffer = buffer;
7097 * mono_reflection_get_custom_attrs_blob:
7098 * @ctor: custom attribute constructor
7099 * @ctorArgs: arguments o the constructor
7105 * Creates the blob of data that needs to be saved in the metadata and that represents
7106 * the custom attributed described by @ctor, @ctorArgs etc.
7107 * Returns: a Byte array representing the blob of data.
7110 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7113 MonoMethodSignature *sig;
7118 MONO_ARCH_SAVE_REGS;
7120 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7121 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7123 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7125 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7127 p = buffer = g_malloc (buflen);
7128 /* write the prolog */
7131 for (i = 0; i < sig->param_count; ++i) {
7132 arg = mono_array_get (ctorArgs, MonoObject*, i);
7133 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7137 i += mono_array_length (properties);
7139 i += mono_array_length (fields);
7141 *p++ = (i >> 8) & 0xff;
7144 for (i = 0; i < mono_array_length (properties); ++i) {
7149 prop = mono_array_get (properties, gpointer, i);
7150 get_prop_name_and_type (prop, &pname, &ptype);
7151 *p++ = 0x54; /* PROPERTY signature */
7153 /* Preallocate a large enough buffer */
7154 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7155 char *str = type_get_qualified_name (ptype, NULL);
7161 len += strlen (pname);
7163 if ((p-buffer) + 20 + len >= buflen) {
7167 newbuf = g_realloc (buffer, buflen);
7168 p = newbuf + (p-buffer);
7172 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7173 char *str = type_get_qualified_name (ptype, NULL);
7174 int slen = strlen (str);
7178 * This seems to be optional...
7181 mono_metadata_encode_value (slen, p, &p);
7182 memcpy (p, str, slen);
7186 mono_metadata_encode_value (ptype->type, p, &p);
7187 if (ptype->type == MONO_TYPE_SZARRAY)
7188 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7190 len = strlen (pname);
7191 mono_metadata_encode_value (len, p, &p);
7192 memcpy (p, pname, len);
7194 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7201 for (i = 0; i < mono_array_length (fields); ++i) {
7206 field = mono_array_get (fields, gpointer, i);
7207 get_field_name_and_type (field, &fname, &ftype);
7208 *p++ = 0x53; /* FIELD signature */
7209 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7210 char *str = type_get_qualified_name (ftype, NULL);
7211 int slen = strlen (str);
7212 if ((p-buffer) + 10 + slen >= buflen) {
7216 newbuf = g_realloc (buffer, buflen);
7217 p = newbuf + (p-buffer);
7222 * This seems to be optional...
7225 mono_metadata_encode_value (slen, p, &p);
7226 memcpy (p, str, slen);
7230 mono_metadata_encode_value (ftype->type, p, &p);
7231 if (ftype->type == MONO_TYPE_SZARRAY)
7232 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7234 len = strlen (fname);
7235 mono_metadata_encode_value (len, p, &p);
7236 memcpy (p, fname, len);
7238 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7243 g_assert (p - buffer <= buflen);
7244 buflen = p - buffer;
7245 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7246 p = mono_array_addr (result, char, 0);
7247 memcpy (p, buffer, buflen);
7249 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7255 * mono_reflection_setup_internal_class:
7256 * @tb: a TypeBuilder object
7258 * Creates a MonoClass that represents the TypeBuilder.
7259 * This is a trick that lets us simplify a lot of reflection code
7260 * (and will allow us to support Build and Run assemblies easier).
7263 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7265 MonoClass *klass, *parent;
7267 MONO_ARCH_SAVE_REGS;
7270 /* check so we can compile corlib correctly */
7271 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7272 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7273 parent = tb->parent->type->data.klass;
7275 parent = my_mono_class_from_mono_type (tb->parent->type);
7281 /* the type has already being created: it means we just have to change the parent */
7282 if (tb->type.type) {
7283 klass = mono_class_from_mono_type (tb->type.type);
7284 klass->parent = NULL;
7285 /* fool mono_class_setup_parent */
7286 g_free (klass->supertypes);
7287 klass->supertypes = NULL;
7288 mono_class_setup_parent (klass, parent);
7289 mono_class_setup_mono_type (klass);
7293 klass = g_new0 (MonoClass, 1);
7295 klass->image = &tb->module->dynamic_image->image;
7297 klass->inited = 1; /* we lie to the runtime */
7298 klass->name = mono_string_to_utf8 (tb->name);
7299 klass->name_space = mono_string_to_utf8 (tb->nspace);
7300 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7301 klass->flags = tb->attrs;
7303 klass->element_class = klass;
7304 klass->reflection_info = tb; /* need to pin. */
7306 /* Put into cache so mono_class_get () will find it */
7307 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7309 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7310 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7312 if (parent != NULL) {
7313 mono_class_setup_parent (klass, parent);
7314 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7315 const char *old_n = klass->name;
7316 /* trick to get relative numbering right when compiling corlib */
7317 klass->name = "BuildingObject";
7318 mono_class_setup_parent (klass, mono_defaults.object_class);
7319 klass->name = old_n;
7322 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7323 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7324 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7325 klass->instance_size = sizeof (MonoObject);
7326 klass->size_inited = 1;
7327 mono_class_setup_vtable (klass, NULL, 0);
7330 mono_class_setup_mono_type (klass);
7332 mono_class_setup_supertypes (klass);
7335 * FIXME: handle interfaces.
7338 tb->type.type = &klass->byval_arg;
7340 if (tb->nesting_type) {
7341 g_assert (tb->nesting_type->type);
7342 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7345 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7349 * mono_reflection_setup_generic_class:
7350 * @tb: a TypeBuilder object
7352 * Setup the generic class before adding the first generic parameter.
7355 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7359 MONO_ARCH_SAVE_REGS;
7361 klass = my_mono_class_from_mono_type (tb->type.type);
7362 if (tb->generic_container)
7365 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7366 tb->generic_container->klass = klass;
7368 tb->generic_container->context.container = tb->generic_container;
7372 * mono_reflection_create_generic_class:
7373 * @tb: a TypeBuilder object
7375 * Creates the generic class after all generic parameters have been added.
7378 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7383 MONO_ARCH_SAVE_REGS;
7385 klass = my_mono_class_from_mono_type (tb->type.type);
7387 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7389 if (klass->generic_container || (count == 0))
7392 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7394 klass->generic_container = tb->generic_container;
7396 klass->generic_container->type_argc = count;
7397 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7399 for (i = 0; i < count; i++) {
7400 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7401 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7402 g_assert (klass->generic_container->type_params [i].owner);
7407 * mono_reflection_create_internal_class:
7408 * @tb: a TypeBuilder object
7410 * Actually create the MonoClass that is associated with the TypeBuilder.
7413 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7417 MONO_ARCH_SAVE_REGS;
7419 klass = my_mono_class_from_mono_type (tb->type.type);
7421 if (klass->enumtype && klass->enum_basetype == NULL) {
7422 MonoReflectionFieldBuilder *fb;
7425 g_assert (tb->fields != NULL);
7426 g_assert (mono_array_length (tb->fields) >= 1);
7428 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7430 klass->enum_basetype = fb->type->type;
7431 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7432 if (!klass->element_class)
7433 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7436 * get the element_class from the current corlib.
7438 ec = default_class_from_mono_type (klass->enum_basetype);
7439 klass->instance_size = ec->instance_size;
7440 klass->size_inited = 1;
7442 * this is almost safe to do with enums and it's needed to be able
7443 * to create objects of the enum type (for use in SetConstant).
7445 /* FIXME: Does this mean enums can't have method overrides ? */
7446 mono_class_setup_vtable (klass, NULL, 0);
7450 static MonoMarshalSpec*
7451 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7452 MonoReflectionMarshal *minfo)
7454 MonoMarshalSpec *res;
7456 res = g_new0 (MonoMarshalSpec, 1);
7457 res->native = minfo->type;
7459 switch (minfo->type) {
7460 case MONO_NATIVE_LPARRAY:
7461 res->data.array_data.elem_type = minfo->eltype;
7462 res->data.array_data.param_num = 0; /* Not yet */
7463 res->data.array_data.num_elem = minfo->count;
7466 case MONO_NATIVE_BYVALTSTR:
7467 case MONO_NATIVE_BYVALARRAY:
7468 res->data.array_data.num_elem = minfo->count;
7471 case MONO_NATIVE_CUSTOM:
7472 if (minfo->marshaltyperef)
7473 res->data.custom_data.custom_name =
7474 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7476 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7486 MonoReflectionMarshal*
7487 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7488 MonoMarshalSpec *spec)
7490 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7491 MonoReflectionMarshal *minfo;
7494 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7495 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7496 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7497 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7500 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7501 minfo->type = spec->native;
7503 switch (minfo->type) {
7504 case MONO_NATIVE_LPARRAY:
7505 minfo->eltype = spec->data.array_data.elem_type;
7506 minfo->count = spec->data.array_data.num_elem;
7509 case MONO_NATIVE_BYVALTSTR:
7510 case MONO_NATIVE_BYVALARRAY:
7511 minfo->count = spec->data.array_data.num_elem;
7514 case MONO_NATIVE_CUSTOM:
7515 if (spec->data.custom_data.custom_name) {
7516 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7518 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7520 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7522 if (spec->data.custom_data.cookie)
7523 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7534 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7535 ReflectionMethodBuilder *rmb,
7536 MonoMethodSignature *sig)
7539 MonoMethodNormal *pm;
7540 MonoMarshalSpec **specs;
7541 MonoReflectionMethodAux *method_aux;
7544 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7545 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7546 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7548 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7550 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7552 pm = (MonoMethodNormal*)m;
7555 m->flags = rmb->attrs;
7556 m->iflags = rmb->iattrs;
7557 m->name = mono_string_to_utf8 (rmb->name);
7561 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7563 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7564 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7567 m->signature->pinvoke = 1;
7568 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7569 m->signature->pinvoke = 1;
7571 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7573 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7574 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7576 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7578 if (klass->image->dynamic)
7579 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7582 } else if (!m->klass->dummy &&
7583 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7584 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7585 MonoMethodHeader *header;
7587 gint32 max_stack, i;
7588 gint32 num_locals = 0;
7589 gint32 num_clauses = 0;
7593 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7594 code_size = rmb->ilgen->code_len;
7595 max_stack = rmb->ilgen->max_stack;
7596 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7597 if (rmb->ilgen->ex_handlers)
7598 num_clauses = method_count_clauses (rmb->ilgen);
7601 code = mono_array_addr (rmb->code, guint8, 0);
7602 code_size = mono_array_length (rmb->code);
7603 /* we probably need to run a verifier on the code... */
7613 header = g_malloc0 (sizeof (MonoMethodHeader) +
7614 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7615 header->code_size = code_size;
7616 header->code = g_malloc (code_size);
7617 memcpy ((char*)header->code, code, code_size);
7618 header->max_stack = max_stack;
7619 header->init_locals = rmb->init_locals;
7620 header->num_locals = num_locals;
7622 for (i = 0; i < num_locals; ++i) {
7623 MonoReflectionLocalBuilder *lb =
7624 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7626 header->locals [i] = g_new0 (MonoType, 1);
7627 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7630 header->num_clauses = num_clauses;
7632 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7633 rmb->ilgen, num_clauses);
7636 pm->header = header;
7639 if (rmb->generic_params) {
7640 int count = mono_array_length (rmb->generic_params);
7641 MonoGenericContainer *container;
7643 pm->generic_container = container = rmb->generic_container;
7644 container->type_argc = count;
7645 container->type_params = g_new0 (MonoGenericParam, count);
7647 for (i = 0; i < count; i++) {
7648 MonoReflectionGenericParam *gp =
7649 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7651 container->type_params [i] = *gp->type.type->data.generic_param;
7656 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7659 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7661 for (i = 0; i < rmb->nrefs; ++i)
7662 mw->data = g_list_append (mw->data, rmb->refs [i]);
7667 /* Parameter info */
7670 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7671 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7672 for (i = 0; i <= m->signature->param_count; ++i) {
7673 MonoReflectionParamBuilder *pb;
7674 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7676 m->signature->params [i - 1]->attrs = pb->attrs;
7678 if (pb->def_value) {
7679 MonoDynamicImage *assembly;
7680 guint32 idx, def_type, len;
7684 if (!method_aux->param_defaults)
7685 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7686 assembly = (MonoDynamicImage*)klass->image;
7687 idx = encode_constant (assembly, pb->def_value, &def_type);
7688 /* Copy the data from the blob since it might get realloc-ed */
7689 p = assembly->blob.data + idx;
7690 len = mono_metadata_decode_blob_size (p, &p2);
7692 method_aux->param_defaults [i] = g_malloc (len);
7693 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7697 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7699 if (!method_aux->param_cattr)
7700 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7701 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7707 /* Parameter marshalling */
7710 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7711 MonoReflectionParamBuilder *pb;
7712 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7713 if (pb->marshal_info) {
7715 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7716 specs [pb->position] =
7717 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7721 if (specs != NULL) {
7723 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7724 method_aux->param_marshall = specs;
7727 if (klass->image->dynamic && method_aux)
7728 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7734 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7736 ReflectionMethodBuilder rmb;
7737 MonoMethodSignature *sig;
7739 sig = ctor_builder_to_signature (mb);
7741 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7743 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7744 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7746 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7747 /* ilgen is no longer needed */
7755 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7757 ReflectionMethodBuilder rmb;
7758 MonoMethodSignature *sig;
7760 sig = method_builder_to_signature (mb);
7762 reflection_methodbuilder_from_method_builder (&rmb, mb);
7764 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7765 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7767 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7768 /* ilgen is no longer needed */
7774 static MonoClassField*
7775 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7777 MonoClassField *field;
7784 field = g_new0 (MonoClassField, 1);
7786 field->name = mono_string_to_utf8 (fb->name);
7788 /* FIXME: handle type modifiers */
7789 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7790 field->type->attrs = fb->attrs;
7792 field->type = fb->type->type;
7794 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7795 field->data = mono_array_addr (fb->rva_data, char, 0);
7796 if (fb->offset != -1)
7797 field->offset = fb->offset;
7798 field->parent = klass;
7800 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7802 if (fb->def_value) {
7803 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7804 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7805 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7806 /* Copy the data from the blob since it might get realloc-ed */
7807 p = assembly->blob.data + idx;
7808 len = mono_metadata_decode_blob_size (p, &p2);
7810 field->data = g_malloc (len);
7811 memcpy ((gpointer)field->data, p, len);
7818 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
7821 MonoClass *klass, *gklass;
7822 MonoReflectionTypeBuilder *tb = NULL;
7823 MonoGenericClass *gclass, *cached;
7828 klass = mono_class_from_mono_type (type->type);
7829 if (!klass->generic_container && !klass->generic_class &&
7830 !(klass->nested_in && klass->nested_in->generic_container))
7833 mono_loader_lock ();
7835 domain = mono_object_domain (type);
7837 gclass = g_new0 (MonoGenericClass, 1);
7838 gclass->inst = g_new0 (MonoGenericInst, 1);
7840 gclass->inst->type_argc = type_argc;
7841 gclass->inst->type_argv = types;
7843 for (i = 0; i < gclass->inst->type_argc; ++i) {
7844 if (!gclass->inst->is_open)
7845 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
7848 gclass->generic_type = &klass->byval_arg;
7850 if (klass->generic_class) {
7851 MonoGenericClass *kgclass = klass->generic_class;
7852 MonoGenericClass *ogclass = gclass;
7854 ogclass->context = g_new0 (MonoGenericContext, 1);
7855 ogclass->context->container = ogclass->container;
7856 ogclass->context->gclass = ogclass;
7858 gclass = g_new0 (MonoGenericClass, 1);
7859 gclass->inst = g_new0 (MonoGenericInst, 1);
7861 gclass->inst->type_argc = kgclass->inst->type_argc;
7862 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
7864 for (i = 0; i < gclass->inst->type_argc; i++) {
7865 MonoType *t = kgclass->inst->type_argv [i];
7867 t = mono_class_inflate_generic_type (t, ogclass->context);
7869 if (!gclass->inst->is_open)
7870 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
7872 gclass->inst->type_argv [i] = t;
7875 gclass->generic_type = kgclass->generic_type;
7878 geninst = g_new0 (MonoType, 1);
7879 geninst->type = MONO_TYPE_GENERICINST;
7881 cached = mono_metadata_lookup_generic_class (gclass);
7884 mono_loader_unlock ();
7885 geninst->data.generic_class = cached;
7889 gklass = mono_class_from_mono_type (gclass->generic_type);
7890 g_assert ((gclass->container = gklass->generic_container) != NULL);
7892 geninst->data.generic_class = gclass;
7894 gclass->parent = parent;
7896 gclass->context = g_new0 (MonoGenericContext, 1);
7897 gclass->context->container = gclass->container;
7898 gclass->context->gclass = gclass;
7900 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7901 tb = (MonoReflectionTypeBuilder *) type;
7903 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7904 gclass->is_dynamic = TRUE;
7905 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
7906 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
7907 MonoReflectionType *rgt = rgi->generic_type;
7909 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7910 tb = (MonoReflectionTypeBuilder *) rgt;
7912 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7913 gclass->is_dynamic = TRUE;
7915 icount = klass->interface_count;
7918 gclass->ifaces = g_new0 (MonoType *, icount);
7919 gclass->count_ifaces = icount;
7921 for (i = 0; i < icount; i++) {
7922 MonoReflectionType *itype;
7925 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7927 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7928 gclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7929 if (!gclass->ifaces [i])
7930 gclass->ifaces [i] = itype->type;
7933 mono_class_create_generic (gclass);
7934 mono_class_create_generic_2 (gclass);
7936 mono_loader_unlock ();
7942 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7944 MonoClass *klass, *pklass = NULL;
7945 MonoReflectionType *parent = NULL;
7946 MonoType *the_parent = NULL, *geninst;
7947 MonoReflectionTypeBuilder *tb = NULL;
7948 MonoGenericClass *gclass;
7951 domain = mono_object_domain (type);
7952 klass = mono_class_from_mono_type (type->type);
7954 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7955 tb = (MonoReflectionTypeBuilder *) type;
7958 parent = tb->parent;
7959 pklass = mono_class_from_mono_type (parent->type);
7962 pklass = klass->parent;
7964 parent = mono_type_get_object (domain, &pklass->byval_arg);
7965 else if (klass->generic_class && klass->generic_class->parent) {
7966 parent = mono_type_get_object (domain, klass->generic_class->parent);
7967 pklass = mono_class_from_mono_type (klass->generic_class->parent);
7971 if (pklass && pklass->generic_class)
7972 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7974 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
7978 gclass = geninst->data.generic_class;
7984 dup_type (const MonoType *original)
7986 MonoType *r = g_new0 (MonoType, 1);
7988 r->attrs = original->attrs;
7989 r->byref = original->byref;
7990 mono_stats.generics_metadata_size += sizeof (MonoType);
7994 MonoReflectionMethod*
7995 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7997 MonoMethod *method, *inflated;
7998 MonoReflectionMethodBuilder *mb = NULL;
7999 MonoGenericContainer *container;
8000 MonoGenericMethod *gmethod;
8001 MonoGenericContext *context;
8002 MonoGenericInst *ginst;
8005 MONO_ARCH_SAVE_REGS;
8006 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8007 MonoReflectionTypeBuilder *tb;
8010 mb = (MonoReflectionMethodBuilder *) rmethod;
8011 tb = (MonoReflectionTypeBuilder *) mb->type;
8012 klass = mono_class_from_mono_type (tb->type.type);
8014 method = methodbuilder_to_mono_method (klass, mb);
8016 method = rmethod->method;
8019 count = method->signature->generic_param_count;
8020 if (count != mono_array_length (types))
8023 container = ((MonoMethodNormal*) method)->generic_container;
8024 g_assert (container);
8026 if (!container->method_hash)
8027 container->method_hash = g_hash_table_new (
8028 (GHashFunc) mono_metadata_generic_method_hash,
8029 (GCompareFunc) mono_metadata_generic_method_equal);
8031 ginst = g_new0 (MonoGenericInst,1 );
8032 ginst->type_argc = count;
8033 ginst->type_argv = g_new0 (MonoType *, count);
8034 for (i = 0; i < count; i++) {
8035 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8036 ginst->type_argv [i] = dup_type (garg->type);
8038 if (!ginst->is_open)
8039 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8041 ginst = mono_metadata_lookup_generic_inst (ginst);
8043 gmethod = g_new0 (MonoGenericMethod, 1);
8044 gmethod->container = container;
8045 gmethod->inst = ginst;
8047 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8051 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8054 gmethod->reflection_info = rmethod;
8056 context = g_new0 (MonoGenericContext, 1);
8057 context->container = container;
8058 context->gclass = method->klass->generic_class;
8059 context->gmethod = gmethod;
8061 inflated = mono_class_inflate_generic_method (method, context, NULL);
8062 g_hash_table_insert (container->method_hash, gmethod, inflated);
8064 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8068 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8070 MonoGenericMethod *gmethod;
8071 MonoGenericClass *gclass;
8072 MonoGenericContext *context;
8075 gclass = type->type.type->data.generic_class;
8077 gmethod = g_new0 (MonoGenericMethod, 1);
8078 gmethod->inst = g_new0 (MonoGenericInst, 1);
8079 gmethod->reflection_info = obj;
8081 gmethod->inst->type_argc = method->signature->generic_param_count;
8082 gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8084 for (i = 0; i < gmethod->inst->type_argc; i++) {
8085 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8086 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8088 g_assert (gparam->pklass);
8089 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8092 context = g_new0 (MonoGenericContext, 1);
8093 context->container = gclass->container;
8094 context->gclass = gclass;
8095 context->gmethod = gmethod;
8097 return mono_class_inflate_generic_method (method, context, gclass->klass);
8101 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8106 klass = mono_class_from_mono_type (type->type.type);
8108 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8109 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8110 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8111 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8112 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8113 method = ((MonoReflectionMethod *) obj)->method;
8115 method = NULL; /* prevent compiler warning */
8116 g_assert_not_reached ();
8119 return inflate_mono_method (type, method, obj);
8123 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8124 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8127 MonoGenericClass *gclass;
8128 MonoDynamicGenericClass *dgclass;
8129 MonoClass *klass, *gklass, *pklass;
8132 MONO_ARCH_SAVE_REGS;
8134 klass = mono_class_from_mono_type (type->type.type);
8135 gclass = type->type.type->data.generic_class;
8137 if (gclass->initialized)
8140 dgclass = gclass->dynamic_info = g_new0 (MonoDynamicGenericClass, 1);
8142 gklass = mono_class_from_mono_type (gclass->generic_type);
8143 mono_class_init (gklass);
8146 pklass = mono_class_from_mono_type (gclass->parent);
8148 pklass = gklass->parent;
8150 mono_class_setup_parent (klass, pklass);
8152 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8153 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8154 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8155 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8156 dgclass->count_events = events ? mono_array_length (events) : 0;
8158 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8159 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8160 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8161 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8162 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8164 for (i = 0; i < dgclass->count_methods; i++) {
8165 MonoObject *obj = mono_array_get (methods, gpointer, i);
8167 dgclass->methods [i] = inflate_method (type, obj);
8170 for (i = 0; i < dgclass->count_ctors; i++) {
8171 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8173 dgclass->ctors [i] = inflate_method (type, obj);
8176 for (i = 0; i < dgclass->count_fields; i++) {
8177 MonoObject *obj = mono_array_get (fields, gpointer, i);
8178 MonoClassField *field;
8179 MonoInflatedField *ifield;
8181 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8182 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8183 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8184 field = ((MonoReflectionField *) obj)->field;
8186 field = NULL; /* prevent compiler warning */
8187 g_assert_not_reached ();
8190 ifield = g_new0 (MonoInflatedField, 1);
8191 ifield->generic_type = field->type;
8192 ifield->reflection_info = obj;
8194 dgclass->fields [i] = *field;
8195 dgclass->fields [i].generic_info = ifield;
8196 dgclass->fields [i].type = mono_class_inflate_generic_type (field->type, gclass->context);
8199 for (i = 0; i < dgclass->count_properties; i++) {
8200 MonoObject *obj = mono_array_get (properties, gpointer, i);
8201 MonoProperty *property = &dgclass->properties [i];
8203 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8204 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8206 property->parent = klass;
8207 property->attrs = pb->attrs;
8208 property->name = mono_string_to_utf8 (pb->name);
8210 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8212 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8213 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8214 *property = *((MonoReflectionProperty *) obj)->property;
8217 property->get = inflate_mono_method (type, property->get, NULL);
8219 property->set = inflate_mono_method (type, property->set, NULL);
8221 g_assert_not_reached ();
8224 for (i = 0; i < dgclass->count_events; i++) {
8225 MonoObject *obj = mono_array_get (events, gpointer, i);
8226 MonoEvent *event = &dgclass->events [i];
8228 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8229 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8231 event->parent = klass;
8232 event->attrs = eb->attrs;
8233 event->name = mono_string_to_utf8 (eb->name);
8235 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8236 if (eb->remove_method)
8237 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8238 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8239 *event = *((MonoReflectionEvent *) obj)->event;
8242 event->add = inflate_mono_method (type, event->add, NULL);
8244 event->remove = inflate_mono_method (type, event->remove, NULL);
8246 g_assert_not_reached ();
8249 gclass->initialized = TRUE;
8253 ensure_runtime_vtable (MonoClass *klass)
8255 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8256 int i, num, j, onum;
8257 MonoMethod **overrides;
8259 if (!tb || klass->wastypebuilder)
8262 ensure_runtime_vtable (klass->parent);
8264 num = tb->ctors? mono_array_length (tb->ctors): 0;
8265 num += tb->num_methods;
8266 klass->method.count = num;
8267 klass->methods = g_new (MonoMethod*, num);
8268 num = tb->ctors? mono_array_length (tb->ctors): 0;
8269 for (i = 0; i < num; ++i)
8270 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8271 num = tb->num_methods;
8273 for (i = 0; i < num; ++i)
8274 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8276 if (tb->interfaces) {
8277 klass->interface_count = mono_array_length (tb->interfaces);
8278 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8279 for (i = 0; i < klass->interface_count; ++i) {
8280 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8281 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8285 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8286 for (i = 0; i < klass->method.count; ++i)
8287 klass->methods [i]->slot = i;
8292 for (i = 0; i < tb->num_methods; ++i) {
8293 MonoReflectionMethodBuilder *mb =
8294 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8295 if (mb->override_method)
8300 overrides = g_new0 (MonoMethod*, onum * 2);
8304 for (i = 0; i < tb->num_methods; ++i) {
8305 MonoReflectionMethodBuilder *mb =
8306 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8307 if (mb->override_method) {
8308 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8309 overrides [onum * 2] =
8310 mb->override_method->method;
8311 overrides [onum * 2 + 1] =
8314 g_assert (mb->mhandle);
8321 mono_class_setup_vtable (klass, overrides, onum);
8326 typebuilder_setup_fields (MonoClass *klass)
8328 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8329 MonoReflectionFieldBuilder *fb;
8330 MonoClassField *field;
8335 klass->field.count = tb->num_fields;
8336 klass->field.first = 0;
8337 klass->field.last = klass->field.count;
8339 if (!klass->field.count)
8342 klass->fields = g_new0 (MonoClassField, klass->field.count);
8344 for (i = 0; i < klass->field.count; ++i) {
8345 fb = mono_array_get (tb->fields, gpointer, i);
8346 field = &klass->fields [i];
8347 field->name = mono_string_to_utf8 (fb->name);
8349 /* FIXME: handle type modifiers */
8350 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8351 field->type->attrs = fb->attrs;
8353 field->type = fb->type->type;
8355 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8356 field->data = mono_array_addr (fb->rva_data, char, 0);
8357 if (fb->offset != -1)
8358 field->offset = fb->offset;
8359 field->parent = klass;
8361 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8363 if (fb->def_value) {
8364 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8365 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8366 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8367 /* Copy the data from the blob since it might get realloc-ed */
8368 p = assembly->blob.data + idx;
8369 len = mono_metadata_decode_blob_size (p, &p2);
8371 field->data = g_malloc (len);
8372 memcpy ((gpointer)field->data, p, len);
8375 mono_class_layout_fields (klass);
8379 typebuilder_setup_properties (MonoClass *klass)
8381 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8382 MonoReflectionPropertyBuilder *pb;
8385 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8386 klass->property.first = 0;
8387 klass->property.last = klass->property.count;
8389 klass->properties = g_new0 (MonoProperty, klass->property.count);
8390 for (i = 0; i < klass->property.count; ++i) {
8391 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8392 klass->properties [i].parent = klass;
8393 klass->properties [i].attrs = pb->attrs;
8394 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8396 klass->properties [i].get = pb->get_method->mhandle;
8398 klass->properties [i].set = pb->set_method->mhandle;
8402 MonoReflectionEvent *
8403 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8405 MonoEvent *event = g_new0 (MonoEvent, 1);
8409 klass = my_mono_class_from_mono_type (tb->type.type);
8411 event->parent = klass;
8412 event->attrs = eb->attrs;
8413 event->name = mono_string_to_utf8 (eb->name);
8415 event->add = eb->add_method->mhandle;
8416 if (eb->remove_method)
8417 event->remove = eb->remove_method->mhandle;
8418 if (eb->raise_method)
8419 event->raise = eb->raise_method->mhandle;
8421 if (eb->other_methods) {
8422 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8423 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8424 MonoReflectionMethodBuilder *mb =
8425 mono_array_get (eb->other_methods,
8426 MonoReflectionMethodBuilder*, j);
8427 event->other [j] = mb->mhandle;
8431 return mono_event_get_object (mono_object_domain (tb), klass, event);
8435 typebuilder_setup_events (MonoClass *klass)
8437 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8438 MonoReflectionEventBuilder *eb;
8441 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8442 klass->event.first = 0;
8443 klass->event.last = klass->event.count;
8445 klass->events = g_new0 (MonoEvent, klass->event.count);
8446 for (i = 0; i < klass->event.count; ++i) {
8447 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8448 klass->events [i].parent = klass;
8449 klass->events [i].attrs = eb->attrs;
8450 klass->events [i].name = mono_string_to_utf8 (eb->name);
8452 klass->events [i].add = eb->add_method->mhandle;
8453 if (eb->remove_method)
8454 klass->events [i].remove = eb->remove_method->mhandle;
8455 if (eb->raise_method)
8456 klass->events [i].raise = eb->raise_method->mhandle;
8458 if (eb->other_methods) {
8459 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8460 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8461 MonoReflectionMethodBuilder *mb =
8462 mono_array_get (eb->other_methods,
8463 MonoReflectionMethodBuilder*, j);
8464 klass->events [i].other [j] = mb->mhandle;
8471 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8474 MonoReflectionType* res;
8477 MONO_ARCH_SAVE_REGS;
8479 klass = my_mono_class_from_mono_type (tb->type.type);
8481 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8484 * Fields to set in klass:
8485 * the various flags: delegate/unicode/contextbound etc.
8487 klass->flags = tb->attrs;
8489 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8490 /* No need to fully construct the type */
8491 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8493 /* enums are done right away */
8494 if (!klass->enumtype)
8495 ensure_runtime_vtable (klass);
8498 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8499 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8500 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8504 /* fields and object layout */
8505 if (klass->parent) {
8506 if (!klass->parent->size_inited)
8507 mono_class_init (klass->parent);
8508 klass->instance_size += klass->parent->instance_size;
8509 klass->class_size += klass->parent->class_size;
8510 klass->min_align = klass->parent->min_align;
8512 klass->instance_size = sizeof (MonoObject);
8513 klass->min_align = 1;
8516 /* FIXME: handle packing_size and instance_size */
8517 typebuilder_setup_fields (klass);
8519 typebuilder_setup_properties (klass);
8521 typebuilder_setup_events (klass);
8523 klass->wastypebuilder = TRUE;
8525 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8526 g_assert (res != (MonoReflectionType*)tb);
8531 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8533 MonoGenericParam *param;
8536 MONO_ARCH_SAVE_REGS;
8538 param = g_new0 (MonoGenericParam, 1);
8540 if (gparam->mbuilder) {
8541 if (!gparam->mbuilder->generic_container)
8542 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8543 param->owner = gparam->mbuilder->generic_container;
8544 } else if (gparam->tbuilder) {
8545 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8546 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8551 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8552 if (gparam->index >= count)
8555 container = nesting->generic_container;
8556 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8559 g_assert (container);
8560 param->owner = container;
8563 param->method = NULL;
8564 param->name = mono_string_to_utf8 (gparam->name);
8565 param->num = gparam->index;
8567 image = &gparam->tbuilder->module->dynamic_image->image;
8568 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8570 param->pklass->reflection_info = gparam;
8572 gparam->type.type = g_new0 (MonoType, 1);
8573 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8574 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8575 gparam->type.type->data.generic_param = param;
8579 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8581 MonoDynamicImage *assembly = sig->module->dynamic_image;
8582 guint32 na = mono_array_length (sig->arguments);
8587 MONO_ARCH_SAVE_REGS;
8589 p = buf = g_malloc (10 + na * 10);
8591 mono_metadata_encode_value (0x07, p, &p);
8592 mono_metadata_encode_value (na, p, &p);
8593 for (i = 0; i < na; ++i) {
8594 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8595 encode_reflection_type (assembly, type, p, &p);
8599 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8600 p = mono_array_addr (result, char, 0);
8601 memcpy (p, buf, buflen);
8608 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8610 MonoDynamicImage *assembly = sig->module->dynamic_image;
8611 guint32 na = mono_array_length (sig->arguments);
8616 MONO_ARCH_SAVE_REGS;
8618 p = buf = g_malloc (10 + na * 10);
8620 mono_metadata_encode_value (0x06, p, &p);
8621 for (i = 0; i < na; ++i) {
8622 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8623 encode_reflection_type (assembly, type, p, &p);
8627 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8628 p = mono_array_addr (result, char, 0);
8629 memcpy (p, buf, buflen);
8636 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8638 ReflectionMethodBuilder rmb;
8639 MonoMethodSignature *sig;
8642 sig = dynamic_method_to_signature (mb);
8644 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8647 * Resolve references.
8649 rmb.nrefs = mb->nrefs;
8650 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8651 for (i = 0; i < mb->nrefs; ++i) {
8652 gpointer ref = resolve_object (mb->module->image,
8653 mono_array_get (mb->refs, MonoObject*, i));
8656 mono_raise_exception (mono_get_exception_type_load (NULL));
8663 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8667 /* ilgen is no longer needed */
8672 * mono_reflection_lookup_dynamic_token:
8674 * Finish the Builder object pointed to by TOKEN and return the corresponding
8675 * runtime structure.
8678 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8680 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8683 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8686 return resolve_object (image, obj);
8690 resolve_object (MonoImage *image, MonoObject *obj)
8692 gpointer result = NULL;
8694 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8695 result = mono_string_intern ((MonoString*)obj);
8697 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8698 MonoReflectionType *tb = (MonoReflectionType*)obj;
8699 result = mono_class_from_mono_type (tb->type);
8701 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8702 result = ((MonoReflectionMethod*)obj)->method;
8704 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8705 result = ((MonoReflectionMethod*)obj)->method;
8707 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8708 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8709 result = mb->mhandle;
8711 /* Type is not yet created */
8712 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8714 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8717 * Hopefully this has been filled in by calling CreateType() on the
8721 * TODO: This won't work if the application finishes another
8722 * TypeBuilder instance instead of this one.
8724 result = mb->mhandle;
8726 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8727 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8729 result = cb->mhandle;
8731 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8733 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8734 result = cb->mhandle;
8736 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8737 result = ((MonoReflectionField*)obj)->field;
8739 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8740 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8741 result = fb->handle;
8744 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8746 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8747 result = fb->handle;
8749 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8750 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8753 klass = tb->type.type->data.klass;
8754 if (klass->wastypebuilder) {
8755 /* Already created */
8759 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8760 result = tb->type.type->data.klass;
8763 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8764 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8765 MonoMethodSignature *sig;
8768 if (helper->arguments)
8769 nargs = mono_array_length (helper->arguments);
8773 sig = mono_metadata_signature_alloc (image, nargs);
8774 sig->explicit_this = helper->call_conv & 64;
8775 sig->hasthis = helper->call_conv & 32;
8777 if (helper->call_conv == 0) /* unmanaged */
8778 sig->call_convention = helper->unmanaged_call_conv - 1;
8780 if (helper->call_conv & 0x02)
8781 sig->call_convention = MONO_CALL_VARARG;
8783 sig->call_convention = MONO_CALL_DEFAULT;
8785 sig->param_count = nargs;
8786 /* TODO: Copy type ? */
8787 sig->ret = helper->return_type->type;
8788 for (i = 0; i < nargs; ++i) {
8789 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8790 sig->params [i] = rt->type;
8795 g_print (obj->vtable->klass->name);
8796 g_assert_not_reached ();
8802 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
8803 const static guint32 declsec_flags_map[] = {
8804 0x00000000, /* empty */
8805 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
8806 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
8807 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
8808 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
8809 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
8810 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
8811 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
8812 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
8813 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
8814 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
8815 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
8816 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
8817 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
8818 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
8819 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
8820 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
8821 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
8822 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
8826 * Returns flags that includes all available security action associated to the handle.
8827 * @token: metadata token (either for a class or a method)
8828 * @image: image where resides the metadata.
8831 mono_declsec_get_flags (MonoImage *image, guint32 token)
8833 guint32 index = mono_metadata_declsec_from_index (image, token);
8834 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
8839 for (i = index; i < t->rows; i++) {
8840 guint32 cols [MONO_DECL_SECURITY_SIZE];
8842 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
8843 if (cols [MONO_DECL_SECURITY_PARENT] != token)
8846 action = cols [MONO_DECL_SECURITY_ACTION];
8847 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
8848 result |= declsec_flags_map [action];
8850 g_assert_not_reached ();
8857 * Get the security actions (in the form of flags) associated with the specified method.
8859 * @method: The method for which we want the declarative security flags.
8860 * Return the declarative security flags for the method (only).
8862 * Note: To keep MonoMethod size down we do not cache the declarative security flags
8863 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
8866 mono_declsec_flags_from_method (MonoMethod *method)
8868 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
8869 /* FIXME: No cache (for the moment) */
8870 guint32 idx = find_method_index (method);
8871 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8872 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
8873 return mono_declsec_get_flags (method->klass->image, idx);
8879 * Get the security actions (in the form of flags) associated with the specified class.
8881 * @klass: The class for which we want the declarative security flags.
8882 * Return the declarative security flags for the class.
8884 * Note: We cache the flags inside the MonoClass structure as this will get
8885 * called very often (at least for each method).
8888 mono_declsec_flags_from_class (MonoClass *klass)
8890 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
8891 if (!klass->declsec_flags) {
8892 guint32 idx = mono_metadata_token_index (klass->type_token);
8893 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8894 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
8895 /* we cache the flags on classes */
8896 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
8898 return klass->declsec_flags;
8904 * Get the security actions (in the form of flags) associated with the specified assembly.
8906 * @assembly: The assembly for which we want the declarative security flags.
8907 * Return the declarative security flags for the assembly.
8910 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
8912 guint32 idx = 1; /* there is only one assembly */
8913 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8914 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
8915 return mono_declsec_get_flags (assembly->image, idx);