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->container_class->byval_arg, p, &p);
466 mono_metadata_encode_value (gclass->inst->type_argc, p, &p);
467 for (i = 0; i < gclass->inst->type_argc; ++i)
468 encode_type (assembly, gclass->inst->type_argv [i], p, &p);
474 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
477 g_assert_not_reached ();
482 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
486 case MONO_TYPE_BOOLEAN:
500 case MONO_TYPE_STRING:
501 case MONO_TYPE_OBJECT:
502 case MONO_TYPE_TYPEDBYREF:
503 mono_metadata_encode_value (type->type, p, &p);
506 mono_metadata_encode_value (type->type, p, &p);
507 encode_type (assembly, type->data.type, p, &p);
509 case MONO_TYPE_SZARRAY:
510 mono_metadata_encode_value (type->type, p, &p);
511 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
513 case MONO_TYPE_VALUETYPE:
514 case MONO_TYPE_CLASS: {
515 MonoClass *k = mono_class_from_mono_type (type);
516 mono_metadata_encode_value (type->type, p, &p);
518 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
519 * otherwise two typerefs could point to the same type, leading to
520 * verification errors.
522 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
525 case MONO_TYPE_ARRAY:
526 mono_metadata_encode_value (type->type, p, &p);
527 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
528 mono_metadata_encode_value (type->data.array->rank, p, &p);
529 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
530 mono_metadata_encode_value (0, p, &p);
532 case MONO_TYPE_GENERICINST:
533 encode_generic_class (assembly, type->data.generic_class, p, &p);
537 mono_metadata_encode_value (type->type, p, &p);
538 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
541 g_error ("need to encode type %x", type->type);
547 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
550 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
554 encode_type (assembly, type->type, p, endbuf);
558 g_assert_not_reached ();
563 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
568 for (i = 0; i < mono_array_length (modreq); ++i) {
569 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
570 *p = MONO_TYPE_CMOD_REQD;
572 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
576 for (i = 0; i < mono_array_length (modopt); ++i) {
577 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
578 *p = MONO_TYPE_CMOD_OPT;
580 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
587 generic_class_get_signature_size (MonoGenericClass *gclass)
593 g_assert_not_reached ();
596 size += 1 + type_get_signature_size (&gclass->container_class->byval_arg);
598 for (i = 0; i < gclass->inst->type_argc; ++i)
599 size += type_get_signature_size (gclass->inst->type_argv [i]);
605 type_get_signature_size (MonoType *type)
610 g_assert_not_reached ();
618 case MONO_TYPE_BOOLEAN:
632 case MONO_TYPE_STRING:
633 case MONO_TYPE_OBJECT:
634 case MONO_TYPE_TYPEDBYREF:
637 return size + 1 + type_get_signature_size (type->data.type);
638 case MONO_TYPE_SZARRAY:
639 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
640 case MONO_TYPE_VALUETYPE:
641 case MONO_TYPE_CLASS:
643 case MONO_TYPE_ARRAY:
644 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
645 case MONO_TYPE_GENERICINST:
646 return size + generic_class_get_signature_size (type->data.generic_class);
651 g_error ("need to encode type %x", type->type);
657 method_get_signature_size (MonoMethodSignature *sig)
662 size = type_get_signature_size (sig->ret);
663 for (i = 0; i < sig->param_count; i++)
664 size += type_get_signature_size (sig->params [i]);
666 if (sig->generic_param_count)
668 if (sig->sentinelpos >= 0)
675 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
680 guint32 nparams = sig->param_count;
681 guint32 size = 11 + method_get_signature_size (sig);
689 p = buf = g_malloc (size);
691 * FIXME: vararg, explicit_this, differenc call_conv values...
693 *p = sig->call_convention;
695 *p |= 0x20; /* hasthis */
696 if (sig->generic_param_count)
697 *p |= 0x10; /* generic */
699 if (sig->generic_param_count)
700 mono_metadata_encode_value (sig->generic_param_count, p, &p);
701 mono_metadata_encode_value (nparams, p, &p);
702 encode_type (assembly, sig->ret, p, &p);
703 for (i = 0; i < nparams; ++i) {
704 if (i == sig->sentinelpos)
705 *p++ = MONO_TYPE_SENTINEL;
706 encode_type (assembly, sig->params [i], p, &p);
709 g_assert (p - buf < size);
710 mono_metadata_encode_value (p-buf, b, &b);
711 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
717 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
720 * FIXME: reuse code from method_encode_signature().
725 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
726 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
727 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
728 guint32 size = 21 + nparams * 20 + notypes * 20;
733 p = buf = g_malloc (size);
734 /* LAMESPEC: all the call conv spec is foobared */
735 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
736 if (mb->call_conv & 2)
737 *p |= 0x5; /* vararg */
738 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
739 *p |= 0x20; /* hasthis */
741 *p |= 0x10; /* generic */
744 mono_metadata_encode_value (ngparams, p, &p);
745 mono_metadata_encode_value (nparams + notypes, p, &p);
746 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
747 encode_reflection_type (assembly, mb->rtype, p, &p);
748 for (i = 0; i < nparams; ++i) {
749 MonoArray *modreq = NULL;
750 MonoArray *modopt = NULL;
751 MonoReflectionType *pt;
753 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
754 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
755 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
756 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
757 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
758 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
759 encode_reflection_type (assembly, pt, p, &p);
762 *p++ = MONO_TYPE_SENTINEL;
763 for (i = 0; i < notypes; ++i) {
764 MonoReflectionType *pt;
766 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
767 encode_reflection_type (assembly, pt, p, &p);
771 g_assert (p - buf < size);
772 mono_metadata_encode_value (p-buf, b, &b);
773 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
779 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
781 MonoDynamicTable *table;
784 guint32 idx, sig_idx, size;
785 guint nl = mono_array_length (ilgen->locals);
792 p = buf = g_malloc (size);
793 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
794 idx = table->next_idx ++;
796 alloc_table (table, table->rows);
797 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
799 mono_metadata_encode_value (0x07, p, &p);
800 mono_metadata_encode_value (nl, p, &p);
801 for (i = 0; i < nl; ++i) {
802 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
805 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
807 encode_reflection_type (assembly, lb->type, p, &p);
809 g_assert (p - buf < size);
810 mono_metadata_encode_value (p-buf, b, &b);
811 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
814 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
820 method_count_clauses (MonoReflectionILGen *ilgen)
822 guint32 num_clauses = 0;
825 MonoILExceptionInfo *ex_info;
826 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
827 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
828 if (ex_info->handlers)
829 num_clauses += mono_array_length (ex_info->handlers);
837 static MonoExceptionClause*
838 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
840 MonoExceptionClause *clauses;
841 MonoExceptionClause *clause;
842 MonoILExceptionInfo *ex_info;
843 MonoILExceptionBlock *ex_block;
844 guint32 finally_start;
845 int i, j, clause_index;;
847 clauses = g_new0 (MonoExceptionClause, num_clauses);
850 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
851 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
852 finally_start = ex_info->start + ex_info->len;
853 g_assert (ex_info->handlers);
854 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
855 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
856 clause = &(clauses [clause_index]);
858 clause->flags = ex_block->type;
859 clause->try_offset = ex_info->start;
861 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
862 clause->try_len = finally_start - ex_info->start;
864 clause->try_len = ex_info->len;
865 clause->handler_offset = ex_block->start;
866 clause->handler_len = ex_block->len;
867 if (ex_block->extype) {
868 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
870 /* FIXME: handle filters */
871 clause->data.filter_offset = 0;
873 finally_start = ex_block->start + ex_block->len;
883 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
889 gint32 num_locals = 0;
890 gint32 num_exception = 0;
893 char fat_header [12];
896 guint32 local_sig = 0;
897 guint32 header_size = 12;
900 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
901 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
905 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
907 code = mb->ilgen->code;
908 code_size = mb->ilgen->code_len;
909 max_stack = mb->ilgen->max_stack;
910 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
911 if (mb->ilgen->ex_handlers)
912 num_exception = method_count_clauses (mb->ilgen);
916 char *name = mono_string_to_utf8 (mb->name);
917 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
918 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
921 mono_raise_exception (exception);
924 code_size = mono_array_length (code);
925 max_stack = 8; /* we probably need to run a verifier on the code... */
928 stream_data_align (&assembly->code);
930 /* check for exceptions, maxstack, locals */
931 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
933 if (code_size < 64 && !(code_size & 1)) {
934 flags = (code_size << 2) | 0x2;
935 } else if (code_size < 32 && (code_size & 1)) {
936 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
940 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
941 /* add to the fixup todo list */
942 if (mb->ilgen && mb->ilgen->num_token_fixups)
943 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
944 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
945 return assembly->text_rva + idx;
949 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
951 * FIXME: need to set also the header size in fat_flags.
952 * (and more sects and init locals flags)
956 fat_flags |= METHOD_HEADER_MORE_SECTS;
958 fat_flags |= METHOD_HEADER_INIT_LOCALS;
959 fat_header [0] = fat_flags;
960 fat_header [1] = (header_size / 4 ) << 4;
961 shortp = (guint16*)(fat_header + 2);
962 *shortp = GUINT16_TO_LE (max_stack);
963 intp = (guint32*)(fat_header + 4);
964 *intp = GUINT32_TO_LE (code_size);
965 intp = (guint32*)(fat_header + 8);
966 *intp = GUINT32_TO_LE (local_sig);
967 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
968 /* add to the fixup todo list */
969 if (mb->ilgen && mb->ilgen->num_token_fixups)
970 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
972 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
974 unsigned char sheader [4];
975 MonoILExceptionInfo * ex_info;
976 MonoILExceptionBlock * ex_block;
979 stream_data_align (&assembly->code);
980 /* always use fat format for now */
981 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
982 num_exception *= 6 * sizeof (guint32);
983 num_exception += 4; /* include the size of the header */
984 sheader [1] = num_exception & 0xff;
985 sheader [2] = (num_exception >> 8) & 0xff;
986 sheader [3] = (num_exception >> 16) & 0xff;
987 mono_image_add_stream_data (&assembly->code, sheader, 4);
988 /* fat header, so we are already aligned */
990 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
991 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
992 if (ex_info->handlers) {
993 int finally_start = ex_info->start + ex_info->len;
994 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
996 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
998 val = GUINT32_TO_LE (ex_block->type);
999 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1001 val = GUINT32_TO_LE (ex_info->start);
1002 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1003 /* need fault, too, probably */
1004 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1005 val = GUINT32_TO_LE (finally_start - ex_info->start);
1007 val = GUINT32_TO_LE (ex_info->len);
1008 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1009 /* handler offset */
1010 val = GUINT32_TO_LE (ex_block->start);
1011 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1013 val = GUINT32_TO_LE (ex_block->len);
1014 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1015 finally_start = ex_block->start + ex_block->len;
1016 if (ex_block->extype) {
1017 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1019 /* FIXME: handle filters */
1022 val = GUINT32_TO_LE (val);
1023 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1024 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1025 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1028 g_error ("No clauses for ex info block %d", i);
1032 return assembly->text_rva + idx;
1036 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1039 MonoDynamicTable *table;
1042 table = &assembly->tables [table_idx];
1044 g_assert (col < table->columns);
1046 values = table->values + table->columns;
1047 for (i = 1; i <= table->rows; ++i) {
1048 if (values [col] == token)
1050 values += table->columns;
1055 static GHashTable *dynamic_custom_attrs = NULL;
1057 static MonoCustomAttrInfo*
1058 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1061 MonoCustomAttrInfo *ainfo;
1062 MonoReflectionCustomAttr *cattr;
1066 /* FIXME: check in assembly the Run flag is set */
1068 count = mono_array_length (cattrs);
1070 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1072 ainfo->image = image;
1073 ainfo->num_attrs = count;
1074 for (i = 0; i < count; ++i) {
1075 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1076 ainfo->attrs [i].ctor = cattr->ctor->method;
1077 /* FIXME: might want to memdup the data here */
1078 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1079 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1086 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1088 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1093 if (!dynamic_custom_attrs)
1094 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1096 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1097 ainfo->cached = TRUE;
1101 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1103 /* they are cached, so we don't free them */
1104 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1110 * idx is the table index of the object
1111 * type is one of MONO_CUSTOM_ATTR_*
1114 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1116 MonoDynamicTable *table;
1117 MonoReflectionCustomAttr *cattr;
1119 guint32 count, i, token;
1121 char *p = blob_size;
1123 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1126 count = mono_array_length (cattrs);
1127 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1128 table->rows += count;
1129 alloc_table (table, table->rows);
1130 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1131 idx <<= MONO_CUSTOM_ATTR_BITS;
1133 for (i = 0; i < count; ++i) {
1134 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1135 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1136 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1137 type = mono_metadata_token_index (token);
1138 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1139 switch (mono_metadata_token_table (token)) {
1140 case MONO_TABLE_METHOD:
1141 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1143 case MONO_TABLE_MEMBERREF:
1144 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1147 g_warning ("got wrong token in custom attr");
1150 values [MONO_CUSTOM_ATTR_TYPE] = type;
1152 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1153 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1154 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1155 values += MONO_CUSTOM_ATTR_SIZE;
1161 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1163 MonoDynamicTable *table;
1165 guint32 count, i, idx;
1166 MonoReflectionPermissionSet *perm;
1171 count = mono_array_length (permissions);
1172 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1173 table->rows += count;
1174 alloc_table (table, table->rows);
1176 for (i = 0; i < mono_array_length (permissions); ++i) {
1177 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1179 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1181 idx = mono_metadata_token_index (parent_token);
1182 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1183 switch (mono_metadata_token_table (parent_token)) {
1184 case MONO_TABLE_TYPEDEF:
1185 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1187 case MONO_TABLE_METHOD:
1188 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1190 case MONO_TABLE_ASSEMBLY:
1191 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1194 g_assert_not_reached ();
1197 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1198 values [MONO_DECL_SECURITY_PARENT] = idx;
1199 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1206 * Fill in the MethodDef and ParamDef tables for a method.
1207 * This is used for both normal methods and constructors.
1210 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1212 MonoDynamicTable *table;
1217 /* room in this table is already allocated */
1218 table = &assembly->tables [MONO_TABLE_METHOD];
1219 *mb->table_idx = table->next_idx ++;
1220 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 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3198 compare_constants (const void *a, const void *b)
3200 const guint32 *a_values = a;
3201 const guint32 *b_values = b;
3202 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3205 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3209 compare_custom_attrs (const void *a, const void *b)
3211 const guint32 *a_values = a;
3212 const guint32 *b_values = b;
3214 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3218 compare_field_marshal (const void *a, const void *b)
3220 const guint32 *a_values = a;
3221 const guint32 *b_values = b;
3223 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3227 compare_nested (const void *a, const void *b)
3229 const guint32 *a_values = a;
3230 const guint32 *b_values = b;
3232 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3236 compare_genericparam (const void *a, const void *b)
3238 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3239 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3241 if ((*b_entry)->owner == (*a_entry)->owner)
3243 (*a_entry)->gparam->type.type->data.generic_param->num -
3244 (*b_entry)->gparam->type.type->data.generic_param->num;
3246 return (*a_entry)->owner - (*b_entry)->owner;
3250 compare_declsecurity_attrs (const void *a, const void *b)
3252 const guint32 *a_values = a;
3253 const guint32 *b_values = b;
3255 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3259 pad_heap (MonoDynamicStream *sh)
3261 if (sh->index & 3) {
3262 int sz = 4 - (sh->index & 3);
3263 memset (sh->data + sh->index, 0, sz);
3270 MonoDynamicStream *stream;
3274 * build_compressed_metadata() fills in the blob of data that represents the
3275 * raw metadata as it will be saved in the PE file. The five streams are output
3276 * and the metadata tables are comnpressed from the guint32 array representation,
3277 * to the compressed on-disk format.
3280 build_compressed_metadata (MonoDynamicImage *assembly)
3282 MonoDynamicTable *table;
3284 guint64 valid_mask = 0;
3285 guint64 sorted_mask;
3286 guint32 heapt_size = 0;
3287 guint32 meta_size = 256; /* allow for header and other stuff */
3288 guint32 table_offset;
3289 guint32 ntables = 0;
3295 struct StreamDesc stream_desc [5];
3297 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3298 for (i = 0; i < assembly->gen_params->len; i++){
3299 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3300 write_generic_param_entry (assembly, entry);
3303 stream_desc [0].name = "#~";
3304 stream_desc [0].stream = &assembly->tstream;
3305 stream_desc [1].name = "#Strings";
3306 stream_desc [1].stream = &assembly->sheap;
3307 stream_desc [2].name = "#US";
3308 stream_desc [2].stream = &assembly->us;
3309 stream_desc [3].name = "#Blob";
3310 stream_desc [3].stream = &assembly->blob;
3311 stream_desc [4].name = "#GUID";
3312 stream_desc [4].stream = &assembly->guid;
3314 /* tables that are sorted */
3315 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3316 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3317 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3318 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3319 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3320 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3322 /* Compute table sizes */
3323 /* the MonoImage has already been created in mono_image_basic_init() */
3324 meta = &assembly->image;
3326 /* sizes should be multiple of 4 */
3327 pad_heap (&assembly->blob);
3328 pad_heap (&assembly->guid);
3329 pad_heap (&assembly->sheap);
3330 pad_heap (&assembly->us);
3332 /* Setup the info used by compute_sizes () */
3333 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3334 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3335 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3337 meta_size += assembly->blob.index;
3338 meta_size += assembly->guid.index;
3339 meta_size += assembly->sheap.index;
3340 meta_size += assembly->us.index;
3342 for (i=0; i < 64; ++i)
3343 meta->tables [i].rows = assembly->tables [i].rows;
3345 for (i = 0; i < 64; i++){
3346 if (meta->tables [i].rows == 0)
3348 valid_mask |= (guint64)1 << i;
3350 meta->tables [i].row_size = mono_metadata_compute_size (
3351 meta, i, &meta->tables [i].size_bitfield);
3352 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3354 heapt_size += 24; /* #~ header size */
3355 heapt_size += ntables * 4;
3356 /* make multiple of 4 */
3359 meta_size += heapt_size;
3360 meta->raw_metadata = g_malloc0 (meta_size);
3361 p = meta->raw_metadata;
3362 /* the metadata signature */
3363 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3364 /* version numbers and 4 bytes reserved */
3365 int16val = (guint16*)p;
3366 *int16val++ = GUINT16_TO_LE (1);
3367 *int16val = GUINT16_TO_LE (1);
3369 /* version string */
3370 int32val = (guint32*)p;
3371 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3373 memcpy (p, meta->version, strlen (meta->version));
3374 p += GUINT32_FROM_LE (*int32val);
3375 align_pointer (meta->raw_metadata, p);
3376 int16val = (guint16*)p;
3377 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3378 *int16val = GUINT16_TO_LE (5); /* number of streams */
3382 * write the stream info.
3384 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3385 table_offset += 3; table_offset &= ~3;
3387 assembly->tstream.index = heapt_size;
3388 for (i = 0; i < 5; ++i) {
3389 int32val = (guint32*)p;
3390 stream_desc [i].stream->offset = table_offset;
3391 *int32val++ = GUINT32_TO_LE (table_offset);
3392 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3393 table_offset += GUINT32_FROM_LE (*int32val);
3394 table_offset += 3; table_offset &= ~3;
3396 strcpy (p, stream_desc [i].name);
3397 p += strlen (stream_desc [i].name) + 1;
3398 align_pointer (meta->raw_metadata, p);
3401 * now copy the data, the table stream header and contents goes first.
3403 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3404 p = meta->raw_metadata + assembly->tstream.offset;
3405 int32val = (guint32*)p;
3406 *int32val = GUINT32_TO_LE (0); /* reserved */
3409 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3410 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3411 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3412 *p++ = 1; /* version */
3415 *p++ = 1; /* version */
3419 if (meta->idx_string_wide)
3421 if (meta->idx_guid_wide)
3423 if (meta->idx_blob_wide)
3426 *p++ = 1; /* reserved */
3427 int64val = (guint64*)p;
3428 *int64val++ = GUINT64_TO_LE (valid_mask);
3429 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3431 int32val = (guint32*)p;
3432 for (i = 0; i < 64; i++){
3433 if (meta->tables [i].rows == 0)
3435 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3437 p = (unsigned char*)int32val;
3439 /* sort the tables that still need sorting */
3440 table = &assembly->tables [MONO_TABLE_CONSTANT];
3442 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3443 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3445 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3446 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3448 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3449 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3451 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3452 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3454 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3455 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3456 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3458 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3460 /* compress the tables */
3461 for (i = 0; i < 64; i++){
3464 guint32 bitfield = meta->tables [i].size_bitfield;
3465 if (!meta->tables [i].rows)
3467 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3468 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3469 meta->tables [i].base = p;
3470 for (row = 1; row <= meta->tables [i].rows; ++row) {
3471 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3472 for (col = 0; col < assembly->tables [i].columns; ++col) {
3473 switch (mono_metadata_table_size (bitfield, col)) {
3475 *p++ = values [col];
3478 *p++ = values [col] & 0xff;
3479 *p++ = (values [col] >> 8) & 0xff;
3482 *p++ = values [col] & 0xff;
3483 *p++ = (values [col] >> 8) & 0xff;
3484 *p++ = (values [col] >> 16) & 0xff;
3485 *p++ = (values [col] >> 24) & 0xff;
3488 g_assert_not_reached ();
3492 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3495 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3496 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3497 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3498 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3499 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3501 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3505 * Some tables in metadata need to be sorted according to some criteria, but
3506 * when methods and fields are first created with reflection, they may be assigned a token
3507 * that doesn't correspond to the final token they will get assigned after the sorting.
3508 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3509 * with the reflection objects that represent them. Once all the tables are set up, the
3510 * reflection objects will contains the correct table index. fixup_method() will fixup the
3511 * tokens for the method with ILGenerator @ilgen.
3514 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3515 guint32 code_idx = GPOINTER_TO_UINT (value);
3516 MonoReflectionILTokenInfo *iltoken;
3517 MonoReflectionFieldBuilder *field;
3518 MonoReflectionCtorBuilder *ctor;
3519 MonoReflectionMethodBuilder *method;
3520 MonoReflectionTypeBuilder *tb;
3521 MonoReflectionArrayMethod *am;
3523 unsigned char *target;
3525 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3526 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3527 target = assembly->code.data + code_idx + iltoken->code_pos;
3528 switch (target [3]) {
3529 case MONO_TABLE_FIELD:
3530 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3531 field = (MonoReflectionFieldBuilder *)iltoken->member;
3532 idx = field->table_idx;
3533 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3534 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3535 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3537 g_assert_not_reached ();
3540 case MONO_TABLE_METHOD:
3541 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3542 method = (MonoReflectionMethodBuilder *)iltoken->member;
3543 idx = method->table_idx;
3544 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3545 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3546 idx = ctor->table_idx;
3547 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3548 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3549 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3550 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3552 g_assert_not_reached ();
3555 case MONO_TABLE_TYPEDEF:
3556 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3557 g_assert_not_reached ();
3558 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3559 idx = tb->table_idx;
3561 case MONO_TABLE_MEMBERREF:
3562 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3563 am = (MonoReflectionArrayMethod*)iltoken->member;
3564 idx = am->table_idx;
3565 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3566 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3567 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3568 g_assert (m->klass->generic_class);
3570 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3572 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3573 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3574 g_assert (f->generic_info);
3576 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3579 g_assert_not_reached ();
3582 case MONO_TABLE_METHODSPEC:
3583 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3584 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3585 g_assert (m->signature->generic_param_count);
3588 g_assert_not_reached ();
3592 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3594 target [0] = idx & 0xff;
3595 target [1] = (idx >> 8) & 0xff;
3596 target [2] = (idx >> 16) & 0xff;
3603 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3604 * value is not known when the table is emitted.
3607 fixup_cattrs (MonoDynamicImage *assembly)
3609 MonoDynamicTable *table;
3611 guint32 type, i, idx, token;
3614 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3616 for (i = 0; i < table->rows; ++i) {
3617 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3619 type = values [MONO_CUSTOM_ATTR_TYPE];
3620 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3621 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3622 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3623 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3626 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3627 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3628 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3629 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3636 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3638 MonoDynamicTable *table;
3642 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3644 alloc_table (table, table->rows);
3645 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3646 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3647 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3648 name = mono_string_to_utf8 (rsrc->name);
3649 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3651 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3656 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3658 MonoDynamicTable *table;
3662 char *b = blob_size;
3664 guint32 idx, offset;
3666 if (rsrc->filename) {
3667 name = mono_string_to_utf8 (rsrc->filename);
3668 sname = g_path_get_basename (name);
3670 table = &assembly->tables [MONO_TABLE_FILE];
3672 alloc_table (table, table->rows);
3673 values = table->values + table->next_idx * MONO_FILE_SIZE;
3674 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3675 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3678 mono_sha1_get_digest_from_file (name, hash);
3679 mono_metadata_encode_value (20, b, &b);
3680 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3681 mono_image_add_stream_data (&assembly->blob, hash, 20);
3683 idx = table->next_idx++;
3685 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3688 offset = mono_array_length (rsrc->data);
3689 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3690 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3691 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3692 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3696 * The entry should be emitted into the MANIFESTRESOURCE table of
3697 * the main module, but that needs to reference the FILE table
3698 * which isn't emitted yet.
3705 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3709 set_version_from_string (MonoString *version, guint32 *values)
3711 gchar *ver, *p, *str;
3714 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3715 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3716 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3717 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3720 ver = str = mono_string_to_utf8 (version);
3721 for (i = 0; i < 4; ++i) {
3722 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3728 /* handle Revision and Build */
3738 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3742 char *b = blob_size;
3747 len = mono_array_length (pkey);
3748 mono_metadata_encode_value (len, b, &b);
3749 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3750 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3752 /* need to get the actual value from the key type... */
3753 assembly->strong_name_size = 128;
3754 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3760 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3762 MonoDynamicTable *table;
3763 MonoDynamicImage *assembly;
3764 MonoReflectionAssemblyBuilder *assemblyb;
3769 guint32 module_index;
3771 assemblyb = moduleb->assemblyb;
3772 assembly = moduleb->dynamic_image;
3773 domain = mono_object_domain (assemblyb);
3775 /* Emit ASSEMBLY table */
3776 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3777 alloc_table (table, 1);
3778 values = table->values + MONO_ASSEMBLY_SIZE;
3779 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3780 name = mono_string_to_utf8 (assemblyb->name);
3781 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3783 if (assemblyb->culture) {
3784 name = mono_string_to_utf8 (assemblyb->culture);
3785 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3788 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3790 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3791 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3792 set_version_from_string (assemblyb->version, values);
3794 /* Emit FILE + EXPORTED_TYPE table */
3796 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3798 MonoReflectionModuleBuilder *file_module =
3799 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3800 if (file_module != moduleb) {
3801 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3803 if (file_module->types) {
3804 for (j = 0; j < file_module->num_types; ++j) {
3805 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3806 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3811 if (assemblyb->loaded_modules) {
3812 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3813 MonoReflectionModule *file_module =
3814 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3815 mono_image_fill_file_table (domain, file_module, assembly);
3817 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3821 /* Emit MANIFESTRESOURCE table */
3823 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3825 MonoReflectionModuleBuilder *file_module =
3826 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3827 /* The table for the main module is emitted later */
3828 if (file_module != moduleb) {
3830 if (file_module->resources) {
3831 int len = mono_array_length (file_module->resources);
3832 for (j = 0; j < len; ++j) {
3833 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3834 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3842 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3843 * for the modulebuilder @moduleb.
3844 * At the end of the process, method and field tokens are fixed up and the
3845 * on-disk compressed metadata representation is created.
3848 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3850 MonoDynamicTable *table;
3851 MonoDynamicImage *assembly;
3852 MonoReflectionAssemblyBuilder *assemblyb;
3857 assemblyb = moduleb->assemblyb;
3858 assembly = moduleb->dynamic_image;
3859 domain = mono_object_domain (assemblyb);
3861 if (assembly->text_rva)
3864 assembly->text_rva = START_TEXT_RVA;
3866 if (moduleb->is_main) {
3867 mono_image_emit_manifest (moduleb);
3870 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3871 table->rows = 1; /* .<Module> */
3873 alloc_table (table, table->rows);
3875 * Set the first entry.
3877 values = table->values + table->columns;
3878 values [MONO_TYPEDEF_FLAGS] = 0;
3879 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3880 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3881 values [MONO_TYPEDEF_EXTENDS] = 0;
3882 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3883 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3886 * handle global methods
3887 * FIXME: test what to do when global methods are defined in multiple modules.
3889 if (moduleb->global_methods) {
3890 table = &assembly->tables [MONO_TABLE_METHOD];
3891 table->rows += mono_array_length (moduleb->global_methods);
3892 alloc_table (table, table->rows);
3893 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3894 mono_image_get_method_info (
3895 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3897 if (moduleb->global_fields) {
3898 table = &assembly->tables [MONO_TABLE_FIELD];
3899 table->rows += mono_array_length (moduleb->global_fields);
3900 alloc_table (table, table->rows);
3901 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3902 mono_image_get_field_info (
3903 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3906 table = &assembly->tables [MONO_TABLE_MODULE];
3907 alloc_table (table, 1);
3908 mono_image_fill_module_table (domain, moduleb, assembly);
3912 /* Collect all types into a list sorted by their table_idx */
3913 GPtrArray *types = g_ptr_array_new ();
3916 for (i = 0; i < moduleb->num_types; ++i) {
3917 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3918 collect_types (types, type);
3921 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3922 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3923 table->rows += types->len;
3924 alloc_table (table, table->rows);
3926 for (i = 0; i < types->len; ++i) {
3927 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3928 mono_image_get_type_info (domain, type, assembly);
3930 g_ptr_array_free (types, TRUE);
3934 * table->rows is already set above and in mono_image_fill_module_table.
3936 /* add all the custom attributes at the end, once all the indexes are stable */
3937 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3939 /* CAS assembly permissions */
3940 if (assemblyb->permissions_minimum)
3941 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3942 if (assemblyb->permissions_optional)
3943 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3944 if (assemblyb->permissions_refused)
3945 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3947 module_add_cattrs (assembly, moduleb);
3950 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3951 fixup_cattrs (assembly);
3955 * mono_image_insert_string:
3956 * @module: module builder object
3959 * Insert @str into the user string stream of @module.
3962 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3964 MonoDynamicImage *assembly;
3969 MONO_ARCH_SAVE_REGS;
3971 if (!module->dynamic_image)
3972 mono_image_module_basic_init (module);
3974 assembly = module->dynamic_image;
3976 if (assembly->save) {
3977 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3978 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3979 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3981 char *swapped = g_malloc (2 * mono_string_length (str));
3982 const char *p = (const char*)mono_string_chars (str);
3984 swap_with_size (swapped, p, 2, mono_string_length (str));
3985 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3989 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3991 mono_image_add_stream_data (&assembly->us, "", 1);
3993 idx = assembly->us.index ++;
3996 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3998 return MONO_TOKEN_STRING | idx;
4002 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4007 klass = obj->vtable->klass;
4008 if (strcmp (klass->name, "MonoMethod") == 0) {
4009 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4010 MonoMethodSignature *sig, *old;
4011 guint32 sig_token, parent;
4014 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
4016 nargs = mono_array_length (opt_param_types);
4017 old = method->signature;
4018 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4020 sig->hasthis = old->hasthis;
4021 sig->explicit_this = old->explicit_this;
4022 sig->call_convention = old->call_convention;
4023 sig->generic_param_count = old->generic_param_count;
4024 sig->param_count = old->param_count + nargs;
4025 sig->sentinelpos = old->param_count;
4026 sig->ret = old->ret;
4028 for (i = 0; i < old->param_count; i++)
4029 sig->params [i] = old->params [i];
4031 for (i = 0; i < nargs; i++) {
4032 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4033 sig->params [old->param_count + i] = rt->type;
4036 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4037 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4038 parent >>= MONO_TYPEDEFORREF_BITS;
4040 parent <<= MONO_MEMBERREF_PARENT_BITS;
4041 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4043 sig_token = method_encode_signature (assembly, sig);
4044 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4045 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4046 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4047 ReflectionMethodBuilder rmb;
4048 guint32 parent, sig;
4050 reflection_methodbuilder_from_method_builder (&rmb, mb);
4051 rmb.opt_types = opt_param_types;
4053 sig = method_builder_encode_signature (assembly, &rmb);
4055 parent = mono_image_create_token (assembly, obj, TRUE);
4056 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4058 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4059 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4061 token = mono_image_get_varargs_method_token (
4062 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4064 g_error ("requested method token for %s\n", klass->name);
4071 * mono_image_create_token:
4072 * @assembly: a dynamic assembly
4075 * Get a token to insert in the IL code stream for the given MemberInfo.
4076 * @obj can be one of:
4077 * ConstructorBuilder
4087 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4092 klass = obj->vtable->klass;
4093 if (strcmp (klass->name, "MethodBuilder") == 0) {
4094 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4096 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4097 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4099 token = mono_image_get_methodbuilder_token (assembly, mb);
4100 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4101 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4102 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4104 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4105 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4107 token = mono_image_get_ctorbuilder_token (assembly, mb);
4108 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4109 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4110 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4111 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4112 if (tb->generic_params) {
4113 token = mono_image_get_generic_field_token (assembly, fb);
4115 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4117 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4118 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4119 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4120 } else if (strcmp (klass->name, "MonoType") == 0 ||
4121 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4122 MonoReflectionType *tb = (MonoReflectionType *)obj;
4123 token = mono_metadata_token_from_dor (
4124 mono_image_typedef_or_ref (assembly, tb->type));
4125 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4126 MonoReflectionType *tb = (MonoReflectionType *)obj;
4127 token = mono_metadata_token_from_dor (
4128 mono_image_typedef_or_ref (assembly, tb->type));
4129 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4130 strcmp (klass->name, "MonoMethod") == 0) {
4131 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4132 if (m->method->signature->is_inflated) {
4133 if (create_methodspec)
4134 token = mono_image_get_methodspec_token (assembly, m->method);
4136 token = mono_image_get_inflated_method_token (assembly, m->method);
4137 } else if ((m->method->klass->image == &assembly->image) &&
4138 !m->method->klass->generic_class) {
4139 static guint32 method_table_idx = 0xffffff;
4140 if (m->method->klass->wastypebuilder) {
4141 /* we use the same token as the one that was assigned
4142 * to the Methodbuilder.
4143 * FIXME: do the equivalent for Fields.
4145 token = m->method->token;
4148 * Each token should have a unique index, but the indexes are
4149 * assigned by managed code, so we don't know about them. An
4150 * easy solution is to count backwards...
4152 method_table_idx --;
4153 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4156 token = mono_image_get_methodref_token (assembly, m->method);
4158 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4159 } else if (strcmp (klass->name, "MonoField") == 0) {
4160 MonoReflectionField *f = (MonoReflectionField *)obj;
4161 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4162 static guint32 field_table_idx = 0xffffff;
4164 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4166 token = mono_image_get_fieldref_token (assembly, f);
4168 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4169 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4170 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4171 token = mono_image_get_array_token (assembly, m);
4172 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4173 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4174 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4176 g_error ("requested token for %s\n", klass->name);
4179 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4185 guint32 import_lookup_table;
4189 guint32 import_address_table_rva;
4197 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4199 static MonoDynamicImage*
4200 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4202 static const guchar entrycode [16] = {0xff, 0x25, 0};
4203 MonoDynamicImage *image;
4206 const char *version = mono_get_runtime_version ();
4209 image = GC_MALLOC (sizeof (MonoDynamicImage));
4211 image = g_new0 (MonoDynamicImage, 1);
4214 /* keep in sync with image.c */
4215 image->image.name = assembly_name;
4216 image->image.assembly_name = image->image.name; /* they may be different */
4217 image->image.module_name = module_name;
4218 image->image.version = g_strdup (version);
4219 image->image.dynamic = TRUE;
4221 image->image.references = g_new0 (MonoAssembly*, 1);
4222 image->image.references [0] = NULL;
4224 mono_image_init (&image->image);
4226 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4227 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4228 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4229 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4230 image->handleref = g_hash_table_new (NULL, NULL);
4231 image->tokens = mono_g_hash_table_new (NULL, NULL);
4232 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4233 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4234 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4235 image->gen_params = g_ptr_array_new ();
4237 string_heap_init (&image->sheap);
4238 mono_image_add_stream_data (&image->us, "", 1);
4239 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4240 /* import tables... */
4241 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4242 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4243 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4244 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4245 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4246 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4247 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4248 stream_data_align (&image->code);
4250 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4252 for (i=0; i < 64; ++i) {
4253 image->tables [i].next_idx = 1;
4254 image->tables [i].columns = table_sizes [i];
4257 image->image.assembly = (MonoAssembly*)assembly;
4258 image->run = assembly->run;
4259 image->save = assembly->save;
4260 image->pe_kind = 0x1; /* ILOnly */
4261 image->machine = 0x14c; /* I386 */
4267 * mono_image_basic_init:
4268 * @assembly: an assembly builder object
4270 * Create the MonoImage that represents the assembly builder and setup some
4271 * of the helper hash table and the basic metadata streams.
4274 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4276 MonoDynamicAssembly *assembly;
4277 MonoDynamicImage *image;
4279 MONO_ARCH_SAVE_REGS;
4281 if (assemblyb->dynamic_assembly)
4285 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4287 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4290 assembly->assembly.dynamic = TRUE;
4291 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4292 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4293 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4294 if (assemblyb->culture)
4295 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4297 assembly->assembly.aname.culture = g_strdup ("");
4299 assembly->run = assemblyb->access != 2;
4300 assembly->save = assemblyb->access != 1;
4302 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4303 image->initial_image = TRUE;
4304 assembly->assembly.aname.name = image->image.name;
4305 assembly->assembly.image = &image->image;
4307 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4308 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4312 calc_section_size (MonoDynamicImage *assembly)
4316 /* alignment constraints */
4317 assembly->code.index += 3;
4318 assembly->code.index &= ~3;
4319 assembly->meta_size += 3;
4320 assembly->meta_size &= ~3;
4321 assembly->resources.index += 3;
4322 assembly->resources.index &= ~3;
4324 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4325 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4328 if (assembly->win32_res) {
4329 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4331 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4332 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4336 assembly->sections [MONO_SECTION_RELOC].size = 12;
4337 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4347 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4351 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4353 ResTreeNode *t1 = (ResTreeNode*)a;
4354 ResTreeNode *t2 = (ResTreeNode*)b;
4356 return t1->id - t2->id;
4360 * resource_tree_create:
4362 * Organize the resources into a resource tree.
4364 static ResTreeNode *
4365 resource_tree_create (MonoArray *win32_resources)
4367 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4371 tree = g_new0 (ResTreeNode, 1);
4373 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4374 MonoReflectionWin32Resource *win32_res =
4375 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4379 lang_node = g_new0 (ResTreeNode, 1);
4380 lang_node->id = win32_res->lang_id;
4381 lang_node->win32_res = win32_res;
4383 /* Create type node if neccesary */
4385 for (l = tree->children; l; l = l->next)
4386 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4387 type_node = (ResTreeNode*)l->data;
4392 type_node = g_new0 (ResTreeNode, 1);
4393 type_node->id = win32_res->res_type;
4396 * The resource types have to be sorted otherwise
4397 * Windows Explorer can't display the version information.
4399 tree->children = g_slist_insert_sorted (tree->children,
4400 type_node, resource_tree_compare_by_id);
4403 /* Create res node if neccesary */
4405 for (l = type_node->children; l; l = l->next)
4406 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4407 res_node = (ResTreeNode*)l->data;
4412 res_node = g_new0 (ResTreeNode, 1);
4413 res_node->id = win32_res->res_id;
4414 type_node->children = g_slist_append (type_node->children, res_node);
4417 res_node->children = g_slist_append (res_node->children, lang_node);
4424 * resource_tree_encode:
4426 * Encode the resource tree into the format used in the PE file.
4429 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4432 MonoPEResourceDir dir;
4433 MonoPEResourceDirEntry dir_entry;
4434 MonoPEResourceDataEntry data_entry;
4438 * For the format of the resource directory, see the article
4439 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4443 memset (&dir, 0, sizeof (dir));
4444 memset (&dir_entry, 0, sizeof (dir_entry));
4445 memset (&data_entry, 0, sizeof (data_entry));
4447 g_assert (sizeof (dir) == 16);
4448 g_assert (sizeof (dir_entry) == 8);
4449 g_assert (sizeof (data_entry) == 16);
4451 node->offset = p - begin;
4453 /* IMAGE_RESOURCE_DIRECTORY */
4454 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4456 memcpy (p, &dir, sizeof (dir));
4459 /* Reserve space for entries */
4461 p += sizeof (dir_entry) * dir.res_id_entries;
4463 /* Write children */
4464 for (l = node->children; l; l = l->next) {
4465 ResTreeNode *child = (ResTreeNode*)l->data;
4467 if (child->win32_res) {
4469 child->offset = p - begin;
4471 /* IMAGE_RESOURCE_DATA_ENTRY */
4472 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4473 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4475 memcpy (p, &data_entry, sizeof (data_entry));
4476 p += sizeof (data_entry);
4478 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4479 p += data_entry.rde_size;
4481 resource_tree_encode (child, begin, p, &p);
4485 /* IMAGE_RESOURCE_ENTRY */
4486 for (l = node->children; l; l = l->next) {
4487 ResTreeNode *child = (ResTreeNode*)l->data;
4488 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4490 dir_entry.is_dir = child->win32_res ? 0 : 1;
4491 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4493 memcpy (entries, &dir_entry, sizeof (dir_entry));
4494 entries += sizeof (dir_entry);
4501 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4506 MonoReflectionWin32Resource *win32_res;
4509 if (!assemblyb->win32_resources)
4513 * Resources are stored in a three level tree inside the PE file.
4514 * - level one contains a node for each type of resource
4515 * - level two contains a node for each resource
4516 * - level three contains a node for each instance of a resource for a
4517 * specific language.
4520 tree = resource_tree_create (assemblyb->win32_resources);
4522 /* Estimate the size of the encoded tree */
4524 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4525 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4526 size += mono_array_length (win32_res->res_data);
4528 /* Directory structure */
4529 size += mono_array_length (assemblyb->win32_resources) * 256;
4530 p = buf = g_malloc (size);
4532 resource_tree_encode (tree, p, p, &p);
4534 g_assert (p - buf < size);
4536 assembly->win32_res = g_malloc (p - buf);
4537 assembly->win32_res_size = p - buf;
4538 memcpy (assembly->win32_res, buf, p - buf);
4544 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4546 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4549 p += sizeof (MonoPEResourceDir);
4550 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4551 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4552 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4553 if (dir_entry->is_dir) {
4554 fixup_resource_directory (res_section, child, rva);
4556 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4557 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4560 p += sizeof (MonoPEResourceDirEntry);
4565 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4568 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4569 g_error ("WriteFile returned %d\n", GetLastError ());
4573 * mono_image_create_pefile:
4574 * @mb: a module builder object
4576 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4577 * assembly->pefile where it can be easily retrieved later in chunks.
4580 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4581 MonoMSDOSHeader *msdos;
4582 MonoDotNetHeader *header;
4583 MonoSectionTable *section;
4584 MonoCLIHeader *cli_header;
4585 guint32 size, image_size, virtual_base, text_offset;
4586 guint32 header_start, section_start, file_offset, virtual_offset;
4587 MonoDynamicImage *assembly;
4588 MonoReflectionAssemblyBuilder *assemblyb;
4589 MonoDynamicStream pefile_stream = {0};
4590 MonoDynamicStream *pefile = &pefile_stream;
4592 guint32 *rva, value;
4594 static const unsigned char msheader[] = {
4595 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4596 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4599 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4600 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4601 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4602 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4605 assemblyb = mb->assemblyb;
4607 mono_image_basic_init (assemblyb);
4608 assembly = mb->dynamic_image;
4610 assembly->pe_kind = assemblyb->pe_kind;
4611 assembly->machine = assemblyb->machine;
4612 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4613 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4615 mono_image_build_metadata (mb);
4617 if (mb->is_main && assemblyb->resources) {
4618 int len = mono_array_length (assemblyb->resources);
4619 for (i = 0; i < len; ++i)
4620 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4623 if (mb->resources) {
4624 int len = mono_array_length (mb->resources);
4625 for (i = 0; i < len; ++i)
4626 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4629 build_compressed_metadata (assembly);
4632 assembly_add_win32_resources (assembly, assemblyb);
4634 nsections = calc_section_size (assembly);
4636 /* The DOS header and stub */
4637 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4638 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4640 /* the dotnet header */
4641 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4643 /* the section tables */
4644 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4646 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4647 virtual_offset = VIRT_ALIGN;
4650 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4651 if (!assembly->sections [i].size)
4654 file_offset += FILE_ALIGN - 1;
4655 file_offset &= ~(FILE_ALIGN - 1);
4656 virtual_offset += VIRT_ALIGN - 1;
4657 virtual_offset &= ~(VIRT_ALIGN - 1);
4659 assembly->sections [i].offset = file_offset;
4660 assembly->sections [i].rva = virtual_offset;
4662 file_offset += assembly->sections [i].size;
4663 virtual_offset += assembly->sections [i].size;
4664 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4667 file_offset += FILE_ALIGN - 1;
4668 file_offset &= ~(FILE_ALIGN - 1);
4670 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4672 /* back-patch info */
4673 msdos = (MonoMSDOSHeader*)pefile->data;
4674 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4675 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4676 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4678 header = (MonoDotNetHeader*)(pefile->data + header_start);
4679 header->pesig [0] = 'P';
4680 header->pesig [1] = 'E';
4682 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4683 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4684 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4685 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4686 if (assemblyb->pekind == 1) {
4688 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4691 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4694 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4696 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4697 header->pe.pe_major = 6;
4698 header->pe.pe_minor = 0;
4699 size = assembly->sections [MONO_SECTION_TEXT].size;
4700 size += FILE_ALIGN - 1;
4701 size &= ~(FILE_ALIGN - 1);
4702 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4703 size = assembly->sections [MONO_SECTION_RSRC].size;
4704 size += FILE_ALIGN - 1;
4705 size &= ~(FILE_ALIGN - 1);
4706 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4707 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4708 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4709 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4710 /* pe_rva_entry_point always at the beginning of the text section */
4711 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4713 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4714 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4715 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4716 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4717 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4718 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4719 size = section_start;
4720 size += FILE_ALIGN - 1;
4721 size &= ~(FILE_ALIGN - 1);
4722 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4724 size += VIRT_ALIGN - 1;
4725 size &= ~(VIRT_ALIGN - 1);
4726 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4729 // Translate the PEFileKind value to the value expected by the Windows loader
4735 // PEFileKinds.Dll == 1
4736 // PEFileKinds.ConsoleApplication == 2
4737 // PEFileKinds.WindowApplication == 3
4740 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4741 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4743 if (assemblyb->pekind == 3)
4748 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4750 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4751 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4752 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4753 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4754 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4755 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4757 /* fill data directory entries */
4759 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4760 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4762 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4763 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4765 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4766 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4767 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4768 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4769 /* patch entrypoint name */
4770 if (assemblyb->pekind == 1)
4771 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4773 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4774 /* patch imported function RVA name */
4775 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4776 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4778 /* the import table */
4779 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4780 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4781 /* patch imported dll RVA name and other entries in the dir */
4782 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4783 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4784 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4785 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4786 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4787 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4789 p = (assembly->code.data + assembly->ilt_offset);
4790 value = (assembly->text_rva + assembly->imp_names_offset);
4791 *p++ = (value) & 0xff;
4792 *p++ = (value >> 8) & (0xff);
4793 *p++ = (value >> 16) & (0xff);
4794 *p++ = (value >> 24) & (0xff);
4796 /* the CLI header info */
4797 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4798 cli_header->ch_size = GUINT32_FROM_LE (72);
4799 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4800 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4801 if (assemblyb->entry_point) {
4802 guint32 table_idx = 0;
4803 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4804 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4805 table_idx = methodb->table_idx;
4807 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4809 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4811 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4813 /* The embedded managed resources */
4814 text_offset = assembly->text_rva + assembly->code.index;
4815 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4816 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4817 text_offset += assembly->resources.index;
4818 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4819 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4820 text_offset += assembly->meta_size;
4821 if (assembly->strong_name_size) {
4822 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4823 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4824 text_offset += assembly->strong_name_size;
4827 /* write the section tables and section content */
4828 section = (MonoSectionTable*)(pefile->data + section_start);
4829 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4830 static const char *section_names [] = {
4831 ".text", ".rsrc", ".reloc"
4833 if (!assembly->sections [i].size)
4835 strcpy (section->st_name, section_names [i]);
4836 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4837 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4838 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4839 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4840 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4841 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4842 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4846 checked_write_file (file, pefile->data, pefile->index);
4848 mono_dynamic_stream_reset (pefile);
4850 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4851 if (!assembly->sections [i].size)
4854 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4855 g_error ("SetFilePointer returned %d\n", GetLastError ());
4858 case MONO_SECTION_TEXT:
4859 /* patch entry point */
4860 p = (assembly->code.data + 2);
4861 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4862 *p++ = (value) & 0xff;
4863 *p++ = (value >> 8) & 0xff;
4864 *p++ = (value >> 16) & 0xff;
4865 *p++ = (value >> 24) & 0xff;
4867 checked_write_file (file, assembly->code.data, assembly->code.index);
4868 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4869 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4870 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4873 g_free (assembly->image.raw_metadata);
4875 case MONO_SECTION_RELOC: {
4879 guint16 type_and_offset;
4883 g_assert (sizeof (reloc) == 12);
4885 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4886 reloc.block_size = GUINT32_FROM_LE (12);
4889 * the entrypoint is always at the start of the text section
4890 * 3 is IMAGE_REL_BASED_HIGHLOW
4891 * 2 is patch_size_rva - text_rva
4893 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4896 checked_write_file (file, &reloc, sizeof (reloc));
4900 case MONO_SECTION_RSRC:
4901 if (assembly->win32_res) {
4903 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4904 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4905 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
4909 g_assert_not_reached ();
4913 /* check that the file is properly padded */
4914 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4915 g_error ("SetFilePointer returned %d\n", GetLastError ());
4916 if (! SetEndOfFile (file))
4917 g_error ("SetEndOfFile returned %d\n", GetLastError ());
4919 mono_dynamic_stream_reset (&assembly->code);
4920 mono_dynamic_stream_reset (&assembly->us);
4921 mono_dynamic_stream_reset (&assembly->blob);
4922 mono_dynamic_stream_reset (&assembly->guid);
4923 string_heap_free (&assembly->sheap);
4925 mono_g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
4926 mono_g_hash_table_destroy (assembly->blob_cache);
4929 MonoReflectionModule *
4930 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4934 MonoImageOpenStatus status;
4935 MonoDynamicAssembly *assembly;
4936 guint32 module_count;
4937 MonoImage **new_modules;
4939 name = mono_string_to_utf8 (fileName);
4941 image = mono_image_open (name, &status);
4944 if (status == MONO_IMAGE_ERROR_ERRNO)
4945 exc = mono_get_exception_file_not_found (fileName);
4947 exc = mono_get_exception_bad_image_format (name);
4949 mono_raise_exception (exc);
4954 assembly = ab->dynamic_assembly;
4955 image->assembly = (MonoAssembly*)assembly;
4957 module_count = image->assembly->image->module_count;
4958 new_modules = g_new0 (MonoImage *, module_count + 1);
4960 if (image->assembly->image->modules)
4961 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4962 new_modules [module_count] = image;
4964 g_free (image->assembly->image->modules);
4965 image->assembly->image->modules = new_modules;
4966 image->assembly->image->module_count ++;
4968 mono_assembly_load_references (image, &status);
4970 mono_image_close (image);
4971 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4974 return mono_module_get_object (mono_domain_get (), image);
4978 * We need to return always the same object for MethodInfo, FieldInfo etc..
4979 * but we need to consider the reflected type.
4980 * type uses a different hash, since it uses custom hash/equal functions.
4985 MonoClass *refclass;
4989 reflected_equal (gconstpointer a, gconstpointer b) {
4990 const ReflectedEntry *ea = a;
4991 const ReflectedEntry *eb = b;
4993 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4997 reflected_hash (gconstpointer a) {
4998 const ReflectedEntry *ea = a;
4999 return GPOINTER_TO_UINT (ea->item);
5002 #define CHECK_OBJECT(t,p,k) \
5008 mono_domain_lock (domain); \
5009 if (!domain->refobject_hash) \
5010 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5011 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5012 mono_domain_unlock (domain); \
5018 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5020 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5023 #define CACHE_OBJECT(p,o,k) \
5025 ReflectedEntry *e = ALLOC_REFENTRY; \
5027 e->refclass = (k); \
5028 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5029 mono_domain_unlock (domain); \
5033 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5035 /* this is done only once */
5036 mono_domain_lock (domain);
5037 CACHE_OBJECT (assembly, res, NULL);
5041 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5043 /* this is done only once */
5044 mono_domain_lock (domain);
5045 CACHE_OBJECT (module, res, NULL);
5049 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5051 MonoDynamicImage *image = moduleb->dynamic_image;
5052 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5055 * FIXME: we already created an image in mono_image_basic_init (), but
5056 * we don't know which module it belongs to, since that is only
5057 * determined at assembly save time.
5059 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5060 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5062 moduleb->module.image = &image->image;
5063 moduleb->dynamic_image = image;
5064 register_module (mono_object_domain (moduleb), moduleb, image);
5069 * mono_assembly_get_object:
5070 * @domain: an app domain
5071 * @assembly: an assembly
5073 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5075 MonoReflectionAssembly*
5076 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5078 static MonoClass *System_Reflection_Assembly;
5079 MonoReflectionAssembly *res;
5081 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5082 if (!System_Reflection_Assembly)
5083 System_Reflection_Assembly = mono_class_from_name (
5084 mono_defaults.corlib, "System.Reflection", "Assembly");
5085 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5086 res->assembly = assembly;
5088 CACHE_OBJECT (assembly, res, NULL);
5094 MonoReflectionModule*
5095 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5097 static MonoClass *System_Reflection_Module;
5098 MonoReflectionModule *res;
5101 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5102 if (!System_Reflection_Module)
5103 System_Reflection_Module = mono_class_from_name (
5104 mono_defaults.corlib, "System.Reflection", "Module");
5105 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5108 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5110 res->fqname = mono_string_new (domain, image->name);
5111 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5112 res->scopename = mono_string_new (domain, image->module_name);
5116 if (image->assembly->image == image) {
5117 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5120 g_assert (image->assembly->image->modules);
5122 for (i = 0; i < image->assembly->image->module_count; i++) {
5123 if (image->assembly->image->modules [i] == image)
5124 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5126 g_assert (res->token);
5129 mono_image_addref (image);
5131 CACHE_OBJECT (image, res, NULL);
5135 MonoReflectionModule*
5136 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5138 static MonoClass *System_Reflection_Module;
5139 MonoReflectionModule *res;
5140 MonoTableInfo *table;
5141 guint32 cols [MONO_FILE_SIZE];
5143 guint32 i, name_idx;
5146 if (!System_Reflection_Module)
5147 System_Reflection_Module = mono_class_from_name (
5148 mono_defaults.corlib, "System.Reflection", "Module");
5149 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5151 table = &image->tables [MONO_TABLE_FILE];
5152 g_assert (table_index < table->rows);
5153 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5156 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5157 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5159 /* Check whenever the row has a corresponding row in the moduleref table */
5160 table = &image->tables [MONO_TABLE_MODULEREF];
5161 for (i = 0; i < table->rows; ++i) {
5162 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5163 val = mono_metadata_string_heap (image, name_idx);
5164 if (strcmp (val, name) == 0)
5165 res->image = image->modules [i];
5168 res->fqname = mono_string_new (domain, name);
5169 res->name = mono_string_new (domain, name);
5170 res->scopename = mono_string_new (domain, name);
5171 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5172 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5178 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5180 if ((t1->type != t2->type) ||
5181 (t1->byref != t2->byref))
5185 case MONO_TYPE_VOID:
5186 case MONO_TYPE_BOOLEAN:
5187 case MONO_TYPE_CHAR:
5198 case MONO_TYPE_STRING:
5201 case MONO_TYPE_OBJECT:
5202 case MONO_TYPE_TYPEDBYREF:
5204 case MONO_TYPE_VALUETYPE:
5205 case MONO_TYPE_CLASS:
5206 case MONO_TYPE_SZARRAY:
5207 return t1->data.klass == t2->data.klass;
5209 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5210 case MONO_TYPE_ARRAY:
5211 if (t1->data.array->rank != t2->data.array->rank)
5213 return t1->data.array->eklass == t2->data.array->eklass;
5214 case MONO_TYPE_GENERICINST: {
5216 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5218 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5219 &t2->data.generic_class->container_class->byval_arg))
5221 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5222 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5228 case MONO_TYPE_MVAR:
5229 return t1->data.generic_param == t2->data.generic_param;
5231 g_error ("implement type compare for %0x!", t1->type);
5239 mymono_metadata_type_hash (MonoType *t1)
5245 hash |= t1->byref << 6; /* do not collide with t1->type values */
5247 case MONO_TYPE_VALUETYPE:
5248 case MONO_TYPE_CLASS:
5249 case MONO_TYPE_SZARRAY:
5250 /* check if the distribution is good enough */
5251 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5253 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5258 static MonoReflectionGenericClass*
5259 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5261 static MonoClass *System_Reflection_MonoGenericClass;
5262 MonoReflectionGenericClass *res;
5263 MonoGenericClass *gclass;
5266 if (!System_Reflection_MonoGenericClass) {
5267 System_Reflection_MonoGenericClass = mono_class_from_name (
5268 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5269 g_assert (System_Reflection_MonoGenericClass);
5272 gclass = geninst->data.generic_class;
5273 gklass = gclass->container_class;
5275 mono_class_init (gclass->klass);
5277 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5279 res->type.type = geninst;
5280 if (gklass->wastypebuilder && gklass->reflection_info)
5281 res->generic_type = gklass->reflection_info;
5283 res->generic_type = mono_type_get_object (domain, &gclass->container_class->byval_arg);
5289 * mono_type_get_object:
5290 * @domain: an app domain
5293 * Return an System.MonoType object representing the type @type.
5296 mono_type_get_object (MonoDomain *domain, MonoType *type)
5298 MonoReflectionType *res;
5299 MonoClass *klass = mono_class_from_mono_type (type);
5301 mono_domain_lock (domain);
5302 if (!domain->type_hash)
5303 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5304 (GCompareFunc)mymono_metadata_type_equal);
5305 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5306 mono_domain_unlock (domain);
5309 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5310 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5311 mono_g_hash_table_insert (domain->type_hash, type, res);
5312 mono_domain_unlock (domain);
5315 if (klass->reflection_info && !klass->wastypebuilder) {
5316 /* g_assert_not_reached (); */
5317 /* should this be considered an error condition? */
5319 mono_domain_unlock (domain);
5320 return klass->reflection_info;
5323 mono_class_init (klass);
5324 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5326 mono_g_hash_table_insert (domain->type_hash, type, res);
5327 mono_domain_unlock (domain);
5332 * mono_method_get_object:
5333 * @domain: an app domain
5335 * @refclass: the reflected type (can be NULL)
5337 * Return an System.Reflection.MonoMethod object representing the method @method.
5339 MonoReflectionMethod*
5340 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5343 * We use the same C representation for methods and constructors, but the type
5344 * name in C# is different.
5348 MonoReflectionMethod *ret;
5351 refclass = method->klass;
5353 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5354 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5355 cname = "MonoCMethod";
5357 cname = "MonoMethod";
5358 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5360 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5361 ret->method = method;
5362 ret->name = mono_string_new (domain, method->name);
5363 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5364 CACHE_OBJECT (method, ret, refclass);
5369 * mono_field_get_object:
5370 * @domain: an app domain
5374 * Return an System.Reflection.MonoField object representing the field @field
5377 MonoReflectionField*
5378 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5380 MonoReflectionField *res;
5383 CHECK_OBJECT (MonoReflectionField *, field, klass);
5384 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5385 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5388 res->name = mono_string_new (domain, field->name);
5389 if (field->generic_info)
5390 res->attrs = field->generic_info->generic_type->attrs;
5392 res->attrs = field->type->attrs;
5393 res->type = mono_type_get_object (domain, field->type);
5394 CACHE_OBJECT (field, res, klass);
5399 * mono_property_get_object:
5400 * @domain: an app domain
5402 * @property: a property
5404 * Return an System.Reflection.MonoProperty object representing the property @property
5407 MonoReflectionProperty*
5408 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5410 MonoReflectionProperty *res;
5413 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5414 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5415 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5417 res->property = property;
5418 CACHE_OBJECT (property, res, klass);
5423 * mono_event_get_object:
5424 * @domain: an app domain
5428 * Return an System.Reflection.MonoEvent object representing the event @event
5431 MonoReflectionEvent*
5432 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5434 MonoReflectionEvent *res;
5437 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5438 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5439 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5442 CACHE_OBJECT (event, res, klass);
5447 * mono_param_get_objects:
5448 * @domain: an app domain
5451 * Return an System.Reflection.ParameterInfo array object representing the parameters
5452 * in the method @method.
5455 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5457 static MonoClass *System_Reflection_ParameterInfo;
5458 MonoArray *res = NULL;
5459 MonoReflectionMethod *member = NULL;
5460 MonoReflectionParameter *param = NULL;
5461 char **names, **blobs = NULL;
5462 MonoObject *dbnull = mono_get_dbnull_object (domain);
5463 MonoMarshalSpec **mspecs;
5466 if (!System_Reflection_ParameterInfo)
5467 System_Reflection_ParameterInfo = mono_class_from_name (
5468 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5470 if (!method->signature->param_count)
5471 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5473 /* Note: the cache is based on the address of the signature into the method
5474 * since we already cache MethodInfos with the method as keys.
5476 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5478 member = mono_method_get_object (domain, method, NULL);
5479 names = g_new (char *, method->signature->param_count);
5480 mono_method_get_param_names (method, (const char **) names);
5482 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5483 mono_method_get_marshal_info (method, mspecs);
5485 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5486 for (i = 0; i < method->signature->param_count; ++i) {
5487 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5488 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5489 param->MemberImpl = (MonoObject*)member;
5490 param->NameImpl = mono_string_new (domain, names [i]);
5491 param->PositionImpl = i;
5492 param->AttrsImpl = method->signature->params [i]->attrs;
5494 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5495 param->DefaultValueImpl = dbnull;
5497 MonoType *type = param->ClassImpl->type;
5500 blobs = g_new0 (char *, method->signature->param_count);
5501 get_default_param_value_blobs (method, blobs);
5504 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5506 if (!param->DefaultValueImpl) {
5507 param->DefaultValueImpl = dbnull;
5512 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5514 mono_array_set (res, gpointer, i, param);
5519 for (i = method->signature->param_count; i >= 0; i--)
5521 mono_metadata_free_marshal_spec (mspecs [i]);
5524 CACHE_OBJECT (&(method->signature), res, NULL);
5529 * mono_method_body_get_object:
5530 * @domain: an app domain
5533 * Return an System.Reflection.MethodBody object representing the method @method.
5535 MonoReflectionMethodBody*
5536 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5538 static MonoClass *System_Reflection_MethodBody = NULL;
5539 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5540 MonoReflectionMethodBody *ret;
5541 MonoMethodNormal *mn;
5542 MonoMethodHeader *header;
5545 if (!System_Reflection_MethodBody)
5546 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5547 if (!System_Reflection_LocalVariableInfo)
5548 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5550 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5552 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5553 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5555 mn = (MonoMethodNormal *)method;
5556 header = mono_method_get_header (method);
5558 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5559 /* FIXME: Other fields */
5560 ret->init_locals = header->init_locals;
5561 ret->max_stack = header->max_stack;
5562 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5563 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5564 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5565 for (i = 0; i < header->num_locals; ++i) {
5566 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5567 info->local_type = mono_type_get_object (domain, header->locals [i]);
5568 info->is_pinned = header->locals [i]->pinned;
5569 info->local_index = 0;
5572 CACHE_OBJECT (method, ret, NULL);
5577 mono_get_dbnull_object (MonoDomain *domain)
5581 static MonoClassField *dbnull_value_field = NULL;
5583 if (!dbnull_value_field) {
5584 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5585 mono_class_init (klass);
5586 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5587 g_assert (dbnull_value_field);
5589 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5596 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5598 guint32 param_index, i, lastp, crow = 0;
5599 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5602 MonoClass *klass = method->klass;
5603 MonoImage *image = klass->image;
5604 MonoMethodSignature *methodsig = method->signature;
5606 MonoTableInfo *constt;
5607 MonoTableInfo *methodt;
5608 MonoTableInfo *paramt;
5610 if (!methodsig->param_count)
5613 if (klass->generic_class) {
5614 return; /* FIXME - ??? */
5617 mono_class_init (klass);
5619 if (klass->image->dynamic) {
5620 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5621 if (aux && aux->param_defaults)
5622 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5626 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5627 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5628 constt = &image->tables [MONO_TABLE_CONSTANT];
5630 for (i = 0; i < klass->method.count; ++i) {
5631 if (method == klass->methods [i]) {
5632 idx = klass->method.first + i;
5637 g_assert (idx != -1);
5639 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5640 if (idx + 1 < methodt->rows)
5641 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5643 lastp = paramt->rows + 1;
5645 for (i = param_index; i < lastp; ++i) {
5648 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5649 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5651 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5654 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5659 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5660 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5667 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5676 klass = mono_class_from_mono_type (type);
5677 if (klass->valuetype) {
5678 object = mono_object_new (domain, klass);
5679 retval = ((gchar *) object + sizeof (MonoObject));
5684 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5691 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5695 memset (assembly, 0, sizeof (MonoAssemblyName));
5697 assembly->culture = "";
5698 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5700 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5703 while (g_ascii_isspace (*p) || *p == ',') {
5712 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5714 assembly->major = strtoul (p, &s, 10);
5715 if (s == p || *s != '.')
5718 assembly->minor = strtoul (p, &s, 10);
5719 if (s == p || *s != '.')
5722 assembly->build = strtoul (p, &s, 10);
5723 if (s == p || *s != '.')
5726 assembly->revision = strtoul (p, &s, 10);
5730 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5732 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5733 assembly->culture = "";
5736 assembly->culture = p;
5737 while (*p && *p != ',') {
5741 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5743 if (strncmp (p, "null", 4) == 0) {
5748 while (*p && *p != ',') {
5751 len = (p - start + 1);
5752 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5753 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5754 g_strlcpy (assembly->public_key_token, start, len);
5757 while (*p && *p != ',')
5761 while (g_ascii_isspace (*p) || *p == ',') {
5775 * mono_reflection_parse_type:
5778 * Parse a type name as accepted by the GetType () method and output the info
5779 * extracted in the info structure.
5780 * the name param will be mangled, so, make a copy before passing it to this function.
5781 * The fields in info will be valid until the memory pointed to by name is valid.
5783 * See also mono_type_get_name () below.
5785 * Returns: 0 on parse error.
5788 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5790 char *start, *p, *w, *last_point, *startn;
5791 int in_modifiers = 0;
5792 int isbyref = 0, rank;
5794 start = p = w = name;
5796 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5797 info->name = info->name_space = NULL;
5798 info->nested = NULL;
5799 info->modifiers = NULL;
5801 /* last_point separates the namespace from the name */
5807 *p = 0; /* NULL terminate the name */
5809 info->nested = g_list_append (info->nested, startn);
5810 /* we have parsed the nesting namespace + name */
5814 info->name_space = start;
5816 info->name = last_point + 1;
5818 info->name_space = (char *)"";
5844 info->name_space = start;
5846 info->name = last_point + 1;
5848 info->name_space = (char *)"";
5855 if (isbyref) /* only one level allowed by the spec */
5858 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5862 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5873 else if (*p != '*') /* '*' means unknown lower bound */
5879 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5884 if (g_ascii_isspace (*p)) {
5891 return 0; /* missing assembly name */
5892 if (!assembly_name_to_aname (&info->assembly, p))
5899 if (info->assembly.name)
5902 *w = 0; /* terminate class name */
5903 if (!info->name || !*info->name)
5905 /* add other consistency checks */
5910 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5917 image = mono_defaults.corlib;
5920 klass = mono_class_from_name_case (image, info->name_space, info->name);
5922 klass = mono_class_from_name (image, info->name_space, info->name);
5925 for (mod = info->nested; mod; mod = mod->next) {
5928 mono_class_init (klass);
5929 nested = klass->nested_classes;
5932 klass = nested->data;
5934 if (g_strcasecmp (klass->name, mod->data) == 0)
5937 if (strcmp (klass->name, mod->data) == 0)
5941 nested = nested->next;
5948 mono_class_init (klass);
5949 for (mod = info->modifiers; mod; mod = mod->next) {
5950 modval = GPOINTER_TO_UINT (mod->data);
5951 if (!modval) { /* byref: must be last modifier */
5952 return &klass->this_arg;
5953 } else if (modval == -1) {
5954 klass = mono_ptr_class_get (&klass->byval_arg);
5955 } else { /* array rank */
5956 klass = mono_array_class_get (klass, modval);
5958 mono_class_init (klass);
5961 return &klass->byval_arg;
5965 * mono_reflection_get_type:
5966 * @image: a metadata context
5967 * @info: type description structure
5968 * @ignorecase: flag for case-insensitive string compares
5969 * @type_resolve: whenever type resolve was already tried
5971 * Build a MonoType from the type description in @info.
5976 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5979 MonoReflectionAssembly *assembly;
5983 type = mono_reflection_get_type_internal (image, info, ignorecase);
5986 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5993 *type_resolve = TRUE;
5996 /* Reconstruct the type name */
5997 fullName = g_string_new ("");
5998 if (info->name_space && (info->name_space [0] != '\0'))
5999 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6001 g_string_printf (fullName, info->name);
6002 for (mod = info->nested; mod; mod = mod->next)
6003 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6005 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6007 if (assembly->assembly->dynamic) {
6008 /* Enumerate all modules */
6009 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6013 if (abuilder->modules) {
6014 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6015 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6016 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6022 if (!type && abuilder->loaded_modules) {
6023 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6024 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6025 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6032 type = mono_reflection_get_type_internal (assembly->assembly->image,
6035 g_string_free (fullName, TRUE);
6040 * mono_reflection_type_from_name:
6042 * @image: a metadata context (can be NULL).
6044 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6045 * it defaults to get the type from @image or, if @image is NULL or loading
6046 * from it fails, uses corlib.
6050 mono_reflection_type_from_name (char *name, MonoImage *image)
6053 MonoTypeNameParse info;
6054 MonoAssembly *assembly;
6056 gboolean type_resolve = FALSE;
6058 /* Make a copy since parse_type modifies its argument */
6059 tmp = g_strdup (name);
6061 /*g_print ("requested type %s\n", str);*/
6062 if (!mono_reflection_parse_type (tmp, &info)) {
6064 g_list_free (info.modifiers);
6065 g_list_free (info.nested);
6069 if (info.assembly.name) {
6070 assembly = mono_assembly_loaded (&info.assembly);
6072 /* then we must load the assembly ourselve - see #60439 */
6073 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6076 g_list_free (info.modifiers);
6077 g_list_free (info.nested);
6081 image = assembly->image;
6082 } else if (image == NULL) {
6083 image = mono_defaults.corlib;
6086 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6087 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6088 image = mono_defaults.corlib;
6089 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6093 g_list_free (info.modifiers);
6094 g_list_free (info.nested);
6099 * mono_reflection_get_token:
6101 * Return the metadata token of OBJ which should be an object
6102 * representing a metadata element.
6105 mono_reflection_get_token (MonoObject *obj)
6110 klass = obj->vtable->klass;
6112 if (strcmp (klass->name, "MethodBuilder") == 0) {
6113 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6115 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6116 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6117 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6119 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6120 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6121 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6122 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6123 if (tb->generic_params) {
6124 g_assert_not_reached ();
6126 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6128 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6129 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6130 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6131 } else if (strcmp (klass->name, "MonoType") == 0) {
6132 MonoReflectionType *tb = (MonoReflectionType *)obj;
6133 token = mono_class_from_mono_type (tb->type)->type_token;
6134 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6135 strcmp (klass->name, "MonoMethod") == 0) {
6136 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6137 if (m->method->signature->is_inflated) {
6138 g_assert_not_reached ();
6139 } else if (m->method->signature->generic_param_count) {
6140 g_assert_not_reached ();
6141 } else if (m->method->klass->generic_class) {
6142 g_assert_not_reached ();
6144 token = m->method->token;
6146 } else if (strcmp (klass->name, "MonoField") == 0) {
6147 MonoReflectionField *f = (MonoReflectionField*)obj;
6149 token = mono_class_get_field_token (f->field);
6150 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6151 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6153 token = mono_class_get_property_token (p->property);
6154 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6155 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6157 token = mono_class_get_event_token (p->event);
6158 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6159 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6161 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6162 } else if (strcmp (klass->name, "Module") == 0) {
6163 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6166 } else if (strcmp (klass->name, "Assembly") == 0) {
6167 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6169 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6170 MonoException *ex = mono_get_exception_not_implemented (msg);
6172 mono_raise_exception (ex);
6179 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6181 int slen, type = t->type;
6186 case MONO_TYPE_BOOLEAN: {
6187 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6192 case MONO_TYPE_CHAR:
6194 case MONO_TYPE_I2: {
6195 guint16 *val = g_malloc (sizeof (guint16));
6200 #if SIZEOF_VOID_P == 4
6206 case MONO_TYPE_I4: {
6207 guint32 *val = g_malloc (sizeof (guint32));
6212 #if SIZEOF_VOID_P == 8
6213 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6218 case MONO_TYPE_I8: {
6219 guint64 *val = g_malloc (sizeof (guint64));
6224 case MONO_TYPE_VALUETYPE:
6225 if (t->data.klass->enumtype) {
6226 type = t->data.klass->enum_basetype->type;
6229 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6232 case MONO_TYPE_STRING:
6233 if (*p == (char)0xFF) {
6237 slen = mono_metadata_decode_value (p, &p);
6239 return mono_string_new_len (mono_domain_get (), p, slen);
6240 case MONO_TYPE_CLASS: {
6243 if (*p == (char)0xFF) {
6248 slen = mono_metadata_decode_value (p, &p);
6249 n = g_memdup (p, slen + 1);
6251 t = mono_reflection_type_from_name (n, image);
6253 g_warning ("Cannot load type '%s'", n);
6257 return mono_type_get_object (mono_domain_get (), t);
6261 case MONO_TYPE_OBJECT: {
6264 MonoClass *subc = NULL;
6269 } else if (subt == 0x0E) {
6270 type = MONO_TYPE_STRING;
6272 } else if (subt == 0x55) {
6275 slen = mono_metadata_decode_value (p, &p);
6276 n = g_memdup (p, slen + 1);
6278 t = mono_reflection_type_from_name (n, image);
6280 g_warning ("Cannot load type '%s'", n);
6283 subc = mono_class_from_mono_type (t);
6284 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6285 MonoType simple_type = {{0}};
6286 simple_type.type = subt;
6287 subc = mono_class_from_mono_type (&simple_type);
6289 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6291 val = load_cattr_value (image, &subc->byval_arg, p, end);
6292 obj = mono_object_new (mono_domain_get (), subc);
6293 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6297 case MONO_TYPE_SZARRAY: {
6299 guint32 i, alen, basetype;
6302 if (alen == 0xffffffff) {
6306 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6307 basetype = t->data.klass->byval_arg.type;
6312 case MONO_TYPE_BOOLEAN:
6313 for (i = 0; i < alen; i++) {
6314 MonoBoolean val = *p++;
6315 mono_array_set (arr, MonoBoolean, i, val);
6318 case MONO_TYPE_CHAR:
6321 for (i = 0; i < alen; i++) {
6322 guint16 val = read16 (p);
6323 mono_array_set (arr, guint16, i, val);
6330 for (i = 0; i < alen; i++) {
6331 guint32 val = read32 (p);
6332 mono_array_set (arr, guint32, i, val);
6339 for (i = 0; i < alen; i++) {
6340 guint64 val = read64 (p);
6341 mono_array_set (arr, guint64, i, val);
6345 case MONO_TYPE_CLASS:
6346 case MONO_TYPE_OBJECT:
6347 case MONO_TYPE_STRING:
6348 for (i = 0; i < alen; i++) {
6349 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6350 mono_array_set (arr, gpointer, i, item);
6354 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6360 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6366 type_is_reference (MonoType *type)
6368 switch (type->type) {
6369 case MONO_TYPE_BOOLEAN:
6370 case MONO_TYPE_CHAR:
6383 case MONO_TYPE_VALUETYPE:
6391 free_param_data (MonoMethodSignature *sig, void **params) {
6393 for (i = 0; i < sig->param_count; ++i) {
6394 if (!type_is_reference (sig->params [i]))
6395 g_free (params [i]);
6400 * Find the method index in the metadata methodDef table.
6401 * Later put these three helper methods in metadata and export them.
6404 find_method_index (MonoMethod *method) {
6405 MonoClass *klass = method->klass;
6408 for (i = 0; i < klass->method.count; ++i) {
6409 if (method == klass->methods [i])
6410 return klass->method.first + 1 + i;
6416 * Find the field index in the metadata FieldDef table.
6419 find_field_index (MonoClass *klass, MonoClassField *field) {
6422 for (i = 0; i < klass->field.count; ++i) {
6423 if (field == &klass->fields [i])
6424 return klass->field.first + 1 + i;
6430 * Find the property index in the metadata Property table.
6433 find_property_index (MonoClass *klass, MonoProperty *property) {
6436 for (i = 0; i < klass->property.count; ++i) {
6437 if (property == &klass->properties [i])
6438 return klass->property.first + 1 + i;
6444 * Find the event index in the metadata Event table.
6447 find_event_index (MonoClass *klass, MonoEvent *event) {
6450 for (i = 0; i < klass->event.count; ++i) {
6451 if (event == &klass->events [i])
6452 return klass->event.first + 1 + i;
6458 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6460 const char *p = data;
6462 guint32 i, j, num_named;
6466 mono_class_init (method->klass);
6469 attr = mono_object_new (mono_domain_get (), method->klass);
6470 mono_runtime_invoke (method, attr, NULL, NULL);
6474 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6477 /*g_print ("got attr %s\n", method->klass->name);*/
6479 params = g_new (void*, method->signature->param_count);
6483 for (i = 0; i < method->signature->param_count; ++i) {
6484 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6488 attr = mono_object_new (mono_domain_get (), method->klass);
6489 mono_runtime_invoke (method, attr, params, NULL);
6490 free_param_data (method->signature, params);
6492 num_named = read16 (named);
6494 for (j = 0; j < num_named; j++) {
6496 char *name, named_type, data_type;
6497 named_type = *named++;
6498 data_type = *named++; /* type of data */
6499 if (data_type == 0x55) {
6502 type_len = mono_metadata_decode_blob_size (named, &named);
6503 type_name = g_malloc (type_len + 1);
6504 memcpy (type_name, named, type_len);
6505 type_name [type_len] = 0;
6507 /* FIXME: lookup the type and check type consistency */
6508 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6509 /* this seems to be the type of the element of the array */
6510 /* g_print ("skipping 0x%02x after prop\n", *named); */
6513 name_len = mono_metadata_decode_blob_size (named, &named);
6514 name = g_malloc (name_len + 1);
6515 memcpy (name, named, name_len);
6516 name [name_len] = 0;
6518 if (named_type == 0x53) {
6519 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6520 void *val = load_cattr_value (image, field->type, named, &named);
6521 mono_field_set_value (attr, field, val);
6522 if (!type_is_reference (field->type))
6524 } else if (named_type == 0x54) {
6527 MonoType *prop_type;
6529 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6530 /* can we have more that 1 arg in a custom attr named property? */
6531 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6532 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6533 mono_property_set_value (prop, attr, pparams, NULL);
6534 if (!type_is_reference (prop_type))
6535 g_free (pparams [0]);
6544 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6551 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6552 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6553 for (i = 0; i < cinfo->num_attrs; ++i) {
6554 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6555 mono_array_set (result, gpointer, i, attr);
6561 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6563 guint32 mtoken, i, len;
6564 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6566 MonoCustomAttrInfo *ainfo;
6567 GList *tmp, *list = NULL;
6570 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6572 i = mono_metadata_custom_attrs_from_index (image, idx);
6576 while (i < ca->rows) {
6577 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6579 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6582 len = g_list_length (list);
6585 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6586 ainfo->num_attrs = len;
6587 ainfo->image = image;
6588 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6589 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6590 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6591 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6592 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6593 mtoken |= MONO_TOKEN_METHOD_DEF;
6595 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6596 mtoken |= MONO_TOKEN_MEMBER_REF;
6599 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6602 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6603 if (!ainfo->attrs [i].ctor)
6604 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6605 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6606 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6607 ainfo->attrs [i].data = data;
6615 mono_custom_attrs_from_method (MonoMethod *method)
6617 MonoCustomAttrInfo *cinfo;
6620 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6622 idx = find_method_index (method);
6623 idx <<= MONO_CUSTOM_ATTR_BITS;
6624 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6625 return mono_custom_attrs_from_index (method->klass->image, idx);
6629 mono_custom_attrs_from_class (MonoClass *klass)
6631 MonoCustomAttrInfo *cinfo;
6634 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6636 idx = mono_metadata_token_index (klass->type_token);
6637 idx <<= MONO_CUSTOM_ATTR_BITS;
6638 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6639 return mono_custom_attrs_from_index (klass->image, idx);
6643 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6645 MonoCustomAttrInfo *cinfo;
6648 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6650 idx = 1; /* there is only one assembly */
6651 idx <<= MONO_CUSTOM_ATTR_BITS;
6652 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6653 return mono_custom_attrs_from_index (assembly->image, idx);
6656 static MonoCustomAttrInfo*
6657 mono_custom_attrs_from_module (MonoImage *image)
6659 MonoCustomAttrInfo *cinfo;
6662 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6664 idx = 1; /* there is only one module */
6665 idx <<= MONO_CUSTOM_ATTR_BITS;
6666 idx |= MONO_CUSTOM_ATTR_MODULE;
6667 return mono_custom_attrs_from_index (image, idx);
6671 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6673 MonoCustomAttrInfo *cinfo;
6676 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6678 idx = find_property_index (klass, property);
6679 idx <<= MONO_CUSTOM_ATTR_BITS;
6680 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6681 return mono_custom_attrs_from_index (klass->image, idx);
6685 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6687 MonoCustomAttrInfo *cinfo;
6690 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6692 idx = find_event_index (klass, event);
6693 idx <<= MONO_CUSTOM_ATTR_BITS;
6694 idx |= MONO_CUSTOM_ATTR_EVENT;
6695 return mono_custom_attrs_from_index (klass->image, idx);
6699 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6701 MonoCustomAttrInfo *cinfo;
6704 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6706 idx = find_field_index (klass, field);
6707 idx <<= MONO_CUSTOM_ATTR_BITS;
6708 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6709 return mono_custom_attrs_from_index (klass->image, idx);
6713 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6716 guint32 i, idx, method_index;
6717 guint32 param_list, param_last, param_pos, found;
6719 MonoReflectionMethodAux *aux;
6721 if (method->klass->image->dynamic) {
6722 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6723 if (!aux || !aux->param_cattr)
6725 return aux->param_cattr [param];
6728 image = method->klass->image;
6729 method_index = find_method_index (method);
6730 ca = &image->tables [MONO_TABLE_METHOD];
6732 if (method->klass->generic_class || method->klass->generic_container ||
6733 method->signature->generic_param_count) {
6734 /* FIXME FIXME FIXME */
6738 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6739 if (method_index == ca->rows) {
6740 ca = &image->tables [MONO_TABLE_PARAM];
6741 param_last = ca->rows + 1;
6743 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6744 ca = &image->tables [MONO_TABLE_PARAM];
6747 for (i = param_list; i < param_last; ++i) {
6748 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6749 if (param_pos == param) {
6757 idx <<= MONO_CUSTOM_ATTR_BITS;
6758 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6759 return mono_custom_attrs_from_index (image, idx);
6763 * mono_reflection_get_custom_attrs:
6764 * @obj: a reflection object handle
6766 * Return an array with all the custom attributes defined of the
6767 * reflection handle @obj. The objects are fully build.
6770 mono_reflection_get_custom_attrs (MonoObject *obj)
6774 MonoCustomAttrInfo *cinfo = NULL;
6776 MONO_ARCH_SAVE_REGS;
6778 klass = obj->vtable->klass;
6779 if (klass == mono_defaults.monotype_class) {
6780 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6781 klass = mono_class_from_mono_type (rtype->type);
6782 cinfo = mono_custom_attrs_from_class (klass);
6783 } else if (strcmp ("Assembly", klass->name) == 0) {
6784 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6785 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6786 } else if (strcmp ("Module", klass->name) == 0) {
6787 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6788 cinfo = mono_custom_attrs_from_module (module->image);
6789 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6790 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6791 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6792 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6793 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6794 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6795 } else if (strcmp ("MonoField", klass->name) == 0) {
6796 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6797 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6798 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6799 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6800 cinfo = mono_custom_attrs_from_method (rmethod->method);
6801 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6802 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6803 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6804 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6805 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6806 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6807 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6808 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6809 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6810 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6811 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
6812 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
6813 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
6814 } else { /* handle other types here... */
6815 g_error ("get custom attrs not yet supported for %s", klass->name);
6819 result = mono_custom_attrs_construct (cinfo);
6821 mono_custom_attrs_free (cinfo);
6823 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6824 result = mono_array_new (mono_domain_get (), klass, 0);
6830 static MonoMethodSignature*
6831 parameters_to_signature (MonoArray *parameters) {
6832 MonoMethodSignature *sig;
6835 count = parameters? mono_array_length (parameters): 0;
6837 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6838 sig->param_count = count;
6839 sig->sentinelpos = -1; /* FIXME */
6840 for (i = 0; i < count; ++i) {
6841 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6842 sig->params [i] = pt->type;
6847 static MonoMethodSignature*
6848 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6849 MonoMethodSignature *sig;
6851 sig = parameters_to_signature (ctor->parameters);
6852 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6853 sig->ret = &mono_defaults.void_class->byval_arg;
6857 static MonoMethodSignature*
6858 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6859 MonoMethodSignature *sig;
6861 sig = parameters_to_signature (method->parameters);
6862 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6863 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6864 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6868 static MonoMethodSignature*
6869 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6870 MonoMethodSignature *sig;
6872 sig = parameters_to_signature (method->parameters);
6873 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6874 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6875 sig->generic_param_count = 0;
6880 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6882 MonoClass *klass = mono_object_class (prop);
6883 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6884 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6885 *name = mono_string_to_utf8 (pb->name);
6886 *type = pb->type->type;
6888 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6889 *name = g_strdup (p->property->name);
6890 if (p->property->get)
6891 *type = p->property->get->signature->ret;
6893 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6898 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6900 MonoClass *klass = mono_object_class (field);
6901 if (strcmp (klass->name, "FieldBuilder") == 0) {
6902 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6903 *name = mono_string_to_utf8 (fb->name);
6904 *type = fb->type->type;
6906 MonoReflectionField *f = (MonoReflectionField *)field;
6907 *name = g_strdup (f->field->name);
6908 *type = f->field->type;
6913 * Encode a value in a custom attribute stream of bytes.
6914 * The value to encode is either supplied as an object in argument val
6915 * (valuetypes are boxed), or as a pointer to the data in the
6917 * @type represents the type of the value
6918 * @buffer is the start of the buffer
6919 * @p the current position in the buffer
6920 * @buflen contains the size of the buffer and is used to return the new buffer size
6921 * if this needs to be realloced.
6922 * @retbuffer and @retp return the start and the position of the buffer
6925 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6927 MonoTypeEnum simple_type;
6929 if ((p-buffer) + 10 >= *buflen) {
6932 newbuf = g_realloc (buffer, *buflen);
6933 p = newbuf + (p-buffer);
6937 argval = ((char*)arg + sizeof (MonoObject));
6938 simple_type = type->type;
6940 switch (simple_type) {
6941 case MONO_TYPE_BOOLEAN:
6946 case MONO_TYPE_CHAR:
6949 swap_with_size (p, argval, 2, 1);
6955 swap_with_size (p, argval, 4, 1);
6961 swap_with_size (p, argval, 8, 1);
6964 case MONO_TYPE_VALUETYPE:
6965 if (type->data.klass->enumtype) {
6966 simple_type = type->data.klass->enum_basetype->type;
6969 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6972 case MONO_TYPE_STRING: {
6979 str = mono_string_to_utf8 ((MonoString*)arg);
6980 slen = strlen (str);
6981 if ((p-buffer) + 10 + slen >= *buflen) {
6985 newbuf = g_realloc (buffer, *buflen);
6986 p = newbuf + (p-buffer);
6989 mono_metadata_encode_value (slen, p, &p);
6990 memcpy (p, str, slen);
6995 case MONO_TYPE_CLASS: {
7003 k = mono_object_class (arg);
7004 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7005 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7006 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7008 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7009 slen = strlen (str);
7010 if ((p-buffer) + 10 + slen >= *buflen) {
7014 newbuf = g_realloc (buffer, *buflen);
7015 p = newbuf + (p-buffer);
7018 mono_metadata_encode_value (slen, p, &p);
7019 memcpy (p, str, slen);
7024 case MONO_TYPE_SZARRAY: {
7026 MonoClass *eclass, *arg_eclass;
7029 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7032 len = mono_array_length ((MonoArray*)arg);
7034 *p++ = (len >> 8) & 0xff;
7035 *p++ = (len >> 16) & 0xff;
7036 *p++ = (len >> 24) & 0xff;
7038 *retbuffer = buffer;
7039 eclass = type->data.klass;
7040 arg_eclass = mono_object_class (arg)->element_class;
7041 if (eclass->valuetype && arg_eclass->valuetype) {
7042 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7043 int elsize = mono_class_array_element_size (eclass);
7044 for (i = 0; i < len; ++i) {
7045 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7049 for (i = 0; i < len; ++i) {
7050 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7055 /* it may be a boxed value or a Type */
7056 case MONO_TYPE_OBJECT: {
7062 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7067 klass = mono_object_class (arg);
7069 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7072 } else if (klass->enumtype) {
7074 } else if (klass == mono_defaults.string_class) {
7075 simple_type = MONO_TYPE_STRING;
7078 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7079 *p++ = simple_type = klass->byval_arg.type;
7082 g_error ("unhandled type in custom attr");
7084 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7085 slen = strlen (str);
7086 if ((p-buffer) + 10 + slen >= *buflen) {
7090 newbuf = g_realloc (buffer, *buflen);
7091 p = newbuf + (p-buffer);
7094 mono_metadata_encode_value (slen, p, &p);
7095 memcpy (p, str, slen);
7098 simple_type = klass->enum_basetype->type;
7102 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7105 *retbuffer = buffer;
7109 * mono_reflection_get_custom_attrs_blob:
7110 * @ctor: custom attribute constructor
7111 * @ctorArgs: arguments o the constructor
7117 * Creates the blob of data that needs to be saved in the metadata and that represents
7118 * the custom attributed described by @ctor, @ctorArgs etc.
7119 * Returns: a Byte array representing the blob of data.
7122 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7125 MonoMethodSignature *sig;
7130 MONO_ARCH_SAVE_REGS;
7132 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7133 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7135 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7137 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7139 p = buffer = g_malloc (buflen);
7140 /* write the prolog */
7143 for (i = 0; i < sig->param_count; ++i) {
7144 arg = mono_array_get (ctorArgs, MonoObject*, i);
7145 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7149 i += mono_array_length (properties);
7151 i += mono_array_length (fields);
7153 *p++ = (i >> 8) & 0xff;
7156 for (i = 0; i < mono_array_length (properties); ++i) {
7161 prop = mono_array_get (properties, gpointer, i);
7162 get_prop_name_and_type (prop, &pname, &ptype);
7163 *p++ = 0x54; /* PROPERTY signature */
7165 /* Preallocate a large enough buffer */
7166 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7167 char *str = type_get_qualified_name (ptype, NULL);
7173 len += strlen (pname);
7175 if ((p-buffer) + 20 + len >= buflen) {
7179 newbuf = g_realloc (buffer, buflen);
7180 p = newbuf + (p-buffer);
7184 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7185 char *str = type_get_qualified_name (ptype, NULL);
7186 int slen = strlen (str);
7190 * This seems to be optional...
7193 mono_metadata_encode_value (slen, p, &p);
7194 memcpy (p, str, slen);
7198 mono_metadata_encode_value (ptype->type, p, &p);
7199 if (ptype->type == MONO_TYPE_SZARRAY)
7200 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7202 len = strlen (pname);
7203 mono_metadata_encode_value (len, p, &p);
7204 memcpy (p, pname, len);
7206 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7213 for (i = 0; i < mono_array_length (fields); ++i) {
7218 field = mono_array_get (fields, gpointer, i);
7219 get_field_name_and_type (field, &fname, &ftype);
7220 *p++ = 0x53; /* FIELD signature */
7221 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7222 char *str = type_get_qualified_name (ftype, NULL);
7223 int slen = strlen (str);
7224 if ((p-buffer) + 10 + slen >= buflen) {
7228 newbuf = g_realloc (buffer, buflen);
7229 p = newbuf + (p-buffer);
7234 * This seems to be optional...
7237 mono_metadata_encode_value (slen, p, &p);
7238 memcpy (p, str, slen);
7242 mono_metadata_encode_value (ftype->type, p, &p);
7243 if (ftype->type == MONO_TYPE_SZARRAY)
7244 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7246 len = strlen (fname);
7247 mono_metadata_encode_value (len, p, &p);
7248 memcpy (p, fname, len);
7250 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7255 g_assert (p - buffer <= buflen);
7256 buflen = p - buffer;
7257 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7258 p = mono_array_addr (result, char, 0);
7259 memcpy (p, buffer, buflen);
7261 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7267 * mono_reflection_setup_internal_class:
7268 * @tb: a TypeBuilder object
7270 * Creates a MonoClass that represents the TypeBuilder.
7271 * This is a trick that lets us simplify a lot of reflection code
7272 * (and will allow us to support Build and Run assemblies easier).
7275 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7277 MonoClass *klass, *parent;
7279 MONO_ARCH_SAVE_REGS;
7282 /* check so we can compile corlib correctly */
7283 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7284 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7285 parent = tb->parent->type->data.klass;
7287 parent = my_mono_class_from_mono_type (tb->parent->type);
7293 /* the type has already being created: it means we just have to change the parent */
7294 if (tb->type.type) {
7295 klass = mono_class_from_mono_type (tb->type.type);
7296 klass->parent = NULL;
7297 /* fool mono_class_setup_parent */
7298 g_free (klass->supertypes);
7299 klass->supertypes = NULL;
7300 mono_class_setup_parent (klass, parent);
7301 mono_class_setup_mono_type (klass);
7305 klass = g_new0 (MonoClass, 1);
7307 klass->image = &tb->module->dynamic_image->image;
7309 klass->inited = 1; /* we lie to the runtime */
7310 klass->name = mono_string_to_utf8 (tb->name);
7311 klass->name_space = mono_string_to_utf8 (tb->nspace);
7312 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7313 klass->flags = tb->attrs;
7315 klass->element_class = klass;
7316 klass->reflection_info = tb; /* need to pin. */
7318 /* Put into cache so mono_class_get () will find it */
7319 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7321 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7322 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7324 if (parent != NULL) {
7325 mono_class_setup_parent (klass, parent);
7326 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7327 const char *old_n = klass->name;
7328 /* trick to get relative numbering right when compiling corlib */
7329 klass->name = "BuildingObject";
7330 mono_class_setup_parent (klass, mono_defaults.object_class);
7331 klass->name = old_n;
7334 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7335 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7336 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7337 klass->instance_size = sizeof (MonoObject);
7338 klass->size_inited = 1;
7339 mono_class_setup_vtable (klass, NULL, 0);
7342 mono_class_setup_mono_type (klass);
7344 mono_class_setup_supertypes (klass);
7347 * FIXME: handle interfaces.
7350 tb->type.type = &klass->byval_arg;
7352 if (tb->nesting_type) {
7353 g_assert (tb->nesting_type->type);
7354 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7357 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7361 * mono_reflection_setup_generic_class:
7362 * @tb: a TypeBuilder object
7364 * Setup the generic class before adding the first generic parameter.
7367 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7371 MONO_ARCH_SAVE_REGS;
7373 klass = my_mono_class_from_mono_type (tb->type.type);
7374 if (tb->generic_container)
7377 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7378 tb->generic_container->klass = klass;
7380 tb->generic_container->context.container = tb->generic_container;
7384 * mono_reflection_create_generic_class:
7385 * @tb: a TypeBuilder object
7387 * Creates the generic class after all generic parameters have been added.
7390 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7395 MONO_ARCH_SAVE_REGS;
7397 klass = my_mono_class_from_mono_type (tb->type.type);
7399 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7401 if (klass->generic_container || (count == 0))
7404 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7406 klass->generic_container = tb->generic_container;
7408 klass->generic_container->type_argc = count;
7409 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7411 for (i = 0; i < count; i++) {
7412 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7413 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7414 g_assert (klass->generic_container->type_params [i].owner);
7419 * mono_reflection_create_internal_class:
7420 * @tb: a TypeBuilder object
7422 * Actually create the MonoClass that is associated with the TypeBuilder.
7425 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7429 MONO_ARCH_SAVE_REGS;
7431 klass = my_mono_class_from_mono_type (tb->type.type);
7433 if (klass->enumtype && klass->enum_basetype == NULL) {
7434 MonoReflectionFieldBuilder *fb;
7437 g_assert (tb->fields != NULL);
7438 g_assert (mono_array_length (tb->fields) >= 1);
7440 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7442 klass->enum_basetype = fb->type->type;
7443 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7444 if (!klass->element_class)
7445 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7448 * get the element_class from the current corlib.
7450 ec = default_class_from_mono_type (klass->enum_basetype);
7451 klass->instance_size = ec->instance_size;
7452 klass->size_inited = 1;
7454 * this is almost safe to do with enums and it's needed to be able
7455 * to create objects of the enum type (for use in SetConstant).
7457 /* FIXME: Does this mean enums can't have method overrides ? */
7458 mono_class_setup_vtable (klass, NULL, 0);
7462 static MonoMarshalSpec*
7463 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7464 MonoReflectionMarshal *minfo)
7466 MonoMarshalSpec *res;
7468 res = g_new0 (MonoMarshalSpec, 1);
7469 res->native = minfo->type;
7471 switch (minfo->type) {
7472 case MONO_NATIVE_LPARRAY:
7473 res->data.array_data.elem_type = minfo->eltype;
7474 res->data.array_data.param_num = 0; /* Not yet */
7475 res->data.array_data.num_elem = minfo->count;
7478 case MONO_NATIVE_BYVALTSTR:
7479 case MONO_NATIVE_BYVALARRAY:
7480 res->data.array_data.num_elem = minfo->count;
7483 case MONO_NATIVE_CUSTOM:
7484 if (minfo->marshaltyperef)
7485 res->data.custom_data.custom_name =
7486 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7488 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7498 MonoReflectionMarshal*
7499 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7500 MonoMarshalSpec *spec)
7502 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7503 MonoReflectionMarshal *minfo;
7506 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7507 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7508 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7509 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7512 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7513 minfo->type = spec->native;
7515 switch (minfo->type) {
7516 case MONO_NATIVE_LPARRAY:
7517 minfo->eltype = spec->data.array_data.elem_type;
7518 minfo->count = spec->data.array_data.num_elem;
7521 case MONO_NATIVE_BYVALTSTR:
7522 case MONO_NATIVE_BYVALARRAY:
7523 minfo->count = spec->data.array_data.num_elem;
7526 case MONO_NATIVE_CUSTOM:
7527 if (spec->data.custom_data.custom_name) {
7528 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7530 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7532 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7534 if (spec->data.custom_data.cookie)
7535 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7546 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7547 ReflectionMethodBuilder *rmb,
7548 MonoMethodSignature *sig)
7551 MonoMethodNormal *pm;
7552 MonoMarshalSpec **specs;
7553 MonoReflectionMethodAux *method_aux;
7556 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7557 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7558 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7560 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7562 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7564 pm = (MonoMethodNormal*)m;
7567 m->flags = rmb->attrs;
7568 m->iflags = rmb->iattrs;
7569 m->name = mono_string_to_utf8 (rmb->name);
7573 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7575 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7576 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7579 m->signature->pinvoke = 1;
7580 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7581 m->signature->pinvoke = 1;
7583 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7585 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7586 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7588 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7590 if (klass->image->dynamic)
7591 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7594 } else if (!m->klass->dummy &&
7595 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7596 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7597 MonoMethodHeader *header;
7599 gint32 max_stack, i;
7600 gint32 num_locals = 0;
7601 gint32 num_clauses = 0;
7605 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7606 code_size = rmb->ilgen->code_len;
7607 max_stack = rmb->ilgen->max_stack;
7608 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7609 if (rmb->ilgen->ex_handlers)
7610 num_clauses = method_count_clauses (rmb->ilgen);
7613 code = mono_array_addr (rmb->code, guint8, 0);
7614 code_size = mono_array_length (rmb->code);
7615 /* we probably need to run a verifier on the code... */
7625 header = g_malloc0 (sizeof (MonoMethodHeader) +
7626 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7627 header->code_size = code_size;
7628 header->code = g_malloc (code_size);
7629 memcpy ((char*)header->code, code, code_size);
7630 header->max_stack = max_stack;
7631 header->init_locals = rmb->init_locals;
7632 header->num_locals = num_locals;
7634 for (i = 0; i < num_locals; ++i) {
7635 MonoReflectionLocalBuilder *lb =
7636 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7638 header->locals [i] = g_new0 (MonoType, 1);
7639 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7642 header->num_clauses = num_clauses;
7644 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7645 rmb->ilgen, num_clauses);
7648 pm->header = header;
7651 if (rmb->generic_params) {
7652 int count = mono_array_length (rmb->generic_params);
7653 MonoGenericContainer *container;
7655 pm->generic_container = container = rmb->generic_container;
7656 container->type_argc = count;
7657 container->type_params = g_new0 (MonoGenericParam, count);
7659 for (i = 0; i < count; i++) {
7660 MonoReflectionGenericParam *gp =
7661 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7663 container->type_params [i] = *gp->type.type->data.generic_param;
7668 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7671 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7673 for (i = 0; i < rmb->nrefs; ++i)
7674 mw->data = g_list_append (mw->data, rmb->refs [i]);
7679 /* Parameter info */
7682 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7683 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7684 for (i = 0; i <= m->signature->param_count; ++i) {
7685 MonoReflectionParamBuilder *pb;
7686 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7688 m->signature->params [i - 1]->attrs = pb->attrs;
7690 if (pb->def_value) {
7691 MonoDynamicImage *assembly;
7692 guint32 idx, def_type, len;
7696 if (!method_aux->param_defaults)
7697 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7698 assembly = (MonoDynamicImage*)klass->image;
7699 idx = encode_constant (assembly, pb->def_value, &def_type);
7700 /* Copy the data from the blob since it might get realloc-ed */
7701 p = assembly->blob.data + idx;
7702 len = mono_metadata_decode_blob_size (p, &p2);
7704 method_aux->param_defaults [i] = g_malloc (len);
7705 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7709 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7711 if (!method_aux->param_cattr)
7712 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7713 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7719 /* Parameter marshalling */
7722 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7723 MonoReflectionParamBuilder *pb;
7724 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7725 if (pb->marshal_info) {
7727 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7728 specs [pb->position] =
7729 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7733 if (specs != NULL) {
7735 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7736 method_aux->param_marshall = specs;
7739 if (klass->image->dynamic && method_aux)
7740 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7746 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7748 ReflectionMethodBuilder rmb;
7749 MonoMethodSignature *sig;
7751 sig = ctor_builder_to_signature (mb);
7753 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7755 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7756 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7758 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7759 /* ilgen is no longer needed */
7767 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7769 ReflectionMethodBuilder rmb;
7770 MonoMethodSignature *sig;
7772 sig = method_builder_to_signature (mb);
7774 reflection_methodbuilder_from_method_builder (&rmb, mb);
7776 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7777 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7779 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7780 /* ilgen is no longer needed */
7786 static MonoClassField*
7787 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7789 MonoClassField *field;
7796 field = g_new0 (MonoClassField, 1);
7798 field->name = mono_string_to_utf8 (fb->name);
7800 /* FIXME: handle type modifiers */
7801 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7802 field->type->attrs = fb->attrs;
7804 field->type = fb->type->type;
7806 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7807 field->data = mono_array_addr (fb->rva_data, char, 0);
7808 if (fb->offset != -1)
7809 field->offset = fb->offset;
7810 field->parent = klass;
7812 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7814 if (fb->def_value) {
7815 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7816 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7817 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7818 /* Copy the data from the blob since it might get realloc-ed */
7819 p = assembly->blob.data + idx;
7820 len = mono_metadata_decode_blob_size (p, &p2);
7822 field->data = g_malloc (len);
7823 memcpy ((gpointer)field->data, p, len);
7830 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
7834 MonoReflectionTypeBuilder *tb = NULL;
7835 MonoGenericClass *gclass, *cached;
7836 MonoDynamicGenericClass *dgclass = NULL;
7837 gboolean is_dynamic = FALSE;
7842 klass = mono_class_from_mono_type (type->type);
7843 if (!klass->generic_container && !klass->generic_class &&
7844 !(klass->nested_in && klass->nested_in->generic_container))
7847 mono_loader_lock ();
7849 domain = mono_object_domain (type);
7851 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7852 tb = (MonoReflectionTypeBuilder *) type;
7854 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7856 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
7857 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
7858 MonoReflectionType *rgt = rgi->generic_type;
7860 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7861 tb = (MonoReflectionTypeBuilder *) rgt;
7863 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7866 icount = klass->interface_count;
7870 dgclass = g_new0 (MonoDynamicGenericClass, 1);
7871 gclass = &dgclass->generic_class;
7872 gclass->is_dynamic = TRUE;
7874 gclass = g_new0 (MonoGenericClass, 1);
7876 gclass->inst = g_new0 (MonoGenericInst, 1);
7878 gclass->inst->type_argc = type_argc;
7879 gclass->inst->type_argv = types;
7881 for (i = 0; i < gclass->inst->type_argc; ++i) {
7882 if (!gclass->inst->is_open)
7883 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
7886 gclass->container_class = klass;
7888 if (klass->generic_class) {
7889 MonoGenericClass *kgclass = klass->generic_class;
7890 MonoGenericClass *ogclass = gclass;
7892 ogclass->context = g_new0 (MonoGenericContext, 1);
7893 ogclass->context->container = ogclass->container_class->generic_container;
7894 ogclass->context->gclass = ogclass;
7897 dgclass = g_new0 (MonoDynamicGenericClass, 1);
7898 gclass = &dgclass->generic_class;
7899 gclass->is_dynamic = TRUE;
7901 gclass = g_new0 (MonoGenericClass, 1);
7903 gclass->inst = g_new0 (MonoGenericInst, 1);
7905 gclass->inst->type_argc = kgclass->inst->type_argc;
7906 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
7908 for (i = 0; i < gclass->inst->type_argc; i++) {
7909 MonoType *t = kgclass->inst->type_argv [i];
7911 t = mono_class_inflate_generic_type (t, ogclass->context);
7913 if (!gclass->inst->is_open)
7914 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
7916 gclass->inst->type_argv [i] = t;
7919 gclass->container_class = kgclass->container_class;
7922 geninst = g_new0 (MonoType, 1);
7923 geninst->type = MONO_TYPE_GENERICINST;
7925 cached = mono_metadata_lookup_generic_class (gclass);
7928 mono_loader_unlock ();
7929 geninst->data.generic_class = cached;
7933 geninst->data.generic_class = gclass;
7935 gclass->parent = parent;
7937 gclass->context = g_new0 (MonoGenericContext, 1);
7938 gclass->context->container = gclass->container_class->generic_container;
7939 gclass->context->gclass = gclass;
7941 gclass->ifaces = g_new0 (MonoType *, icount);
7942 gclass->count_ifaces = icount;
7944 for (i = 0; i < icount; i++) {
7945 MonoReflectionType *itype;
7948 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7950 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7951 gclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7952 if (!gclass->ifaces [i])
7953 gclass->ifaces [i] = itype->type;
7956 mono_class_create_generic (gclass);
7957 mono_class_create_generic_2 (gclass);
7959 mono_loader_unlock ();
7965 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7967 MonoClass *klass, *pklass = NULL;
7968 MonoReflectionType *parent = NULL;
7969 MonoType *the_parent = NULL, *geninst;
7970 MonoReflectionTypeBuilder *tb = NULL;
7971 MonoGenericClass *gclass;
7974 domain = mono_object_domain (type);
7975 klass = mono_class_from_mono_type (type->type);
7977 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7978 tb = (MonoReflectionTypeBuilder *) type;
7981 parent = tb->parent;
7982 pklass = mono_class_from_mono_type (parent->type);
7985 pklass = klass->parent;
7987 parent = mono_type_get_object (domain, &pklass->byval_arg);
7988 else if (klass->generic_class && klass->generic_class->parent) {
7989 parent = mono_type_get_object (domain, klass->generic_class->parent);
7990 pklass = mono_class_from_mono_type (klass->generic_class->parent);
7994 if (pklass && pklass->generic_class)
7995 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7997 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
8001 gclass = geninst->data.generic_class;
8007 dup_type (const MonoType *original)
8009 MonoType *r = g_new0 (MonoType, 1);
8011 r->attrs = original->attrs;
8012 r->byref = original->byref;
8013 mono_stats.generics_metadata_size += sizeof (MonoType);
8017 MonoReflectionMethod*
8018 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8020 MonoMethod *method, *inflated;
8021 MonoReflectionMethodBuilder *mb = NULL;
8022 MonoGenericContainer *container;
8023 MonoGenericMethod *gmethod;
8024 MonoGenericContext *context;
8025 MonoGenericInst *ginst;
8028 MONO_ARCH_SAVE_REGS;
8029 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8030 MonoReflectionTypeBuilder *tb;
8033 mb = (MonoReflectionMethodBuilder *) rmethod;
8034 tb = (MonoReflectionTypeBuilder *) mb->type;
8035 klass = mono_class_from_mono_type (tb->type.type);
8037 method = methodbuilder_to_mono_method (klass, mb);
8039 method = rmethod->method;
8042 count = method->signature->generic_param_count;
8043 if (count != mono_array_length (types))
8046 container = ((MonoMethodNormal*) method)->generic_container;
8047 g_assert (container);
8049 if (!container->method_hash)
8050 container->method_hash = g_hash_table_new (
8051 (GHashFunc) mono_metadata_generic_method_hash,
8052 (GCompareFunc) mono_metadata_generic_method_equal);
8054 ginst = g_new0 (MonoGenericInst,1 );
8055 ginst->type_argc = count;
8056 ginst->type_argv = g_new0 (MonoType *, count);
8057 for (i = 0; i < count; i++) {
8058 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8059 ginst->type_argv [i] = dup_type (garg->type);
8061 if (!ginst->is_open)
8062 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8064 ginst = mono_metadata_lookup_generic_inst (ginst);
8066 gmethod = g_new0 (MonoGenericMethod, 1);
8067 gmethod->container = container;
8068 gmethod->inst = ginst;
8070 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8074 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8077 gmethod->reflection_info = rmethod;
8079 context = g_new0 (MonoGenericContext, 1);
8080 context->container = container;
8081 context->gclass = method->klass->generic_class;
8082 context->gmethod = gmethod;
8084 inflated = mono_class_inflate_generic_method (method, context, NULL);
8085 g_hash_table_insert (container->method_hash, gmethod, inflated);
8087 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8091 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8093 MonoGenericMethod *gmethod;
8094 MonoGenericClass *gclass;
8095 MonoGenericContext *context;
8098 gclass = type->type.type->data.generic_class;
8100 gmethod = g_new0 (MonoGenericMethod, 1);
8101 gmethod->inst = g_new0 (MonoGenericInst, 1);
8102 gmethod->reflection_info = obj;
8104 gmethod->inst->type_argc = method->signature->generic_param_count;
8105 gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8107 for (i = 0; i < gmethod->inst->type_argc; i++) {
8108 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8109 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8111 g_assert (gparam->pklass);
8112 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8115 context = g_new0 (MonoGenericContext, 1);
8116 context->container = gclass->container_class->generic_container;
8117 context->gclass = gclass;
8118 context->gmethod = gmethod;
8120 return mono_class_inflate_generic_method (method, context, gclass->klass);
8124 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8129 klass = mono_class_from_mono_type (type->type.type);
8131 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8132 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8133 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8134 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8135 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8136 method = ((MonoReflectionMethod *) obj)->method;
8138 method = NULL; /* prevent compiler warning */
8139 g_assert_not_reached ();
8142 return inflate_mono_method (type, method, obj);
8146 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8147 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8150 MonoGenericClass *gclass;
8151 MonoDynamicGenericClass *dgclass;
8152 MonoClass *klass, *gklass, *pklass;
8155 MONO_ARCH_SAVE_REGS;
8157 klass = mono_class_from_mono_type (type->type.type);
8158 gclass = type->type.type->data.generic_class;
8160 if (gclass->initialized)
8163 g_assert (gclass->is_dynamic);
8164 dgclass = (MonoDynamicGenericClass *) gclass;
8166 gklass = gclass->container_class;
8167 mono_class_init (gklass);
8170 pklass = mono_class_from_mono_type (gclass->parent);
8172 pklass = gklass->parent;
8174 mono_class_setup_parent (klass, pklass);
8176 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8177 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8178 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8179 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8180 dgclass->count_events = events ? mono_array_length (events) : 0;
8182 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8183 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8184 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8185 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8186 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8188 for (i = 0; i < dgclass->count_methods; i++) {
8189 MonoObject *obj = mono_array_get (methods, gpointer, i);
8191 dgclass->methods [i] = inflate_method (type, obj);
8194 for (i = 0; i < dgclass->count_ctors; i++) {
8195 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8197 dgclass->ctors [i] = inflate_method (type, obj);
8200 for (i = 0; i < dgclass->count_fields; i++) {
8201 MonoObject *obj = mono_array_get (fields, gpointer, i);
8202 MonoClassField *field;
8203 MonoInflatedField *ifield;
8205 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8206 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8207 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8208 field = ((MonoReflectionField *) obj)->field;
8210 field = NULL; /* prevent compiler warning */
8211 g_assert_not_reached ();
8214 ifield = g_new0 (MonoInflatedField, 1);
8215 ifield->generic_type = field->type;
8216 ifield->reflection_info = obj;
8218 dgclass->fields [i] = *field;
8219 dgclass->fields [i].generic_info = ifield;
8220 dgclass->fields [i].type = mono_class_inflate_generic_type (field->type, gclass->context);
8223 for (i = 0; i < dgclass->count_properties; i++) {
8224 MonoObject *obj = mono_array_get (properties, gpointer, i);
8225 MonoProperty *property = &dgclass->properties [i];
8227 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8228 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8230 property->parent = klass;
8231 property->attrs = pb->attrs;
8232 property->name = mono_string_to_utf8 (pb->name);
8234 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8236 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8237 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8238 *property = *((MonoReflectionProperty *) obj)->property;
8241 property->get = inflate_mono_method (type, property->get, NULL);
8243 property->set = inflate_mono_method (type, property->set, NULL);
8245 g_assert_not_reached ();
8248 for (i = 0; i < dgclass->count_events; i++) {
8249 MonoObject *obj = mono_array_get (events, gpointer, i);
8250 MonoEvent *event = &dgclass->events [i];
8252 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8253 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8255 event->parent = klass;
8256 event->attrs = eb->attrs;
8257 event->name = mono_string_to_utf8 (eb->name);
8259 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8260 if (eb->remove_method)
8261 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8262 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8263 *event = *((MonoReflectionEvent *) obj)->event;
8266 event->add = inflate_mono_method (type, event->add, NULL);
8268 event->remove = inflate_mono_method (type, event->remove, NULL);
8270 g_assert_not_reached ();
8273 gclass->initialized = TRUE;
8277 ensure_runtime_vtable (MonoClass *klass)
8279 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8280 int i, num, j, onum;
8281 MonoMethod **overrides;
8283 if (!tb || klass->wastypebuilder)
8286 ensure_runtime_vtable (klass->parent);
8288 num = tb->ctors? mono_array_length (tb->ctors): 0;
8289 num += tb->num_methods;
8290 klass->method.count = num;
8291 klass->methods = g_new (MonoMethod*, num);
8292 num = tb->ctors? mono_array_length (tb->ctors): 0;
8293 for (i = 0; i < num; ++i)
8294 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8295 num = tb->num_methods;
8297 for (i = 0; i < num; ++i)
8298 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8300 if (tb->interfaces) {
8301 klass->interface_count = mono_array_length (tb->interfaces);
8302 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8303 for (i = 0; i < klass->interface_count; ++i) {
8304 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8305 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8309 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8310 for (i = 0; i < klass->method.count; ++i)
8311 klass->methods [i]->slot = i;
8316 for (i = 0; i < tb->num_methods; ++i) {
8317 MonoReflectionMethodBuilder *mb =
8318 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8319 if (mb->override_method)
8324 overrides = g_new0 (MonoMethod*, onum * 2);
8328 for (i = 0; i < tb->num_methods; ++i) {
8329 MonoReflectionMethodBuilder *mb =
8330 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8331 if (mb->override_method) {
8332 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8333 overrides [onum * 2] =
8334 mb->override_method->method;
8335 overrides [onum * 2 + 1] =
8338 g_assert (mb->mhandle);
8345 mono_class_setup_vtable (klass, overrides, onum);
8350 typebuilder_setup_fields (MonoClass *klass)
8352 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8353 MonoReflectionFieldBuilder *fb;
8354 MonoClassField *field;
8359 klass->field.count = tb->num_fields;
8360 klass->field.first = 0;
8361 klass->field.last = klass->field.count;
8363 if (!klass->field.count)
8366 klass->fields = g_new0 (MonoClassField, klass->field.count);
8368 for (i = 0; i < klass->field.count; ++i) {
8369 fb = mono_array_get (tb->fields, gpointer, i);
8370 field = &klass->fields [i];
8371 field->name = mono_string_to_utf8 (fb->name);
8373 /* FIXME: handle type modifiers */
8374 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8375 field->type->attrs = fb->attrs;
8377 field->type = fb->type->type;
8379 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8380 field->data = mono_array_addr (fb->rva_data, char, 0);
8381 if (fb->offset != -1)
8382 field->offset = fb->offset;
8383 field->parent = klass;
8385 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8387 if (fb->def_value) {
8388 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8389 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8390 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8391 /* Copy the data from the blob since it might get realloc-ed */
8392 p = assembly->blob.data + idx;
8393 len = mono_metadata_decode_blob_size (p, &p2);
8395 field->data = g_malloc (len);
8396 memcpy ((gpointer)field->data, p, len);
8399 mono_class_layout_fields (klass);
8403 typebuilder_setup_properties (MonoClass *klass)
8405 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8406 MonoReflectionPropertyBuilder *pb;
8409 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8410 klass->property.first = 0;
8411 klass->property.last = klass->property.count;
8413 klass->properties = g_new0 (MonoProperty, klass->property.count);
8414 for (i = 0; i < klass->property.count; ++i) {
8415 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8416 klass->properties [i].parent = klass;
8417 klass->properties [i].attrs = pb->attrs;
8418 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8420 klass->properties [i].get = pb->get_method->mhandle;
8422 klass->properties [i].set = pb->set_method->mhandle;
8426 MonoReflectionEvent *
8427 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8429 MonoEvent *event = g_new0 (MonoEvent, 1);
8433 klass = my_mono_class_from_mono_type (tb->type.type);
8435 event->parent = klass;
8436 event->attrs = eb->attrs;
8437 event->name = mono_string_to_utf8 (eb->name);
8439 event->add = eb->add_method->mhandle;
8440 if (eb->remove_method)
8441 event->remove = eb->remove_method->mhandle;
8442 if (eb->raise_method)
8443 event->raise = eb->raise_method->mhandle;
8445 if (eb->other_methods) {
8446 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8447 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8448 MonoReflectionMethodBuilder *mb =
8449 mono_array_get (eb->other_methods,
8450 MonoReflectionMethodBuilder*, j);
8451 event->other [j] = mb->mhandle;
8455 return mono_event_get_object (mono_object_domain (tb), klass, event);
8459 typebuilder_setup_events (MonoClass *klass)
8461 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8462 MonoReflectionEventBuilder *eb;
8465 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8466 klass->event.first = 0;
8467 klass->event.last = klass->event.count;
8469 klass->events = g_new0 (MonoEvent, klass->event.count);
8470 for (i = 0; i < klass->event.count; ++i) {
8471 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8472 klass->events [i].parent = klass;
8473 klass->events [i].attrs = eb->attrs;
8474 klass->events [i].name = mono_string_to_utf8 (eb->name);
8476 klass->events [i].add = eb->add_method->mhandle;
8477 if (eb->remove_method)
8478 klass->events [i].remove = eb->remove_method->mhandle;
8479 if (eb->raise_method)
8480 klass->events [i].raise = eb->raise_method->mhandle;
8482 if (eb->other_methods) {
8483 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8484 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8485 MonoReflectionMethodBuilder *mb =
8486 mono_array_get (eb->other_methods,
8487 MonoReflectionMethodBuilder*, j);
8488 klass->events [i].other [j] = mb->mhandle;
8495 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8498 MonoReflectionType* res;
8501 MONO_ARCH_SAVE_REGS;
8503 klass = my_mono_class_from_mono_type (tb->type.type);
8505 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8508 * Fields to set in klass:
8509 * the various flags: delegate/unicode/contextbound etc.
8511 klass->flags = tb->attrs;
8513 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8514 /* No need to fully construct the type */
8515 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8517 /* enums are done right away */
8518 if (!klass->enumtype)
8519 ensure_runtime_vtable (klass);
8522 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8523 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8524 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8528 /* fields and object layout */
8529 if (klass->parent) {
8530 if (!klass->parent->size_inited)
8531 mono_class_init (klass->parent);
8532 klass->instance_size += klass->parent->instance_size;
8533 klass->class_size += klass->parent->class_size;
8534 klass->min_align = klass->parent->min_align;
8536 klass->instance_size = sizeof (MonoObject);
8537 klass->min_align = 1;
8540 /* FIXME: handle packing_size and instance_size */
8541 typebuilder_setup_fields (klass);
8543 typebuilder_setup_properties (klass);
8545 typebuilder_setup_events (klass);
8547 klass->wastypebuilder = TRUE;
8549 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8550 g_assert (res != (MonoReflectionType*)tb);
8555 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8557 MonoGenericParam *param;
8560 MONO_ARCH_SAVE_REGS;
8562 param = g_new0 (MonoGenericParam, 1);
8564 if (gparam->mbuilder) {
8565 if (!gparam->mbuilder->generic_container)
8566 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8567 param->owner = gparam->mbuilder->generic_container;
8568 } else if (gparam->tbuilder) {
8569 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8570 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8575 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8576 if (gparam->index >= count)
8579 container = nesting->generic_container;
8580 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8583 g_assert (container);
8584 param->owner = container;
8587 param->method = NULL;
8588 param->name = mono_string_to_utf8 (gparam->name);
8589 param->num = gparam->index;
8591 image = &gparam->tbuilder->module->dynamic_image->image;
8592 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8594 param->pklass->reflection_info = gparam;
8596 gparam->type.type = g_new0 (MonoType, 1);
8597 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8598 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8599 gparam->type.type->data.generic_param = param;
8603 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8605 MonoDynamicImage *assembly = sig->module->dynamic_image;
8606 guint32 na = mono_array_length (sig->arguments);
8611 MONO_ARCH_SAVE_REGS;
8613 p = buf = g_malloc (10 + na * 10);
8615 mono_metadata_encode_value (0x07, p, &p);
8616 mono_metadata_encode_value (na, p, &p);
8617 for (i = 0; i < na; ++i) {
8618 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8619 encode_reflection_type (assembly, type, p, &p);
8623 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8624 p = mono_array_addr (result, char, 0);
8625 memcpy (p, buf, buflen);
8632 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8634 MonoDynamicImage *assembly = sig->module->dynamic_image;
8635 guint32 na = mono_array_length (sig->arguments);
8640 MONO_ARCH_SAVE_REGS;
8642 p = buf = g_malloc (10 + na * 10);
8644 mono_metadata_encode_value (0x06, p, &p);
8645 for (i = 0; i < na; ++i) {
8646 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8647 encode_reflection_type (assembly, type, p, &p);
8651 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8652 p = mono_array_addr (result, char, 0);
8653 memcpy (p, buf, buflen);
8660 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8662 ReflectionMethodBuilder rmb;
8663 MonoMethodSignature *sig;
8666 sig = dynamic_method_to_signature (mb);
8668 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8671 * Resolve references.
8673 rmb.nrefs = mb->nrefs;
8674 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8675 for (i = 0; i < mb->nrefs; ++i) {
8676 gpointer ref = resolve_object (mb->module->image,
8677 mono_array_get (mb->refs, MonoObject*, i));
8680 mono_raise_exception (mono_get_exception_type_load (NULL));
8687 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8691 /* ilgen is no longer needed */
8696 * mono_reflection_lookup_dynamic_token:
8698 * Finish the Builder object pointed to by TOKEN and return the corresponding
8699 * runtime structure.
8702 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8704 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8707 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8710 return resolve_object (image, obj);
8714 resolve_object (MonoImage *image, MonoObject *obj)
8716 gpointer result = NULL;
8718 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8719 result = mono_string_intern ((MonoString*)obj);
8721 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8722 MonoReflectionType *tb = (MonoReflectionType*)obj;
8723 result = mono_class_from_mono_type (tb->type);
8725 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8726 result = ((MonoReflectionMethod*)obj)->method;
8728 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8729 result = ((MonoReflectionMethod*)obj)->method;
8731 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8732 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8733 result = mb->mhandle;
8735 /* Type is not yet created */
8736 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8738 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8741 * Hopefully this has been filled in by calling CreateType() on the
8745 * TODO: This won't work if the application finishes another
8746 * TypeBuilder instance instead of this one.
8748 result = mb->mhandle;
8750 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8751 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8753 result = cb->mhandle;
8755 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8757 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8758 result = cb->mhandle;
8760 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8761 result = ((MonoReflectionField*)obj)->field;
8763 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8764 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8765 result = fb->handle;
8768 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8770 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8771 result = fb->handle;
8773 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8774 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8777 klass = tb->type.type->data.klass;
8778 if (klass->wastypebuilder) {
8779 /* Already created */
8783 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8784 result = tb->type.type->data.klass;
8787 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8788 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8789 MonoMethodSignature *sig;
8792 if (helper->arguments)
8793 nargs = mono_array_length (helper->arguments);
8797 sig = mono_metadata_signature_alloc (image, nargs);
8798 sig->explicit_this = helper->call_conv & 64;
8799 sig->hasthis = helper->call_conv & 32;
8801 if (helper->call_conv == 0) /* unmanaged */
8802 sig->call_convention = helper->unmanaged_call_conv - 1;
8804 if (helper->call_conv & 0x02)
8805 sig->call_convention = MONO_CALL_VARARG;
8807 sig->call_convention = MONO_CALL_DEFAULT;
8809 sig->param_count = nargs;
8810 /* TODO: Copy type ? */
8811 sig->ret = helper->return_type->type;
8812 for (i = 0; i < nargs; ++i) {
8813 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8814 sig->params [i] = rt->type;
8819 g_print (obj->vtable->klass->name);
8820 g_assert_not_reached ();
8826 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
8827 const static guint32 declsec_flags_map[] = {
8828 0x00000000, /* empty */
8829 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
8830 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
8831 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
8832 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
8833 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
8834 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
8835 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
8836 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
8837 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
8838 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
8839 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
8840 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
8841 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
8842 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
8843 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
8844 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
8845 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
8846 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
8850 * Returns flags that includes all available security action associated to the handle.
8851 * @token: metadata token (either for a class or a method)
8852 * @image: image where resides the metadata.
8855 mono_declsec_get_flags (MonoImage *image, guint32 token)
8857 guint32 index = mono_metadata_declsec_from_index (image, token);
8858 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
8863 for (i = index; i < t->rows; i++) {
8864 guint32 cols [MONO_DECL_SECURITY_SIZE];
8866 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
8867 if (cols [MONO_DECL_SECURITY_PARENT] != token)
8870 action = cols [MONO_DECL_SECURITY_ACTION];
8871 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
8872 result |= declsec_flags_map [action];
8874 g_assert_not_reached ();
8881 * Get the security actions (in the form of flags) associated with the specified method.
8883 * @method: The method for which we want the declarative security flags.
8884 * Return the declarative security flags for the method (only).
8886 * Note: To keep MonoMethod size down we do not cache the declarative security flags
8887 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
8890 mono_declsec_flags_from_method (MonoMethod *method)
8892 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
8893 /* FIXME: No cache (for the moment) */
8894 guint32 idx = find_method_index (method);
8895 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8896 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
8897 return mono_declsec_get_flags (method->klass->image, idx);
8903 * Get the security actions (in the form of flags) associated with the specified class.
8905 * @klass: The class for which we want the declarative security flags.
8906 * Return the declarative security flags for the class.
8908 * Note: We cache the flags inside the MonoClass structure as this will get
8909 * called very often (at least for each method).
8912 mono_declsec_flags_from_class (MonoClass *klass)
8914 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
8915 if (!klass->declsec_flags) {
8916 guint32 idx = mono_metadata_token_index (klass->type_token);
8917 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8918 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
8919 /* we cache the flags on classes */
8920 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
8922 return klass->declsec_flags;
8928 * Get the security actions (in the form of flags) associated with the specified assembly.
8930 * @assembly: The assembly for which we want the declarative security flags.
8931 * Return the declarative security flags for the assembly.
8934 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
8936 guint32 idx = 1; /* there is only one assembly */
8937 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8938 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
8939 return mono_declsec_get_flags (assembly->image, idx);