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;
51 guint32 *table_idx; /* note: it's a pointer */
55 MonoBoolean init_locals;
56 MonoArray *return_modreq;
57 MonoArray *return_modopt;
58 MonoArray *param_modreq;
59 MonoArray *param_modopt;
60 MonoArray *permissions;
64 } ReflectionMethodBuilder;
66 const unsigned char table_sizes [64] = {
76 MONO_INTERFACEIMPL_SIZE,
77 MONO_MEMBERREF_SIZE, /* 0x0A */
79 MONO_CUSTOM_ATTR_SIZE,
80 MONO_FIELD_MARSHAL_SIZE,
81 MONO_DECL_SECURITY_SIZE,
82 MONO_CLASS_LAYOUT_SIZE,
83 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
84 MONO_STAND_ALONE_SIGNATURE_SIZE,
88 MONO_PROPERTY_MAP_SIZE,
91 MONO_METHOD_SEMA_SIZE,
93 MONO_MODULEREF_SIZE, /* 0x1A */
99 MONO_ASSEMBLY_SIZE, /* 0x20 */
100 MONO_ASSEMBLY_PROCESSOR_SIZE,
101 MONO_ASSEMBLYOS_SIZE,
102 MONO_ASSEMBLYREF_SIZE,
103 MONO_ASSEMBLYREFPROC_SIZE,
104 MONO_ASSEMBLYREFOS_SIZE,
108 MONO_NESTED_CLASS_SIZE,
110 MONO_GENERICPARAM_SIZE, /* 0x2A */
111 MONO_METHODSPEC_SIZE,
112 MONO_GENPARCONSTRAINT_SIZE,
118 * These macros can be used to allocate long living atomic data so it won't be
119 * tracked by the garbage collector. We use libgc because it's apparently faster
123 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
124 #define FREE_ATOMIC(ptr)
125 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
127 #define ALLOC_ATOMIC(size) g_malloc (size)
128 #define FREE_ATOMIC(ptr) g_free (ptr)
129 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
132 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
133 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
134 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
135 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
136 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
137 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
138 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
139 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
140 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
141 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
142 static void ensure_runtime_vtable (MonoClass *klass);
143 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
144 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
145 static guint32 type_get_signature_size (MonoType *type);
149 alloc_table (MonoDynamicTable *table, guint nrows)
152 g_assert (table->columns);
153 if (nrows + 1 >= table->alloc_rows) {
154 while (nrows + 1 >= table->alloc_rows)
155 if (table->alloc_rows == 0)
156 table->alloc_rows = 16;
158 table->alloc_rows *= 2;
161 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
163 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
168 make_room_in_stream (MonoDynamicStream *stream, int size)
170 while (stream->alloc_size <= size) {
171 if (stream->alloc_size < 4096)
172 stream->alloc_size = 4096;
174 stream->alloc_size *= 2;
177 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
179 stream->data = ALLOC_ATOMIC (stream->alloc_size);
183 string_heap_insert (MonoDynamicStream *sh, const char *str)
187 gpointer oldkey, oldval;
189 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
190 return GPOINTER_TO_UINT (oldval);
192 len = strlen (str) + 1;
194 if (idx + len > sh->alloc_size)
195 make_room_in_stream (sh, idx + len);
198 * We strdup the string even if we already copy them in sh->data
199 * so that the string pointers in the hash remain valid even if
200 * we need to realloc sh->data. We may want to avoid that later.
202 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
203 memcpy (sh->data + idx, str, len);
209 string_heap_init (MonoDynamicStream *sh)
212 sh->alloc_size = 4096;
213 sh->data = ALLOC_ATOMIC (4096);
214 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
215 string_heap_insert (sh, "");
218 #if 0 /* never used */
220 string_heap_free (MonoDynamicStream *sh)
222 FREE_ATOMIC (sh->data);
223 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
224 g_hash_table_destroy (sh->hash);
229 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
232 if (stream->alloc_size < stream->index + len)
233 make_room_in_stream (stream, stream->index + len);
234 memcpy (stream->data + stream->index, data, len);
236 stream->index += len;
238 * align index? Not without adding an additional param that controls it since
239 * we may store a blob value in pieces.
245 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
248 if (stream->alloc_size < stream->index + len)
249 make_room_in_stream (stream, stream->index + len);
250 memset (stream->data + stream->index, 0, len);
252 stream->index += len;
257 stream_data_align (MonoDynamicStream *stream)
260 guint32 count = stream->index % 4;
262 /* we assume the stream data will be aligned */
264 mono_image_add_stream_data (stream, buf, 4 - count);
268 mono_blob_entry_hash (const char* str)
272 len = mono_metadata_decode_blob_size (str, &str);
276 for (str += 1; str < end; str++)
277 h = (h << 5) - h + *str;
285 mono_blob_entry_equal (const char *str1, const char *str2) {
289 len = mono_metadata_decode_blob_size (str1, &end1);
290 len2 = mono_metadata_decode_blob_size (str2, &end2);
293 return memcmp (end1, end2, len) == 0;
297 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
301 gpointer oldkey, oldval;
303 copy = ALLOC_ATOMIC (s1+s2);
304 memcpy (copy, b1, s1);
305 memcpy (copy + s1, b2, s2);
306 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
308 idx = GPOINTER_TO_UINT (oldval);
310 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
311 mono_image_add_stream_data (&assembly->blob, b2, s2);
312 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
318 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
319 * dest may be misaligned.
322 swap_with_size (char *dest, const char* val, int len, int nelem) {
323 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
326 for (elem = 0; elem < nelem; ++elem) {
352 g_assert_not_reached ();
358 memcpy (dest, val, len * nelem);
363 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
367 guint32 idx = 0, len;
369 len = str->length * 2;
370 mono_metadata_encode_value (len, b, &b);
371 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
373 char *swapped = g_malloc (2 * mono_string_length (str));
374 const char *p = (const char*)mono_string_chars (str);
376 swap_with_size (swapped, p, 2, mono_string_length (str));
377 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
381 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
386 /* modified version needed to handle building corlib */
388 my_mono_class_from_mono_type (MonoType *type) {
389 switch (type->type) {
390 case MONO_TYPE_ARRAY:
392 case MONO_TYPE_SZARRAY:
393 case MONO_TYPE_GENERICINST:
394 return mono_class_from_mono_type (type);
397 g_assert (type->data.generic_param->pklass);
398 return type->data.generic_param->pklass;
400 /* should be always valid when we reach this case... */
401 return type->data.klass;
406 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
411 g_assert_not_reached ();
415 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
416 encode_type (assembly, ginst->generic_type, p, &p);
417 mono_metadata_encode_value (ginst->type_argc, p, &p);
418 for (i = 0; i < ginst->type_argc; ++i)
419 encode_type (assembly, ginst->type_argv [i], p, &p);
425 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
428 g_assert_not_reached ();
433 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
437 case MONO_TYPE_BOOLEAN:
451 case MONO_TYPE_STRING:
452 case MONO_TYPE_OBJECT:
453 case MONO_TYPE_TYPEDBYREF:
454 mono_metadata_encode_value (type->type, p, &p);
457 mono_metadata_encode_value (type->type, p, &p);
458 encode_type (assembly, type->data.type, p, &p);
460 case MONO_TYPE_SZARRAY:
461 mono_metadata_encode_value (type->type, p, &p);
462 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
465 case MONO_TYPE_VALUETYPE:
466 case MONO_TYPE_CLASS: {
467 MonoClass *k = mono_class_from_mono_type (type);
468 mono_metadata_encode_value (type->type, p, &p);
470 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
471 * otherwise two typerefs could point to the same type, leading to
472 * verification errors.
474 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
478 case MONO_TYPE_ARRAY:
479 mono_metadata_encode_value (type->type, p, &p);
480 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
481 mono_metadata_encode_value (type->data.array->rank, p, &p);
482 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
483 mono_metadata_encode_value (0, p, &p);
485 case MONO_TYPE_GENERICINST:
486 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
490 mono_metadata_encode_value (type->type, p, &p);
491 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
495 g_error ("need to encode type %x", type->type);
501 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
504 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
508 encode_type (assembly, type->type, p, endbuf);
512 g_assert_not_reached ();
517 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
522 for (i = 0; i < mono_array_length (modreq); ++i) {
523 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
524 *p = MONO_TYPE_CMOD_REQD;
526 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
530 for (i = 0; i < mono_array_length (modopt); ++i) {
531 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
532 *p = MONO_TYPE_CMOD_OPT;
534 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
541 generic_inst_get_signature_size (MonoGenericInst *ginst)
547 g_assert_not_reached ();
550 size += 1 + type_get_signature_size (ginst->generic_type);
552 for (i = 0; i < ginst->type_argc; ++i)
553 size += type_get_signature_size (ginst->type_argv [i]);
559 type_get_signature_size (MonoType *type)
564 g_assert_not_reached ();
572 case MONO_TYPE_BOOLEAN:
586 case MONO_TYPE_STRING:
587 case MONO_TYPE_OBJECT:
588 case MONO_TYPE_TYPEDBYREF:
591 return size + 1 + type_get_signature_size (type->data.type);
592 case MONO_TYPE_SZARRAY:
593 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
595 case MONO_TYPE_VALUETYPE:
596 case MONO_TYPE_CLASS:
599 case MONO_TYPE_ARRAY:
600 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
601 case MONO_TYPE_GENERICINST:
602 return size + generic_inst_get_signature_size (type->data.generic_inst);
608 g_error ("need to encode type %x", type->type);
614 method_get_signature_size (MonoMethodSignature *sig)
619 size = type_get_signature_size (sig->ret);
620 for (i = 0; i < sig->param_count; i++)
621 size += type_get_signature_size (sig->params [i]);
623 if (sig->generic_param_count)
625 if (sig->sentinelpos >= 0)
632 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
637 guint32 nparams = sig->param_count;
638 guint32 size = 11 + method_get_signature_size (sig);
646 p = buf = g_malloc (size);
648 * FIXME: vararg, explicit_this, differenc call_conv values...
650 *p = sig->call_convention;
652 *p |= 0x20; /* hasthis */
653 if (sig->generic_param_count)
654 *p |= 0x10; /* generic */
656 if (sig->generic_param_count)
657 mono_metadata_encode_value (sig->generic_param_count, p, &p);
658 mono_metadata_encode_value (nparams, p, &p);
659 encode_type (assembly, sig->ret, p, &p);
660 for (i = 0; i < nparams; ++i) {
661 if (i == sig->sentinelpos)
662 *p++ = MONO_TYPE_SENTINEL;
663 encode_type (assembly, sig->params [i], p, &p);
666 g_assert (p - buf < size);
667 mono_metadata_encode_value (p-buf, b, &b);
668 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
674 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
677 * FIXME: reuse code from method_encode_signature().
682 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
683 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
684 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
685 guint32 size = 21 + nparams * 20 + notypes * 20;
690 p = buf = g_malloc (size);
691 /* LAMESPEC: all the call conv spec is foobared */
692 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
693 if (mb->call_conv & 2)
694 *p |= 0x5; /* vararg */
695 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
696 *p |= 0x20; /* hasthis */
698 *p |= 0x10; /* generic */
701 mono_metadata_encode_value (ngparams, p, &p);
702 mono_metadata_encode_value (nparams + notypes, p, &p);
703 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
704 encode_reflection_type (assembly, mb->rtype, p, &p);
705 for (i = 0; i < nparams; ++i) {
706 MonoArray *modreq = NULL;
707 MonoArray *modopt = NULL;
708 MonoReflectionType *pt;
710 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
711 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
712 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
713 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
714 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
715 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
716 encode_reflection_type (assembly, pt, p, &p);
719 *p++ = MONO_TYPE_SENTINEL;
720 for (i = 0; i < notypes; ++i) {
721 MonoReflectionType *pt;
723 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
724 encode_reflection_type (assembly, pt, p, &p);
728 g_assert (p - buf < size);
729 mono_metadata_encode_value (p-buf, b, &b);
730 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
736 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
738 MonoDynamicTable *table;
741 guint32 idx, sig_idx, size;
742 guint nl = mono_array_length (ilgen->locals);
749 p = buf = g_malloc (size);
750 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
751 idx = table->next_idx ++;
753 alloc_table (table, table->rows);
754 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
756 mono_metadata_encode_value (0x07, p, &p);
757 mono_metadata_encode_value (nl, p, &p);
758 for (i = 0; i < nl; ++i) {
759 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
762 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
764 encode_reflection_type (assembly, lb->type, p, &p);
766 g_assert (p - buf < size);
767 mono_metadata_encode_value (p-buf, b, &b);
768 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
771 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
777 method_count_clauses (MonoReflectionILGen *ilgen)
779 guint32 num_clauses = 0;
782 MonoILExceptionInfo *ex_info;
783 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
784 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
785 if (ex_info->handlers)
786 num_clauses += mono_array_length (ex_info->handlers);
794 static MonoExceptionClause*
795 method_encode_clauses (MonoDynamicImage *assembly,
796 MonoReflectionILGen *ilgen, guint32 num_clauses)
798 MonoExceptionClause *clauses;
799 MonoExceptionClause *clause;
800 MonoILExceptionInfo *ex_info;
801 MonoILExceptionBlock *ex_block;
802 guint32 finally_start;
803 int i, j, clause_index;;
805 clauses = g_new0 (MonoExceptionClause, num_clauses);
808 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
809 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
810 finally_start = ex_info->start + ex_info->len;
811 g_assert (ex_info->handlers);
812 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
813 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
814 clause = &(clauses [clause_index]);
816 clause->flags = ex_block->type;
817 clause->try_offset = ex_info->start;
819 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
820 clause->try_len = finally_start - ex_info->start;
822 clause->try_len = ex_info->len;
823 clause->handler_offset = ex_block->start;
824 clause->handler_len = ex_block->len;
825 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
826 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
827 if (ex_block->extype) {
828 mono_g_hash_table_insert (assembly->tokens,
829 GUINT_TO_POINTER (clause->token_or_filter),
832 finally_start = ex_block->start + ex_block->len;
842 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
848 gint32 num_locals = 0;
849 gint32 num_exception = 0;
852 char fat_header [12];
855 guint32 local_sig = 0;
856 guint32 header_size = 12;
859 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
860 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
861 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
862 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
866 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
868 code = mb->ilgen->code;
869 code_size = mb->ilgen->code_len;
870 max_stack = mb->ilgen->max_stack;
871 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
872 if (mb->ilgen->ex_handlers)
873 num_exception = method_count_clauses (mb->ilgen);
877 char *name = mono_string_to_utf8 (mb->name);
878 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
879 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
882 mono_raise_exception (exception);
885 code_size = mono_array_length (code);
886 max_stack = 8; /* we probably need to run a verifier on the code... */
889 /* check for exceptions, maxstack, locals */
890 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
892 if (code_size < 64 && !(code_size & 1)) {
893 flags = (code_size << 2) | 0x2;
894 } else if (code_size < 32 && (code_size & 1)) {
895 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
899 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
900 /* add to the fixup todo list */
901 if (mb->ilgen && mb->ilgen->num_token_fixups)
902 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
903 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
904 return assembly->text_rva + idx;
908 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
910 * FIXME: need to set also the header size in fat_flags.
911 * (and more sects and init locals flags)
915 fat_flags |= METHOD_HEADER_MORE_SECTS;
917 fat_flags |= METHOD_HEADER_INIT_LOCALS;
918 fat_header [0] = fat_flags;
919 fat_header [1] = (header_size / 4 ) << 4;
920 shortp = (guint16*)(fat_header + 2);
921 *shortp = GUINT16_TO_LE (max_stack);
922 intp = (guint32*)(fat_header + 4);
923 *intp = GUINT32_TO_LE (code_size);
924 intp = (guint32*)(fat_header + 8);
925 *intp = GUINT32_TO_LE (local_sig);
926 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
927 /* add to the fixup todo list */
928 if (mb->ilgen && mb->ilgen->num_token_fixups)
929 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
931 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
933 unsigned char sheader [4];
934 MonoExceptionClause clause;
935 MonoILExceptionInfo * ex_info;
936 MonoILExceptionBlock * ex_block;
939 stream_data_align (&assembly->code);
940 /* always use fat format for now */
941 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
942 num_exception *= sizeof (MonoExceptionClause);
943 num_exception += 4; /* include the size of the header */
944 sheader [1] = num_exception & 0xff;
945 sheader [2] = (num_exception >> 8) & 0xff;
946 sheader [3] = (num_exception >> 16) & 0xff;
947 mono_image_add_stream_data (&assembly->code, sheader, 4);
948 /* fat header, so we are already aligned */
950 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
951 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
952 if (ex_info->handlers) {
953 int finally_start = ex_info->start + ex_info->len;
954 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
955 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
956 clause.flags = GUINT32_TO_LE (ex_block->type);
957 clause.try_offset = GUINT32_TO_LE (ex_info->start);
958 /* need fault, too, probably */
959 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
960 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
962 clause.try_len = GUINT32_TO_LE (ex_info->len);
963 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
964 clause.handler_len = GUINT32_TO_LE (ex_block->len);
965 finally_start = ex_block->start + ex_block->len;
966 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
967 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
968 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
969 /*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",
970 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);*/
971 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
974 g_error ("No clauses for ex info block %d", i);
978 return assembly->text_rva + idx;
982 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
985 MonoDynamicTable *table;
988 table = &assembly->tables [table_idx];
990 g_assert (col < table->columns);
992 values = table->values + table->columns;
993 for (i = 1; i <= table->rows; ++i) {
994 if (values [col] == token)
996 values += table->columns;
1001 static GHashTable *dynamic_custom_attrs = NULL;
1003 static MonoCustomAttrInfo*
1004 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1007 MonoCustomAttrInfo *ainfo;
1008 MonoReflectionCustomAttr *cattr;
1012 /* FIXME: check in assembly the Run flag is set */
1014 count = mono_array_length (cattrs);
1016 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1018 ainfo->image = image;
1019 ainfo->num_attrs = count;
1020 for (i = 0; i < count; ++i) {
1021 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1022 ainfo->attrs [i].ctor = cattr->ctor->method;
1023 /* FIXME: might want to memdup the data here */
1024 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1025 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1032 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1034 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1039 if (!dynamic_custom_attrs)
1040 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1042 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1043 ainfo->cached = TRUE;
1047 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1049 /* they are cached, so we don't free them */
1050 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1056 * idx is the table index of the object
1057 * type is one of MONO_CUSTOM_ATTR_*
1060 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1062 MonoDynamicTable *table;
1063 MonoReflectionCustomAttr *cattr;
1065 guint32 count, i, token;
1067 char *p = blob_size;
1069 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1072 count = mono_array_length (cattrs);
1073 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1074 table->rows += count;
1075 alloc_table (table, table->rows);
1076 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1077 idx <<= MONO_CUSTOM_ATTR_BITS;
1079 for (i = 0; i < count; ++i) {
1080 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1081 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1082 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
1083 type = mono_metadata_token_index (token);
1084 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1085 switch (mono_metadata_token_table (token)) {
1086 case MONO_TABLE_METHOD:
1087 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1089 case MONO_TABLE_MEMBERREF:
1090 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1093 g_warning ("got wrong token in custom attr");
1096 values [MONO_CUSTOM_ATTR_TYPE] = type;
1098 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1099 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1100 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1101 values += MONO_CUSTOM_ATTR_SIZE;
1107 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
1108 MonoArray *permissions)
1110 MonoDynamicTable *table;
1112 guint32 count, i, idx;
1113 MonoReflectionPermissionSet *perm;
1118 count = mono_array_length (permissions);
1119 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1120 table->rows += count;
1121 alloc_table (table, table->rows);
1123 for (i = 0; i < mono_array_length (permissions); ++i) {
1124 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1126 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1128 idx = mono_metadata_token_index (parent_token);
1129 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1130 switch (mono_metadata_token_table (parent_token)) {
1131 case MONO_TABLE_TYPEDEF:
1132 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1134 case MONO_TABLE_METHOD:
1135 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1137 case MONO_TABLE_ASSEMBLY:
1138 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1141 g_assert_not_reached ();
1144 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1145 values [MONO_DECL_SECURITY_PARENT] = idx;
1146 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1153 * Fill in the MethodDef and ParamDef tables for a method.
1154 * This is used for both normal methods and constructors.
1157 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1159 MonoDynamicTable *table;
1164 /* room in this table is already allocated */
1165 table = &assembly->tables [MONO_TABLE_METHOD];
1166 *mb->table_idx = table->next_idx ++;
1167 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1168 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1169 name = mono_string_to_utf8 (mb->name);
1170 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1172 values [MONO_METHOD_FLAGS] = mb->attrs;
1173 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1174 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1175 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1177 table = &assembly->tables [MONO_TABLE_PARAM];
1178 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1180 mono_image_add_decl_security (assembly,
1181 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1185 MonoDynamicTable *mtable;
1188 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1189 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1192 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1193 if (mono_array_get (mb->pinfo, gpointer, i))
1196 table->rows += count;
1197 alloc_table (table, table->rows);
1198 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1199 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1200 MonoReflectionParamBuilder *pb;
1201 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1202 values [MONO_PARAM_FLAGS] = pb->attrs;
1203 values [MONO_PARAM_SEQUENCE] = i;
1204 if (pb->name != NULL) {
1205 name = mono_string_to_utf8 (pb->name);
1206 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1210 values [MONO_PARAM_NAME] = 0;
1211 values += MONO_PARAM_SIZE;
1212 if (pb->marshal_info) {
1214 alloc_table (mtable, mtable->rows);
1215 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1216 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1217 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1219 pb->table_idx = table->next_idx++;
1226 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1227 MonoReflectionMethodBuilder *mb)
1229 rmb->ilgen = mb->ilgen;
1230 rmb->rtype = mb->rtype;
1231 rmb->parameters = mb->parameters;
1232 rmb->generic_params = mb->generic_params;
1233 rmb->opt_types = NULL;
1234 rmb->pinfo = mb->pinfo;
1235 rmb->attrs = mb->attrs;
1236 rmb->iattrs = mb->iattrs;
1237 rmb->call_conv = mb->call_conv;
1238 rmb->code = mb->code;
1239 rmb->type = mb->type;
1240 rmb->name = mb->name;
1241 rmb->table_idx = &mb->table_idx;
1242 rmb->init_locals = mb->init_locals;
1243 rmb->return_modreq = mb->return_modreq;
1244 rmb->return_modopt = mb->return_modopt;
1245 rmb->param_modreq = mb->param_modreq;
1246 rmb->param_modopt = mb->param_modopt;
1247 rmb->permissions = mb->permissions;
1248 rmb->mhandle = mb->mhandle;
1254 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1255 MonoReflectionCtorBuilder *mb)
1257 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1259 rmb->ilgen = mb->ilgen;
1260 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1261 rmb->parameters = mb->parameters;
1262 rmb->generic_params = NULL;
1263 rmb->opt_types = NULL;
1264 rmb->pinfo = mb->pinfo;
1265 rmb->attrs = mb->attrs;
1266 rmb->iattrs = mb->iattrs;
1267 rmb->call_conv = mb->call_conv;
1269 rmb->type = mb->type;
1270 rmb->name = mono_string_new (mono_domain_get (), name);
1271 rmb->table_idx = &mb->table_idx;
1272 rmb->init_locals = mb->init_locals;
1273 rmb->return_modreq = NULL;
1274 rmb->return_modopt = NULL;
1275 rmb->param_modreq = mb->param_modreq;
1276 rmb->param_modopt = mb->param_modopt;
1277 rmb->permissions = mb->permissions;
1278 rmb->mhandle = mb->mhandle;
1284 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1285 MonoReflectionDynamicMethod *mb)
1287 rmb->ilgen = mb->ilgen;
1288 rmb->rtype = mb->rtype;
1289 rmb->parameters = mb->parameters;
1290 rmb->generic_params = NULL;
1291 rmb->opt_types = NULL;
1293 rmb->attrs = mb->attrs;
1295 rmb->call_conv = mb->call_conv;
1298 rmb->name = mb->name;
1299 rmb->table_idx = NULL;
1300 rmb->init_locals = mb->init_locals;
1301 rmb->return_modreq = NULL;
1302 rmb->return_modopt = NULL;
1303 rmb->param_modreq = NULL;
1304 rmb->param_modopt = NULL;
1305 rmb->permissions = NULL;
1306 rmb->mhandle = mb->mhandle;
1312 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1314 MonoDynamicTable *table;
1317 ReflectionMethodBuilder rmb;
1320 reflection_methodbuilder_from_method_builder (&rmb, mb);
1322 mono_image_basic_method (&rmb, assembly);
1324 if (mb->dll) { /* It's a P/Invoke method */
1326 int charset = mb->charset & 0xf;
1327 int lasterr = mb->charset & 0x40;
1328 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1330 alloc_table (table, table->rows);
1331 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1332 /* map CharSet values to on-disk values */
1334 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1335 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1336 name = mono_string_to_utf8 (mb->dllentry);
1337 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1339 name = mono_string_to_utf8 (mb->dll);
1340 moduleref = string_heap_insert (&assembly->sheap, name);
1342 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1343 table = &assembly->tables [MONO_TABLE_MODULEREF];
1345 alloc_table (table, table->rows);
1346 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1347 values [MONO_IMPLMAP_SCOPE] = table->rows;
1351 if (mb->override_method) {
1352 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1354 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1356 alloc_table (table, table->rows);
1357 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1358 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1359 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1360 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
1361 switch (mono_metadata_token_table (tok)) {
1362 case MONO_TABLE_MEMBERREF:
1363 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1365 case MONO_TABLE_METHOD:
1366 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1369 g_assert_not_reached ();
1371 values [MONO_METHODIMPL_DECLARATION] = tok;
1374 if (mb->generic_params) {
1375 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1376 table->rows += mono_array_length (mb->generic_params);
1377 alloc_table (table, table->rows);
1378 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1379 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1381 mono_image_get_generic_param_info (
1382 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1389 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1391 ReflectionMethodBuilder rmb;
1393 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1395 mono_image_basic_method (&rmb, assembly);
1399 type_get_fully_qualified_name (MonoType *type) {
1400 char *name, *result;
1404 name = mono_type_get_name (type);
1405 klass = my_mono_class_from_mono_type (type);
1406 ta = klass->image->assembly;
1408 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1409 name, ta->aname.name,
1410 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1411 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1412 ta->aname.public_key_token [0] ? ta->aname.public_key_token : "null");
1418 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1422 klass = my_mono_class_from_mono_type (type);
1423 ta = klass->image->assembly;
1424 if (ta == ass || klass->image == mono_defaults.corlib)
1425 return mono_type_get_name (type);
1427 return type_get_fully_qualified_name (type);
1431 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1433 char blob_size [64];
1434 char *b = blob_size;
1439 if (!assembly->save)
1442 p = buf = g_malloc (64);
1444 mono_metadata_encode_value (0x06, p, &p);
1445 /* encode custom attributes before the type */
1446 encode_type (assembly, type, p, &p);
1447 g_assert (p-buf < 64);
1448 mono_metadata_encode_value (p-buf, b, &b);
1449 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1455 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1457 char blob_size [64];
1458 char *b = blob_size;
1463 p = buf = g_malloc (64);
1465 mono_metadata_encode_value (0x06, p, &p);
1466 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1467 /* encode custom attributes before the type */
1468 encode_reflection_type (assembly, fb->type, p, &p);
1469 g_assert (p-buf < 64);
1470 mono_metadata_encode_value (p-buf, b, &b);
1471 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1477 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1478 char blob_size [64];
1479 char *b = blob_size;
1482 guint32 idx = 0, len = 0, dummy = 0;
1484 p = buf = g_malloc (64);
1486 *ret_type = MONO_TYPE_CLASS;
1488 box_val = (char*)&dummy;
1490 box_val = ((char*)val) + sizeof (MonoObject);
1491 *ret_type = val->vtable->klass->byval_arg.type;
1494 switch (*ret_type) {
1495 case MONO_TYPE_BOOLEAN:
1500 case MONO_TYPE_CHAR:
1515 case MONO_TYPE_VALUETYPE:
1516 if (val->vtable->klass->enumtype) {
1517 *ret_type = val->vtable->klass->enum_basetype->type;
1520 g_error ("we can't encode valuetypes");
1521 case MONO_TYPE_CLASS:
1523 case MONO_TYPE_STRING: {
1524 MonoString *str = (MonoString*)val;
1525 /* there is no signature */
1526 len = str->length * 2;
1527 mono_metadata_encode_value (len, b, &b);
1528 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1530 char *swapped = g_malloc (2 * mono_string_length (str));
1531 const char *p = (const char*)mono_string_chars (str);
1533 swap_with_size (swapped, p, 2, mono_string_length (str));
1534 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1538 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1545 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1548 /* there is no signature */
1549 mono_metadata_encode_value (len, b, &b);
1550 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1551 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1552 swap_with_size (blob_size, box_val, len, 1);
1553 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1555 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1563 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1564 char blob_size [64];
1565 char *b = blob_size;
1566 char *p, *buf, *str;
1567 guint32 idx, len, bufsize = 256;
1569 p = buf = g_malloc (bufsize);
1571 switch (minfo->type) {
1572 case MONO_NATIVE_BYVALTSTR:
1573 case MONO_NATIVE_BYVALARRAY:
1574 mono_metadata_encode_value (minfo->type, p, &p);
1575 mono_metadata_encode_value (minfo->count, p, &p);
1577 case MONO_NATIVE_LPARRAY:
1578 mono_metadata_encode_value (minfo->type, p, &p);
1579 if (minfo->eltype || (minfo->count > 0)) {
1580 mono_metadata_encode_value (minfo->eltype, p, &p);
1581 if (minfo->count > 0) {
1582 mono_metadata_encode_value (0, p, &p);
1583 mono_metadata_encode_value (minfo->count, p, &p);
1587 case MONO_NATIVE_CUSTOM:
1588 mono_metadata_encode_value (minfo->type, p, &p);
1590 str = mono_string_to_utf8 (minfo->guid);
1592 mono_metadata_encode_value (len, p, &p);
1593 memcpy (p, str, len);
1597 mono_metadata_encode_value (0, p, &p);
1599 if (minfo->marshaltype) {
1600 str = mono_string_to_utf8 (minfo->marshaltype);
1602 mono_metadata_encode_value (len, p, &p);
1603 if (p + len >= buf + bufsize) {
1606 buf = g_realloc (buf, bufsize);
1609 memcpy (p, str, len);
1613 mono_metadata_encode_value (0, p, &p);
1615 if (minfo->marshaltyperef) {
1616 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1618 mono_metadata_encode_value (len, p, &p);
1619 if (p + len >= buf + bufsize) {
1622 buf = g_realloc (buf, bufsize);
1625 memcpy (p, str, len);
1629 mono_metadata_encode_value (0, p, &p);
1631 if (minfo->mcookie) {
1632 str = mono_string_to_utf8 (minfo->mcookie);
1634 mono_metadata_encode_value (len, p, &p);
1635 if (p + len >= buf + bufsize) {
1638 buf = g_realloc (buf, bufsize);
1641 memcpy (p, str, len);
1645 mono_metadata_encode_value (0, p, &p);
1649 mono_metadata_encode_value (minfo->type, p, &p);
1653 mono_metadata_encode_value (len, b, &b);
1654 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1660 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1662 MonoDynamicTable *table;
1666 /* maybe this fixup should be done in the C# code */
1667 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1668 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1669 table = &assembly->tables [MONO_TABLE_FIELD];
1670 fb->table_idx = table->next_idx ++;
1671 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1672 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1673 name = mono_string_to_utf8 (fb->name);
1674 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1676 values [MONO_FIELD_FLAGS] = fb->attrs;
1677 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1679 if (fb->offset != -1) {
1680 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1682 alloc_table (table, table->rows);
1683 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1684 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1685 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1687 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1688 guint32 field_type = 0;
1689 table = &assembly->tables [MONO_TABLE_CONSTANT];
1691 alloc_table (table, table->rows);
1692 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1693 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1694 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1695 values [MONO_CONSTANT_TYPE] = field_type;
1696 values [MONO_CONSTANT_PADDING] = 0;
1698 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1700 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1702 alloc_table (table, table->rows);
1703 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1704 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1706 * We store it in the code section because it's simpler for now.
1709 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1711 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1712 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1714 if (fb->marshal_info) {
1715 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1717 alloc_table (table, table->rows);
1718 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1719 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1720 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1725 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1729 char *b = blob_size;
1730 guint32 nparams = 0;
1731 MonoReflectionMethodBuilder *mb = fb->get_method;
1732 MonoReflectionMethodBuilder *smb = fb->set_method;
1733 guint32 idx, i, size;
1735 if (mb && mb->parameters)
1736 nparams = mono_array_length (mb->parameters);
1737 if (!mb && smb && smb->parameters)
1738 nparams = mono_array_length (smb->parameters) - 1;
1739 size = 24 + nparams * 10;
1740 buf = p = g_malloc (size);
1743 mono_metadata_encode_value (nparams, p, &p);
1745 encode_reflection_type (assembly, mb->rtype, p, &p);
1746 for (i = 0; i < nparams; ++i) {
1747 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1748 encode_reflection_type (assembly, pt, p, &p);
1751 /* the property type is the last param */
1752 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1753 for (i = 0; i < nparams; ++i) {
1754 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1755 encode_reflection_type (assembly, pt, p, &p);
1759 g_assert (p - buf < size);
1760 mono_metadata_encode_value (p-buf, b, &b);
1761 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1767 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1769 MonoDynamicTable *table;
1772 guint num_methods = 0;
1776 * we need to set things in the following tables:
1777 * PROPERTYMAP (info already filled in _get_type_info ())
1778 * PROPERTY (rows already preallocated in _get_type_info ())
1779 * METHOD (method info already done with the generic method code)
1782 table = &assembly->tables [MONO_TABLE_PROPERTY];
1783 pb->table_idx = table->next_idx ++;
1784 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1785 name = mono_string_to_utf8 (pb->name);
1786 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1788 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1789 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1791 /* FIXME: we still don't handle 'other' methods */
1792 if (pb->get_method) num_methods ++;
1793 if (pb->set_method) num_methods ++;
1795 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1796 table->rows += num_methods;
1797 alloc_table (table, table->rows);
1799 if (pb->get_method) {
1800 semaidx = table->next_idx ++;
1801 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1802 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1803 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1804 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1806 if (pb->set_method) {
1807 semaidx = table->next_idx ++;
1808 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1809 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1810 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1811 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1816 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1818 MonoDynamicTable *table;
1821 guint num_methods = 0;
1825 * we need to set things in the following tables:
1826 * EVENTMAP (info already filled in _get_type_info ())
1827 * EVENT (rows already preallocated in _get_type_info ())
1828 * METHOD (method info already done with the generic method code)
1831 table = &assembly->tables [MONO_TABLE_EVENT];
1832 eb->table_idx = table->next_idx ++;
1833 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1834 name = mono_string_to_utf8 (eb->name);
1835 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1837 values [MONO_EVENT_FLAGS] = eb->attrs;
1838 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1841 * FIXME: we still don't handle 'other' methods
1843 if (eb->add_method) num_methods ++;
1844 if (eb->remove_method) num_methods ++;
1845 if (eb->raise_method) num_methods ++;
1847 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1848 table->rows += num_methods;
1849 alloc_table (table, table->rows);
1851 if (eb->add_method) {
1852 semaidx = table->next_idx ++;
1853 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1854 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1855 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1856 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1858 if (eb->remove_method) {
1859 semaidx = table->next_idx ++;
1860 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1861 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1862 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1863 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1865 if (eb->raise_method) {
1866 semaidx = table->next_idx ++;
1867 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1868 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1869 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1870 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1875 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1877 static MonoClass *NewConstraintAttr;
1878 static MonoMethod *NewConstraintAttr_ctor;
1879 MonoDynamicTable *table;
1881 guint32 token, type;
1882 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1885 if (!NewConstraintAttr)
1886 NewConstraintAttr = mono_class_from_name (
1887 mono_defaults.corlib, "System.Runtime.CompilerServices",
1888 "NewConstraintAttribute");
1889 g_assert (NewConstraintAttr);
1891 if (!NewConstraintAttr_ctor) {
1894 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1895 MonoMethod *m = NewConstraintAttr->methods [i];
1897 if (strcmp (m->name, ".ctor"))
1900 NewConstraintAttr_ctor = m;
1904 g_assert (NewConstraintAttr_ctor);
1907 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1909 alloc_table (table, table->rows);
1911 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1912 owner <<= MONO_CUSTOM_ATTR_BITS;
1913 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1914 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1916 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1918 type = mono_metadata_token_index (token);
1919 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1920 switch (mono_metadata_token_table (token)) {
1921 case MONO_TABLE_METHOD:
1922 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1924 case MONO_TABLE_MEMBERREF:
1925 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1928 g_warning ("got wrong token in custom attr");
1931 values [MONO_CUSTOM_ATTR_TYPE] = type;
1933 buf = p = g_malloc (1);
1934 mono_metadata_encode_value (4, p, &p);
1935 g_assert (p-buf == 1);
1937 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1939 values += MONO_CUSTOM_ATTR_SIZE;
1944 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1946 MonoDynamicTable *table;
1947 guint32 num_constraints, i;
1951 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1952 num_constraints = gparam->iface_constraints ?
1953 mono_array_length (gparam->iface_constraints) : 0;
1954 table->rows += num_constraints;
1955 if (gparam->base_type)
1957 alloc_table (table, table->rows);
1959 if (gparam->base_type) {
1960 table_idx = table->next_idx ++;
1961 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1963 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1964 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1965 assembly, gparam->base_type->type);
1968 for (i = 0; i < num_constraints; i++) {
1969 MonoReflectionType *constraint = mono_array_get (
1970 gparam->iface_constraints, gpointer, i);
1972 table_idx = table->next_idx ++;
1973 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1975 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1976 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1977 assembly, constraint->type);
1980 if (gparam->has_ctor_constraint)
1981 encode_new_constraint (assembly, owner);
1985 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1987 MonoDynamicTable *table;
1988 MonoGenericParam *param;
1992 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1993 table_idx = table->next_idx ++;
1994 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
1996 param = gparam->type.type->data.generic_param;
1998 values [MONO_GENERICPARAM_OWNER] = owner;
1999 if (gparam->has_value_type)
2000 values [MONO_GENERICPARAM_FLAGS] = 0x18;
2001 else if (gparam->has_reference_type)
2002 values [MONO_GENERICPARAM_FLAGS] = 0x04;
2004 values [MONO_GENERICPARAM_FLAGS] = 0x00;
2005 values [MONO_GENERICPARAM_NUMBER] = param->num;
2006 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2007 values [MONO_GENERICPARAM_KIND] = 0;
2009 encode_constraints (gparam, table_idx, assembly);
2013 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2015 MonoDynamicTable *table;
2018 guint32 cols [MONO_ASSEMBLY_SIZE];
2022 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2025 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2026 table = &assembly->tables [MONO_TABLE_MODULEREF];
2027 token = table->next_idx ++;
2029 alloc_table (table, table->rows);
2030 values = table->values + token * MONO_MODULEREF_SIZE;
2031 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2033 token <<= MONO_RESOLTION_SCOPE_BITS;
2034 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2035 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2040 if (image->assembly->dynamic)
2042 memset (cols, 0, sizeof (cols));
2044 /* image->assembly->image is the manifest module */
2045 image = image->assembly->image;
2046 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2049 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2050 token = table->next_idx ++;
2052 alloc_table (table, table->rows);
2053 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2054 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2055 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2056 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2057 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2058 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2059 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2060 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2061 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2063 if (strcmp ("", image->assembly->aname.culture)) {
2064 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2065 image->assembly->aname.culture);
2068 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2069 guchar pubtoken [9];
2071 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2072 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2074 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2076 token <<= MONO_RESOLTION_SCOPE_BITS;
2077 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2078 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2083 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2085 MonoDynamicTable *table;
2091 char *b = blob_size;
2093 switch (type->type) {
2094 case MONO_TYPE_FNPTR:
2096 case MONO_TYPE_SZARRAY:
2097 case MONO_TYPE_ARRAY:
2099 case MONO_TYPE_MVAR:
2100 case MONO_TYPE_GENERICINST:
2101 encode_type (assembly, type, p, &p);
2103 case MONO_TYPE_CLASS:
2104 case MONO_TYPE_VALUETYPE: {
2105 MonoClass *k = mono_class_from_mono_type (type);
2106 if (!k || !k->generic_inst)
2108 encode_generic_inst (assembly, k->generic_inst, p, &p);
2115 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2116 if (assembly->save) {
2117 g_assert (p-sig < 128);
2118 mono_metadata_encode_value (p-sig, b, &b);
2119 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2120 alloc_table (table, table->rows + 1);
2121 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2122 values [MONO_TYPESPEC_SIGNATURE] = token;
2125 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2126 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2132 * Despite the name, we handle also TypeSpec (with the above helper).
2135 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2137 MonoDynamicTable *table;
2139 guint32 token, scope, enclosing;
2142 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2145 token = create_typespec (assembly, type);
2148 klass = my_mono_class_from_mono_type (type);
2150 klass = mono_class_from_mono_type (type);
2153 * If it's in the same module and not a generic type parameter:
2155 if ((klass->image == &assembly->image) &&
2156 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2157 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2158 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2159 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2163 if (klass->nested_in) {
2164 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2165 /* get the typeref idx of the enclosing type */
2166 enclosing >>= MONO_TYPEDEFORREF_BITS;
2167 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2169 scope = resolution_scope_from_image (assembly, klass->image);
2171 table = &assembly->tables [MONO_TABLE_TYPEREF];
2172 if (assembly->save) {
2173 alloc_table (table, table->rows + 1);
2174 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2175 values [MONO_TYPEREF_SCOPE] = scope;
2176 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2177 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2179 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2180 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2182 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2187 * Insert a memberef row into the metadata: the token that point to the memberref
2188 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2189 * mono_image_get_fieldref_token()).
2190 * The sig param is an index to an already built signature.
2193 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2195 MonoDynamicTable *table;
2197 guint32 token, pclass;
2200 parent = mono_image_typedef_or_ref (assembly, type);
2201 switch (parent & MONO_TYPEDEFORREF_MASK) {
2202 case MONO_TYPEDEFORREF_TYPEREF:
2203 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2205 case MONO_TYPEDEFORREF_TYPESPEC:
2206 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2208 case MONO_TYPEDEFORREF_TYPEDEF:
2209 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2212 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2215 /* extract the index */
2216 parent >>= MONO_TYPEDEFORREF_BITS;
2218 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2220 if (assembly->save) {
2221 alloc_table (table, table->rows + 1);
2222 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2223 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2224 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2225 values [MONO_MEMBERREF_SIGNATURE] = sig;
2228 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2235 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2239 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2242 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2243 method->name, method_encode_signature (assembly, method->signature));
2244 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2249 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2250 const gchar *name, guint32 sig)
2252 MonoDynamicTable *table;
2253 guint32 parent, token;
2256 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2258 if (assembly->save) {
2259 alloc_table (table, table->rows + 1);
2260 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2261 values [MONO_MEMBERREF_CLASS] = original;
2262 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2263 values [MONO_MEMBERREF_SIGNATURE] = sig;
2266 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2273 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2276 ReflectionMethodBuilder rmb;
2278 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2282 reflection_methodbuilder_from_method_builder (&rmb, mb);
2284 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2285 mono_string_to_utf8 (rmb.name),
2286 method_builder_encode_signature (assembly, &rmb));
2287 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2292 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2295 ReflectionMethodBuilder rmb;
2297 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2301 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2303 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2304 mono_string_to_utf8 (rmb.name),
2305 method_builder_encode_signature (assembly, &rmb));
2306 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2311 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2316 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2319 g_assert (f->field->parent);
2320 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2321 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2322 f->field->name, fieldref_encode_signature (assembly, type));
2323 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2328 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2333 guint32 nparams = gmethod->mtype_argc;
2334 guint32 size = 10 + nparams * 10;
2337 char *b = blob_size;
2339 if (!assembly->save)
2342 p = buf = g_malloc (size);
2344 * FIXME: vararg, explicit_this, differenc call_conv values...
2346 mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2347 mono_metadata_encode_value (nparams, p, &p);
2349 for (i = 0; i < nparams; i++)
2350 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2353 g_assert (p - buf < size);
2354 mono_metadata_encode_value (p-buf, b, &b);
2355 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2361 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2363 MonoDynamicTable *table;
2365 guint32 token, mtoken = 0, sig;
2366 MonoMethodInflated *imethod;
2367 MonoMethod *declaring;
2369 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2371 g_assert (method->signature->is_inflated);
2372 imethod = (MonoMethodInflated *) method;
2373 declaring = imethod->declaring;
2375 sig = method_encode_signature (assembly, declaring->signature);
2376 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2377 declaring->name, sig);
2379 if (!declaring->signature->generic_param_count)
2382 switch (mono_metadata_token_table (mtoken)) {
2383 case MONO_TABLE_MEMBERREF:
2384 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2386 case MONO_TABLE_METHOD:
2387 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2390 g_assert_not_reached ();
2393 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2395 if (assembly->save) {
2396 alloc_table (table, table->rows + 1);
2397 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2398 values [MONO_METHODSPEC_METHOD] = mtoken;
2399 values [MONO_METHODSPEC_SIGNATURE] = sig;
2402 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2409 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2411 MonoMethodInflated *imethod;
2414 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2418 g_assert (m->signature->is_inflated);
2419 imethod = (MonoMethodInflated *) m;
2421 if (imethod->declaring->signature->generic_param_count)
2422 token = method_encode_methodspec (assembly, m);
2424 guint32 sig = method_encode_signature (
2425 assembly, imethod->declaring->signature);
2426 token = mono_image_get_memberref_token (
2427 assembly, &m->klass->byval_arg, m->name, sig);
2430 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2435 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2437 MonoDynamicTable *table;
2444 char *b = blob_size;
2448 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2449 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2450 * Because of this, we must not insert it into the `typeref' hash table.
2453 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2457 g_assert (tb->generic_params);
2458 klass = mono_class_from_mono_type (tb->type.type);
2460 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2461 encode_type (assembly, &klass->byval_arg, p, &p);
2463 count = mono_array_length (tb->generic_params);
2464 mono_metadata_encode_value (count, p, &p);
2465 for (i = 0; i < count; i++) {
2466 MonoReflectionGenericParam *gparam;
2468 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2470 encode_type (assembly, gparam->type.type, p, &p);
2473 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2474 if (assembly->save) {
2475 g_assert (p-sig < 128);
2476 mono_metadata_encode_value (p-sig, b, &b);
2477 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2478 alloc_table (table, table->rows + 1);
2479 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2480 values [MONO_TYPESPEC_SIGNATURE] = token;
2483 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2484 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2490 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2492 MonoDynamicTable *table;
2495 guint32 token, pclass, parent, sig;
2498 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2502 klass = mono_class_from_mono_type (fb->typeb->type);
2503 name = mono_string_to_utf8 (fb->name);
2505 sig = fieldref_encode_signature (assembly, fb->type->type);
2507 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2508 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2510 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2511 parent >>= MONO_TYPEDEFORREF_BITS;
2513 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2515 if (assembly->save) {
2516 alloc_table (table, table->rows + 1);
2517 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2518 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2519 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2520 values [MONO_MEMBERREF_SIGNATURE] = sig;
2523 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2525 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2530 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2538 char *b = blob_size;
2540 if (!assembly->save)
2544 g_assert (helper->type == 2);
2546 if (helper->arguments)
2547 nargs = mono_array_length (helper->arguments);
2551 size = 10 + (nargs * 10);
2553 p = buf = g_malloc (size);
2555 /* Encode calling convention */
2556 /* Change Any to Standard */
2557 if ((helper->call_conv & 0x03) == 0x03)
2558 helper->call_conv = 0x01;
2559 /* explicit_this implies has_this */
2560 if (helper->call_conv & 0x40)
2561 helper->call_conv &= 0x20;
2563 if (helper->call_conv == 0) /* Unmanaged */
2564 *p = helper->unmanaged_call_conv - 1;
2567 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2568 if (helper->call_conv & 0x02) /* varargs */
2573 mono_metadata_encode_value (nargs, p, &p);
2574 encode_reflection_type (assembly, helper->return_type, p, &p);
2575 for (i = 0; i < nargs; ++i) {
2576 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2577 encode_reflection_type (assembly, pt, p, &p);
2580 g_assert (p - buf < size);
2581 mono_metadata_encode_value (p-buf, b, &b);
2582 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2589 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2592 MonoDynamicTable *table;
2595 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2596 idx = table->next_idx ++;
2598 alloc_table (table, table->rows);
2599 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2601 values [MONO_STAND_ALONE_SIGNATURE] =
2602 mono_reflection_encode_sighelper (assembly, helper);
2608 reflection_cc_to_file (int call_conv) {
2609 switch (call_conv & 0x3) {
2611 case 1: return MONO_CALL_DEFAULT;
2612 case 2: return MONO_CALL_VARARG;
2614 g_assert_not_reached ();
2621 MonoMethodSignature *sig;
2627 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2632 MonoMethodSignature *sig;
2635 name = mono_string_to_utf8 (m->name);
2636 nparams = mono_array_length (m->parameters);
2637 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2639 sig->sentinelpos = -1;
2640 sig->call_convention = reflection_cc_to_file (m->call_conv);
2641 sig->param_count = nparams;
2642 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2643 for (i = 0; i < nparams; ++i) {
2644 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2645 sig->params [i] = t->type;
2648 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2650 if (strcmp (name, am->name) == 0 &&
2651 mono_metadata_type_equal (am->parent, m->parent->type) &&
2652 mono_metadata_signature_equal (am->sig, sig)) {
2655 m->table_idx = am->token & 0xffffff;
2659 am = g_new0 (ArrayMethod, 1);
2662 am->parent = m->parent->type;
2663 am->token = mono_image_get_memberref_token (assembly, am->parent,
2664 name, method_encode_signature (assembly, sig));
2665 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2666 m->table_idx = am->token & 0xffffff;
2671 * Insert into the metadata tables all the info about the TypeBuilder tb.
2672 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2675 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2677 MonoDynamicTable *table;
2679 int i, is_object = 0, is_system = 0;
2682 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2683 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2684 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2685 n = mono_string_to_utf8 (tb->name);
2686 if (strcmp (n, "Object") == 0)
2688 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2690 n = mono_string_to_utf8 (tb->nspace);
2691 if (strcmp (n, "System") == 0)
2693 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2695 if (tb->parent && !(is_system && is_object) &&
2696 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2697 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2699 values [MONO_TYPEDEF_EXTENDS] = 0;
2700 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2701 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2704 * if we have explicitlayout or sequentiallayouts, output data in the
2705 * ClassLayout table.
2707 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2708 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2710 alloc_table (table, table->rows);
2711 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2712 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2713 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2714 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2717 /* handle interfaces */
2718 if (tb->interfaces) {
2719 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2721 table->rows += mono_array_length (tb->interfaces);
2722 alloc_table (table, table->rows);
2723 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2724 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2725 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2726 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2727 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2728 values += MONO_INTERFACEIMPL_SIZE;
2732 /* handle generic parameters */
2733 if (tb->generic_params) {
2734 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2735 table->rows += mono_array_length (tb->generic_params);
2736 alloc_table (table, table->rows);
2737 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2738 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2740 mono_image_get_generic_param_info (
2741 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2747 table = &assembly->tables [MONO_TABLE_FIELD];
2748 table->rows += tb->num_fields;
2749 alloc_table (table, table->rows);
2750 for (i = 0; i < tb->num_fields; ++i)
2751 mono_image_get_field_info (
2752 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2755 /* handle constructors */
2757 table = &assembly->tables [MONO_TABLE_METHOD];
2758 table->rows += mono_array_length (tb->ctors);
2759 alloc_table (table, table->rows);
2760 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2761 mono_image_get_ctor_info (domain,
2762 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2765 /* handle methods */
2767 table = &assembly->tables [MONO_TABLE_METHOD];
2768 table->rows += tb->num_methods;
2769 alloc_table (table, table->rows);
2770 for (i = 0; i < tb->num_methods; ++i)
2771 mono_image_get_method_info (
2772 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2775 /* Do the same with properties etc.. */
2776 if (tb->events && mono_array_length (tb->events)) {
2777 table = &assembly->tables [MONO_TABLE_EVENT];
2778 table->rows += mono_array_length (tb->events);
2779 alloc_table (table, table->rows);
2780 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2782 alloc_table (table, table->rows);
2783 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2784 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2785 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2786 for (i = 0; i < mono_array_length (tb->events); ++i)
2787 mono_image_get_event_info (
2788 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2790 if (tb->properties && mono_array_length (tb->properties)) {
2791 table = &assembly->tables [MONO_TABLE_PROPERTY];
2792 table->rows += mono_array_length (tb->properties);
2793 alloc_table (table, table->rows);
2794 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2796 alloc_table (table, table->rows);
2797 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2798 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2799 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2800 for (i = 0; i < mono_array_length (tb->properties); ++i)
2801 mono_image_get_property_info (
2802 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2805 mono_image_add_decl_security (assembly,
2806 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2810 MonoDynamicTable *ntable;
2812 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2813 ntable->rows += mono_array_length (tb->subtypes);
2814 alloc_table (ntable, ntable->rows);
2815 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2817 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2818 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2820 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2821 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2822 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2823 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2824 mono_string_to_utf8 (tb->name), tb->table_idx,
2825 ntable->next_idx, ntable->rows);*/
2826 values += MONO_NESTED_CLASS_SIZE;
2833 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2837 g_ptr_array_add (types, type);
2839 if (!type->subtypes)
2842 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2843 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2844 collect_types (types, subtype);
2849 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2850 MonoReflectionTypeBuilder **type2)
2852 if ((*type1)->table_idx < (*type2)->table_idx)
2855 if ((*type1)->table_idx > (*type2)->table_idx)
2862 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2867 for (i = 0; i < mono_array_length (pinfo); ++i) {
2868 MonoReflectionParamBuilder *pb;
2869 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2872 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2877 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2880 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2882 for (i = 0; i < tb->num_fields; ++i) {
2883 MonoReflectionFieldBuilder* fb;
2884 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2885 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2889 for (i = 0; i < mono_array_length (tb->events); ++i) {
2890 MonoReflectionEventBuilder* eb;
2891 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2892 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2895 if (tb->properties) {
2896 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2897 MonoReflectionPropertyBuilder* pb;
2898 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2899 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2903 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2904 MonoReflectionCtorBuilder* cb;
2905 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2906 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2907 params_add_cattrs (assembly, cb->pinfo);
2912 for (i = 0; i < tb->num_methods; ++i) {
2913 MonoReflectionMethodBuilder* mb;
2914 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2915 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2916 params_add_cattrs (assembly, mb->pinfo);
2921 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2922 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2927 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2930 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
2932 /* no types in the module */
2936 for (i = 0; i < mb->num_types; ++i)
2937 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2941 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2942 MonoDynamicImage *assembly)
2944 MonoDynamicTable *table;
2948 char *b = blob_size;
2951 table = &assembly->tables [MONO_TABLE_FILE];
2953 alloc_table (table, table->rows);
2954 values = table->values + table->next_idx * MONO_FILE_SIZE;
2955 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2956 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2957 if (module->image->dynamic) {
2958 /* This depends on the fact that the main module is emitted last */
2959 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2960 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2964 path = g_strdup (module->image->name);
2966 mono_sha1_get_digest_from_file (path, hash);
2969 mono_metadata_encode_value (20, b, &b);
2970 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2971 mono_image_add_stream_data (&assembly->blob, hash, 20);
2976 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2978 MonoDynamicTable *table;
2982 table = &assembly->tables [MONO_TABLE_MODULE];
2983 mb->table_idx = table->next_idx ++;
2984 name = mono_string_to_utf8 (mb->module.name);
2985 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2987 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2990 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2991 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2992 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2996 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
2997 guint32 module_index, guint32 parent_index,
2998 MonoDynamicImage *assembly)
3000 MonoDynamicTable *table;
3004 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3005 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3008 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3010 alloc_table (table, table->rows);
3011 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3013 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3014 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3015 if (klass->nested_in)
3016 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3018 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3019 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3020 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3022 res = table->next_idx;
3026 /* Emit nested types */
3027 if (klass->nested_classes) {
3030 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3031 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3038 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3039 guint32 module_index, guint32 parent_index,
3040 MonoDynamicImage *assembly)
3045 klass = mono_class_from_mono_type (tb->type.type);
3047 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3049 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3050 parent_index, assembly);
3054 * We need to do this ourselves since klass->nested_classes is not set up.
3057 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3058 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3063 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3064 guint32 module_index,
3065 MonoDynamicImage *assembly)
3067 MonoImage *image = module->image;
3071 t = &image->tables [MONO_TABLE_TYPEDEF];
3073 for (i = 0; i < t->rows; ++i) {
3074 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3076 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3077 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3081 #define align_pointer(base,p)\
3083 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3085 (p) += 4 - (__diff & 3);\
3089 compare_semantics (const void *a, const void *b)
3091 const guint32 *a_values = a;
3092 const guint32 *b_values = b;
3093 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3096 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3100 compare_custom_attrs (const void *a, const void *b)
3102 const guint32 *a_values = a;
3103 const guint32 *b_values = b;
3105 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3109 compare_field_marshal (const void *a, const void *b)
3111 const guint32 *a_values = a;
3112 const guint32 *b_values = b;
3114 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3118 compare_nested (const void *a, const void *b)
3120 const guint32 *a_values = a;
3121 const guint32 *b_values = b;
3123 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3127 * build_compressed_metadata() fills in the blob of data that represents the
3128 * raw metadata as it will be saved in the PE file. The five streams are output
3129 * and the metadata tables are comnpressed from the guint32 array representation,
3130 * to the compressed on-disk format.
3133 build_compressed_metadata (MonoDynamicImage *assembly)
3135 MonoDynamicTable *table;
3137 guint64 valid_mask = 0;
3138 guint64 sorted_mask;
3139 guint32 heapt_size = 0;
3140 guint32 meta_size = 256; /* allow for header and other stuff */
3141 guint32 table_offset;
3142 guint32 ntables = 0;
3151 MonoDynamicStream *stream;
3154 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3155 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3156 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3157 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3158 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3160 /* tables that are sorted */
3161 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3162 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3163 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3164 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3165 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3166 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
3168 /* Compute table sizes */
3169 /* the MonoImage has already been created in mono_image_basic_init() */
3170 meta = &assembly->image;
3172 /* Setup the info used by compute_sizes () */
3173 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3174 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3175 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3177 meta_size += assembly->blob.index;
3178 meta_size += assembly->guid.index;
3179 meta_size += assembly->sheap.index;
3180 meta_size += assembly->us.index;
3182 for (i=0; i < 64; ++i)
3183 meta->tables [i].rows = assembly->tables [i].rows;
3185 for (i = 0; i < 64; i++){
3186 if (meta->tables [i].rows == 0)
3188 valid_mask |= (guint64)1 << i;
3190 meta->tables [i].row_size = mono_metadata_compute_size (
3191 meta, i, &meta->tables [i].size_bitfield);
3192 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3194 heapt_size += 24; /* #~ header size */
3195 heapt_size += ntables * 4;
3196 meta_size += heapt_size;
3197 meta->raw_metadata = g_malloc0 (meta_size);
3198 p = meta->raw_metadata;
3199 /* the metadata signature */
3200 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3201 /* version numbers and 4 bytes reserved */
3202 int16val = (guint16*)p;
3203 *int16val++ = GUINT16_TO_LE (1);
3204 *int16val = GUINT16_TO_LE (1);
3206 /* version string */
3207 int32val = (guint32*)p;
3208 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3210 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3211 p += GUINT32_FROM_LE (*int32val);
3212 align_pointer (meta->raw_metadata, p);
3213 int16val = (guint16*)p;
3214 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3215 *int16val = GUINT16_TO_LE (5); /* number of streams */
3219 * write the stream info.
3221 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3222 table_offset += 3; table_offset &= ~3;
3224 assembly->tstream.index = heapt_size;
3225 for (i = 0; i < 5; ++i) {
3226 int32val = (guint32*)p;
3227 stream_desc [i].stream->offset = table_offset;
3228 *int32val++ = GUINT32_TO_LE (table_offset);
3229 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3230 table_offset += GUINT32_FROM_LE (*int32val);
3231 table_offset += 3; table_offset &= ~3;
3233 strcpy (p, stream_desc [i].name);
3234 p += strlen (stream_desc [i].name) + 1;
3235 align_pointer (meta->raw_metadata, p);
3238 * now copy the data, the table stream header and contents goes first.
3240 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3241 p = meta->raw_metadata + assembly->tstream.offset;
3242 int32val = (guint32*)p;
3243 *int32val = GUINT32_TO_LE (0); /* reserved */
3246 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3247 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3248 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3249 *p++ = 1; /* version */
3252 *p++ = 1; /* version */
3256 if (meta->idx_string_wide)
3258 if (meta->idx_guid_wide)
3260 if (meta->idx_blob_wide)
3263 *p++ = 0; /* reserved */
3264 int64val = (guint64*)p;
3265 *int64val++ = GUINT64_TO_LE (valid_mask);
3266 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3268 int32val = (guint32*)p;
3269 for (i = 0; i < 64; i++){
3270 if (meta->tables [i].rows == 0)
3272 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3274 p = (unsigned char*)int32val;
3276 /* sort the tables that still need sorting */
3277 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3279 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3280 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3282 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3283 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3285 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3286 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3288 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3290 /* compress the tables */
3291 for (i = 0; i < 64; i++){
3294 guint32 bitfield = meta->tables [i].size_bitfield;
3295 if (!meta->tables [i].rows)
3297 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3298 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3299 meta->tables [i].base = p;
3300 for (row = 1; row <= meta->tables [i].rows; ++row) {
3301 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3302 for (col = 0; col < assembly->tables [i].columns; ++col) {
3303 switch (mono_metadata_table_size (bitfield, col)) {
3305 *p++ = values [col];
3308 *p++ = values [col] & 0xff;
3309 *p++ = (values [col] >> 8) & 0xff;
3312 *p++ = values [col] & 0xff;
3313 *p++ = (values [col] >> 8) & 0xff;
3314 *p++ = (values [col] >> 16) & 0xff;
3315 *p++ = (values [col] >> 24) & 0xff;
3318 g_assert_not_reached ();
3322 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3325 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3326 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3327 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3328 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3329 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3331 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3335 * Some tables in metadata need to be sorted according to some criteria, but
3336 * when methods and fields are first created with reflection, they may be assigned a token
3337 * that doesn't correspond to the final token they will get assigned after the sorting.
3338 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3339 * with the reflection objects that represent them. Once all the tables are set up, the
3340 * reflection objects will contains the correct table index. fixup_method() will fixup the
3341 * tokens for the method with ILGenerator @ilgen.
3344 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3345 guint32 code_idx = GPOINTER_TO_UINT (value);
3346 MonoReflectionILTokenInfo *iltoken;
3347 MonoReflectionFieldBuilder *field;
3348 MonoReflectionCtorBuilder *ctor;
3349 MonoReflectionMethodBuilder *method;
3350 MonoReflectionTypeBuilder *tb;
3351 MonoReflectionArrayMethod *am;
3353 unsigned char *target;
3355 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3356 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3357 target = assembly->code.data + code_idx + iltoken->code_pos;
3358 switch (target [3]) {
3359 case MONO_TABLE_FIELD:
3360 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3361 field = (MonoReflectionFieldBuilder *)iltoken->member;
3362 idx = field->table_idx;
3363 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3364 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3365 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3367 g_assert_not_reached ();
3370 case MONO_TABLE_METHOD:
3371 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3372 method = (MonoReflectionMethodBuilder *)iltoken->member;
3373 idx = method->table_idx;
3374 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3375 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3376 idx = ctor->table_idx;
3377 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3378 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3379 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3380 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3382 g_assert_not_reached ();
3385 case MONO_TABLE_TYPEDEF:
3386 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3387 g_assert_not_reached ();
3388 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3389 idx = tb->table_idx;
3391 case MONO_TABLE_MEMBERREF:
3392 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3393 am = (MonoReflectionArrayMethod*)iltoken->member;
3394 idx = am->table_idx;
3395 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3396 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3397 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3398 g_assert (m->klass->generic_inst);
3400 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3402 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3403 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3404 g_assert (f->generic_info);
3406 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3409 g_assert_not_reached ();
3412 case MONO_TABLE_METHODSPEC:
3413 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3414 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3415 g_assert (m->signature->generic_param_count);
3418 g_assert_not_reached ();
3422 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3424 target [0] = idx & 0xff;
3425 target [1] = (idx >> 8) & 0xff;
3426 target [2] = (idx >> 16) & 0xff;
3433 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3434 * value is not known when the table is emitted.
3437 fixup_cattrs (MonoDynamicImage *assembly)
3439 MonoDynamicTable *table;
3441 guint32 type, i, idx, token;
3444 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3446 for (i = 0; i < table->rows; ++i) {
3447 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3449 type = values [MONO_CUSTOM_ATTR_TYPE];
3450 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3451 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3452 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3453 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3456 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3457 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3458 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3459 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3466 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3468 MonoDynamicTable *table;
3472 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3474 alloc_table (table, table->rows);
3475 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3476 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3477 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3478 name = mono_string_to_utf8 (rsrc->name);
3479 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3481 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3486 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3488 MonoDynamicTable *table;
3492 char *b = blob_size;
3494 guint32 idx, offset;
3496 if (rsrc->filename) {
3497 name = mono_string_to_utf8 (rsrc->filename);
3498 sname = g_path_get_basename (name);
3500 table = &assembly->tables [MONO_TABLE_FILE];
3502 alloc_table (table, table->rows);
3503 values = table->values + table->next_idx * MONO_FILE_SIZE;
3504 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3505 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3508 mono_sha1_get_digest_from_file (name, hash);
3509 mono_metadata_encode_value (20, b, &b);
3510 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3511 mono_image_add_stream_data (&assembly->blob, hash, 20);
3513 idx = table->next_idx++;
3515 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3518 offset = mono_array_length (rsrc->data);
3519 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3520 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3521 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3522 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3526 * The entry should be emitted into the MANIFESTRESOURCE table of
3527 * the main module, but that needs to reference the FILE table
3528 * which isn't emitted yet.
3535 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3539 set_version_from_string (MonoString *version, guint32 *values)
3541 gchar *ver, *p, *str;
3544 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3545 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3546 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3547 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3550 ver = str = mono_string_to_utf8 (version);
3551 for (i = 0; i < 4; ++i) {
3552 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3558 /* handle Revision and Build */
3568 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3572 char *b = blob_size;
3577 len = mono_array_length (pkey);
3578 mono_metadata_encode_value (len, b, &b);
3579 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3580 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3582 /* need to get the actual value from the key type... */
3583 assembly->strong_name_size = 128;
3584 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3590 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3592 MonoDynamicTable *table;
3593 MonoDynamicImage *assembly;
3594 MonoReflectionAssemblyBuilder *assemblyb;
3599 guint32 module_index;
3601 assemblyb = moduleb->assemblyb;
3602 assembly = moduleb->dynamic_image;
3603 domain = mono_object_domain (assemblyb);
3605 /* Emit ASSEMBLY table */
3606 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3607 alloc_table (table, 1);
3608 values = table->values + MONO_ASSEMBLY_SIZE;
3609 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3610 name = mono_string_to_utf8 (assemblyb->name);
3611 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3613 if (assemblyb->culture) {
3614 name = mono_string_to_utf8 (assemblyb->culture);
3615 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3618 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3620 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3621 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3622 set_version_from_string (assemblyb->version, values);
3624 /* Emit FILE + EXPORTED_TYPE table */
3626 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3628 MonoReflectionModuleBuilder *file_module =
3629 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3630 if (file_module != moduleb) {
3631 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3633 if (file_module->types) {
3634 for (j = 0; j < file_module->num_types; ++j) {
3635 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3636 mono_image_fill_export_table (domain, tb, module_index, 0,
3642 if (assemblyb->loaded_modules) {
3643 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3644 MonoReflectionModule *file_module =
3645 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3646 mono_image_fill_file_table (domain, file_module, assembly);
3648 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3652 /* Emit MANIFESTRESOURCE table */
3654 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3656 MonoReflectionModuleBuilder *file_module =
3657 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3658 /* The table for the main module is emitted later */
3659 if (file_module != moduleb) {
3661 if (file_module->resources) {
3662 int len = mono_array_length (file_module->resources);
3663 for (j = 0; j < len; ++j) {
3664 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3665 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3673 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3674 * for the modulebuilder @moduleb.
3675 * At the end of the process, method and field tokens are fixed up and the
3676 * on-disk compressed metadata representation is created.
3679 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3681 MonoDynamicTable *table;
3682 MonoDynamicImage *assembly;
3683 MonoReflectionAssemblyBuilder *assemblyb;
3688 assemblyb = moduleb->assemblyb;
3689 assembly = moduleb->dynamic_image;
3690 domain = mono_object_domain (assemblyb);
3692 if (assembly->text_rva)
3695 assembly->text_rva = START_TEXT_RVA;
3697 if (moduleb->is_main) {
3698 mono_image_emit_manifest (moduleb);
3701 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3702 table->rows = 1; /* .<Module> */
3704 alloc_table (table, table->rows);
3706 * Set the first entry.
3708 values = table->values + table->columns;
3709 values [MONO_TYPEDEF_FLAGS] = 0;
3710 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3711 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3712 values [MONO_TYPEDEF_EXTENDS] = 0;
3713 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3714 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3717 * handle global methods
3718 * FIXME: test what to do when global methods are defined in multiple modules.
3720 if (moduleb->global_methods) {
3721 table = &assembly->tables [MONO_TABLE_METHOD];
3722 table->rows += mono_array_length (moduleb->global_methods);
3723 alloc_table (table, table->rows);
3724 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3725 mono_image_get_method_info (
3726 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3728 if (moduleb->global_fields) {
3729 table = &assembly->tables [MONO_TABLE_FIELD];
3730 table->rows += mono_array_length (moduleb->global_fields);
3731 alloc_table (table, table->rows);
3732 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3733 mono_image_get_field_info (
3734 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3737 table = &assembly->tables [MONO_TABLE_MODULE];
3738 alloc_table (table, 1);
3739 mono_image_fill_module_table (domain, moduleb, assembly);
3743 /* Collect all types into a list sorted by their table_idx */
3744 GPtrArray *types = g_ptr_array_new ();
3747 for (i = 0; i < moduleb->num_types; ++i) {
3748 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3749 collect_types (types, type);
3752 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3753 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3754 table->rows += types->len;
3755 alloc_table (table, table->rows);
3757 for (i = 0; i < types->len; ++i) {
3758 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3759 mono_image_get_type_info (domain, type, assembly);
3761 g_ptr_array_free (types, TRUE);
3765 * table->rows is already set above and in mono_image_fill_module_table.
3767 /* add all the custom attributes at the end, once all the indexes are stable */
3768 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3770 module_add_cattrs (assembly, moduleb);
3773 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3774 fixup_cattrs (assembly);
3778 * mono_image_insert_string:
3779 * @module: module builder object
3782 * Insert @str into the user string stream of @module.
3785 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3787 MonoDynamicImage *assembly;
3792 MONO_ARCH_SAVE_REGS;
3794 if (!module->dynamic_image)
3795 mono_image_module_basic_init (module);
3797 assembly = module->dynamic_image;
3799 if (assembly->save) {
3800 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3801 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3802 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3804 char *swapped = g_malloc (2 * mono_string_length (str));
3805 const char *p = (const char*)mono_string_chars (str);
3807 swap_with_size (swapped, p, 2, mono_string_length (str));
3808 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3812 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3814 mono_image_add_stream_data (&assembly->us, "", 1);
3817 idx = assembly->us.index ++;
3819 mono_g_hash_table_insert (assembly->tokens,
3820 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3822 return MONO_TOKEN_STRING | idx;
3826 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj,
3827 MonoArray *opt_param_types)
3832 klass = obj->vtable->klass;
3833 if (strcmp (klass->name, "MonoMethod") == 0) {
3834 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3835 MonoMethodSignature *sig, *old;
3836 guint32 sig_token, parent;
3839 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3841 nargs = mono_array_length (opt_param_types);
3842 old = method->signature;
3843 sig = mono_metadata_signature_alloc (
3844 &assembly->image, old->param_count + nargs);
3846 sig->hasthis = old->hasthis;
3847 sig->explicit_this = old->explicit_this;
3848 sig->call_convention = old->call_convention;
3849 sig->generic_param_count = old->generic_param_count;
3850 sig->param_count = old->param_count + nargs;
3851 sig->sentinelpos = old->param_count;
3852 sig->ret = old->ret;
3854 for (i = 0; i < old->param_count; i++)
3855 sig->params [i] = old->params [i];
3857 for (i = 0; i < nargs; i++) {
3858 MonoReflectionType *rt = mono_array_get (
3859 opt_param_types, MonoReflectionType *, i);
3860 sig->params [old->param_count + i] = rt->type;
3863 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
3864 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
3865 parent >>= MONO_TYPEDEFORREF_BITS;
3867 parent <<= MONO_MEMBERREF_PARENT_BITS;
3868 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
3870 sig_token = method_encode_signature (assembly, sig);
3871 token = mono_image_get_varargs_method_token (
3872 assembly, parent, method->name, sig_token);
3873 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
3874 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3875 ReflectionMethodBuilder rmb;
3876 guint32 parent, sig;
3878 reflection_methodbuilder_from_method_builder (&rmb, mb);
3879 rmb.opt_types = opt_param_types;
3881 sig = method_builder_encode_signature (assembly, &rmb);
3883 parent = mono_image_create_token (assembly, obj);
3884 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
3886 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
3887 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
3889 token = mono_image_get_varargs_method_token (
3890 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
3892 g_error ("requested method token for %s\n", klass->name);
3898 * mono_image_create_token:
3899 * @assembly: a dynamic assembly
3902 * Get a token to insert in the IL code stream for the given MemberInfo.
3903 * @obj can be one of:
3904 * ConstructorBuilder
3914 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3919 klass = obj->vtable->klass;
3920 if (strcmp (klass->name, "MethodBuilder") == 0) {
3921 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3923 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3924 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3926 token = mono_image_get_methodbuilder_token (assembly, mb);
3927 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3929 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3930 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3932 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3933 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3935 token = mono_image_get_ctorbuilder_token (assembly, mb);
3936 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3938 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3939 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3940 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3941 if (tb->generic_params) {
3942 token = mono_image_get_generic_field_token (assembly, fb);
3944 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3947 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3948 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3949 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3951 else if (strcmp (klass->name, "MonoType") == 0 ||
3952 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
3953 MonoReflectionType *tb = (MonoReflectionType *)obj;
3954 token = mono_metadata_token_from_dor (
3955 mono_image_typedef_or_ref (assembly, tb->type));
3957 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
3958 MonoReflectionType *tb = (MonoReflectionType *)obj;
3959 token = mono_metadata_token_from_dor (
3960 mono_image_typedef_or_ref (assembly, tb->type));
3962 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3963 strcmp (klass->name, "MonoMethod") == 0) {
3964 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3965 if (m->method->signature->is_inflated) {
3966 token = mono_image_get_methodspec_token (assembly, m->method);
3967 } else if (m->method->signature->generic_param_count) {
3968 g_assert_not_reached ();
3969 } else if ((m->method->klass->image == &assembly->image) &&
3970 !m->method->klass->generic_inst) {
3971 static guint32 method_table_idx = 0xffffff;
3972 if (m->method->klass->wastypebuilder) {
3973 /* we use the same token as the one that was assigned
3974 * to the Methodbuilder.
3975 * FIXME: do the equivalent for Fields.
3977 token = m->method->token;
3980 * Each token should have a unique index, but the indexes are
3981 * assigned by managed code, so we don't know about them. An
3982 * easy solution is to count backwards...
3984 method_table_idx --;
3985 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3988 token = mono_image_get_methodref_token (assembly, m->method);
3989 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3991 else if (strcmp (klass->name, "MonoField") == 0) {
3992 MonoReflectionField *f = (MonoReflectionField *)obj;
3993 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
3994 static guint32 field_table_idx = 0xffffff;
3996 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3998 token = mono_image_get_fieldref_token (assembly, f);
3999 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4001 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4002 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4003 token = mono_image_get_array_token (assembly, m);
4005 else if (strcmp (klass->name, "SignatureHelper") == 0) {
4006 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4007 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4010 g_error ("requested token for %s\n", klass->name);
4012 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
4019 guint32 import_lookup_table;
4023 guint32 import_address_table_rva;
4031 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4033 static MonoDynamicImage*
4034 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
4035 char *assembly_name, char *module_name)
4037 static const guchar entrycode [16] = {0xff, 0x25, 0};
4038 MonoDynamicImage *image;
4042 * We need to use the current ms version or the ms runtime it won't find
4043 * the support dlls. D'oh!
4044 * const char *version = "mono-" VERSION;
4047 * To make binaries default to the .Net 1.0 version
4048 * const char *version = "v1.0.3705";
4050 const char *version = "v1.1.4322";
4053 image = GC_MALLOC (sizeof (MonoDynamicImage));
4055 image = g_new0 (MonoDynamicImage, 1);
4058 /* keep in sync with image.c */
4059 image->image.name = assembly_name;
4060 image->image.assembly_name = image->image.name; /* they may be different */
4061 image->image.module_name = module_name;
4062 image->image.version = g_strdup (version);
4063 image->image.dynamic = TRUE;
4065 image->image.references = g_new0 (MonoAssembly*, 1);
4066 image->image.references [0] = NULL;
4068 mono_image_init (&image->image);
4070 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4071 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4072 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4073 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4074 image->handleref = g_hash_table_new (NULL, NULL);
4075 image->tokens = mono_g_hash_table_new (NULL, NULL);
4076 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4077 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4078 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4080 string_heap_init (&image->sheap);
4081 mono_image_add_stream_data (&image->us, "", 1);
4082 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4083 /* import tables... */
4084 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4085 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4086 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4087 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4088 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4089 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4090 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4091 stream_data_align (&image->code);
4093 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4095 for (i=0; i < 64; ++i) {
4096 image->tables [i].next_idx = 1;
4097 image->tables [i].columns = table_sizes [i];
4100 image->image.assembly = (MonoAssembly*)assembly;
4101 image->run = assembly->run;
4102 image->save = assembly->save;
4108 * mono_image_basic_init:
4109 * @assembly: an assembly builder object
4111 * Create the MonoImage that represents the assembly builder and setup some
4112 * of the helper hash table and the basic metadata streams.
4115 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4117 MonoDynamicAssembly *assembly;
4118 MonoDynamicImage *image;
4120 MONO_ARCH_SAVE_REGS;
4122 if (assemblyb->dynamic_assembly)
4126 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4128 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4131 assembly->assembly.dynamic = TRUE;
4132 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4133 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4134 if (assemblyb->culture)
4135 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4137 assembly->assembly.aname.culture = g_strdup ("");
4139 assembly->run = assemblyb->access != 2;
4140 assembly->save = assemblyb->access != 1;
4142 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4143 assembly->assembly.aname.name = image->image.name;
4144 assembly->assembly.image = &image->image;
4146 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4147 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4151 calc_section_size (MonoDynamicImage *assembly)
4155 /* alignment constraints */
4156 assembly->code.index += 3;
4157 assembly->code.index &= ~3;
4158 assembly->meta_size += 3;
4159 assembly->meta_size &= ~3;
4160 assembly->resources.index += 3;
4161 assembly->resources.index &= ~3;
4163 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4164 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4167 if (assembly->win32_res) {
4168 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4170 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4171 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4175 assembly->sections [MONO_SECTION_RELOC].size = 12;
4176 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4186 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4190 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4192 ResTreeNode *t1 = (ResTreeNode*)a;
4193 ResTreeNode *t2 = (ResTreeNode*)b;
4195 return t1->id - t2->id;
4199 * resource_tree_create:
4201 * Organize the resources into a resource tree.
4203 static ResTreeNode *
4204 resource_tree_create (MonoArray *win32_resources)
4206 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4210 tree = g_new0 (ResTreeNode, 1);
4212 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4213 MonoReflectionWin32Resource *win32_res =
4214 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4218 lang_node = g_new0 (ResTreeNode, 1);
4219 lang_node->id = win32_res->lang_id;
4220 lang_node->win32_res = win32_res;
4222 /* Create type node if neccesary */
4224 for (l = tree->children; l; l = l->next)
4225 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4226 type_node = (ResTreeNode*)l->data;
4231 type_node = g_new0 (ResTreeNode, 1);
4232 type_node->id = win32_res->res_type;
4235 * The resource types have to be sorted otherwise
4236 * Windows Explorer can't display the version information.
4238 tree->children = g_slist_insert_sorted (tree->children, type_node,
4239 resource_tree_compare_by_id);
4242 /* Create res node if neccesary */
4244 for (l = type_node->children; l; l = l->next)
4245 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4246 res_node = (ResTreeNode*)l->data;
4251 res_node = g_new0 (ResTreeNode, 1);
4252 res_node->id = win32_res->res_id;
4253 type_node->children = g_slist_append (type_node->children, res_node);
4256 res_node->children = g_slist_append (res_node->children, lang_node);
4263 * resource_tree_encode:
4265 * Encode the resource tree into the format used in the PE file.
4268 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4271 MonoPEResourceDir dir;
4272 MonoPEResourceDirEntry dir_entry;
4273 MonoPEResourceDataEntry data_entry;
4277 * For the format of the resource directory, see the article
4278 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4282 memset (&dir, 0, sizeof (dir));
4283 memset (&dir_entry, 0, sizeof (dir_entry));
4284 memset (&data_entry, 0, sizeof (data_entry));
4286 g_assert (sizeof (dir) == 16);
4287 g_assert (sizeof (dir_entry) == 8);
4288 g_assert (sizeof (data_entry) == 16);
4290 node->offset = p - begin;
4292 /* IMAGE_RESOURCE_DIRECTORY */
4293 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4295 memcpy (p, &dir, sizeof (dir));
4298 /* Reserve space for entries */
4300 p += sizeof (dir_entry) * dir.res_id_entries;
4302 /* Write children */
4303 for (l = node->children; l; l = l->next) {
4304 ResTreeNode *child = (ResTreeNode*)l->data;
4306 if (child->win32_res) {
4308 child->offset = p - begin;
4310 /* IMAGE_RESOURCE_DATA_ENTRY */
4311 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4312 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4314 memcpy (p, &data_entry, sizeof (data_entry));
4315 p += sizeof (data_entry);
4317 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4318 p += data_entry.rde_size;
4321 resource_tree_encode (child, begin, p, &p);
4324 /* IMAGE_RESOURCE_ENTRY */
4325 for (l = node->children; l; l = l->next) {
4326 ResTreeNode *child = (ResTreeNode*)l->data;
4327 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4329 dir_entry.is_dir = child->win32_res ? 0 : 1;
4330 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4332 memcpy (entries, &dir_entry, sizeof (dir_entry));
4333 entries += sizeof (dir_entry);
4340 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4345 MonoReflectionWin32Resource *win32_res;
4348 if (!assemblyb->win32_resources)
4352 * Resources are stored in a three level tree inside the PE file.
4353 * - level one contains a node for each type of resource
4354 * - level two contains a node for each resource
4355 * - level three contains a node for each instance of a resource for a
4356 * specific language.
4359 tree = resource_tree_create (assemblyb->win32_resources);
4361 /* Estimate the size of the encoded tree */
4363 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4364 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4365 size += mono_array_length (win32_res->res_data);
4367 /* Directory structure */
4368 size += mono_array_length (assemblyb->win32_resources) * 256;
4369 p = buf = g_malloc (size);
4371 resource_tree_encode (tree, p, p, &p);
4373 g_assert (p - buf < size);
4375 assembly->win32_res = g_malloc (p - buf);
4376 assembly->win32_res_size = p - buf;
4377 memcpy (assembly->win32_res, buf, p - buf);
4383 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4385 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4388 p += sizeof (MonoPEResourceDir);
4389 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4390 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4391 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4392 if (dir_entry->is_dir)
4393 fixup_resource_directory (res_section, child, rva);
4395 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4396 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4399 p += sizeof (MonoPEResourceDirEntry);
4404 * mono_image_create_pefile:
4405 * @mb: a module builder object
4407 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4408 * assembly->pefile where it can be easily retrieved later in chunks.
4411 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4412 MonoMSDOSHeader *msdos;
4413 MonoDotNetHeader *header;
4414 MonoSectionTable *section;
4415 MonoCLIHeader *cli_header;
4416 guint32 size, image_size, virtual_base, text_offset;
4417 guint32 header_start, section_start, file_offset, virtual_offset;
4418 MonoDynamicImage *assembly;
4419 MonoReflectionAssemblyBuilder *assemblyb;
4420 MonoDynamicStream *pefile;
4422 guint32 *rva, value;
4425 static const unsigned char msheader[] = {
4426 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4427 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4430 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4431 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4432 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4433 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4436 assemblyb = mb->assemblyb;
4438 mono_image_basic_init (assemblyb);
4439 assembly = mb->dynamic_image;
4441 /* already created */
4442 if (assembly->pefile.index)
4445 mono_image_build_metadata (mb);
4447 if (mb->is_main && assemblyb->resources) {
4448 int len = mono_array_length (assemblyb->resources);
4449 for (i = 0; i < len; ++i)
4450 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4453 if (mb->resources) {
4454 int len = mono_array_length (mb->resources);
4455 for (i = 0; i < len; ++i)
4456 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4459 build_compressed_metadata (assembly);
4462 assembly_add_win32_resources (assembly, assemblyb);
4464 nsections = calc_section_size (assembly);
4466 pefile = &assembly->pefile;
4468 /* The DOS header and stub */
4469 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4470 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4472 /* the dotnet header */
4473 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4475 /* the section tables */
4476 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4478 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4479 virtual_offset = VIRT_ALIGN;
4482 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4483 if (!assembly->sections [i].size)
4486 file_offset += FILE_ALIGN - 1;
4487 file_offset &= ~(FILE_ALIGN - 1);
4488 virtual_offset += VIRT_ALIGN - 1;
4489 virtual_offset &= ~(VIRT_ALIGN - 1);
4491 assembly->sections [i].offset = file_offset;
4492 assembly->sections [i].rva = virtual_offset;
4494 file_offset += assembly->sections [i].size;
4495 virtual_offset += assembly->sections [i].size;
4496 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4499 file_offset += FILE_ALIGN - 1;
4500 file_offset &= ~(FILE_ALIGN - 1);
4501 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4503 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4505 /* back-patch info */
4506 msdos = (MonoMSDOSHeader*)pefile->data;
4507 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4508 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4509 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4511 header = (MonoDotNetHeader*)(pefile->data + header_start);
4512 header->pesig [0] = 'P';
4513 header->pesig [1] = 'E';
4515 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4516 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4517 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4518 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4519 if (assemblyb->pekind == 1) {
4521 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4524 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4527 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4529 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4530 header->pe.pe_major = 6;
4531 header->pe.pe_minor = 0;
4532 size = assembly->sections [MONO_SECTION_TEXT].size;
4533 size += FILE_ALIGN - 1;
4534 size &= ~(FILE_ALIGN - 1);
4535 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4536 size = assembly->sections [MONO_SECTION_RSRC].size;
4537 size += FILE_ALIGN - 1;
4538 size &= ~(FILE_ALIGN - 1);
4539 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4540 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4541 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4542 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4543 /* pe_rva_entry_point always at the beginning of the text section */
4544 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4546 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4547 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4548 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4549 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4550 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4551 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4552 size = section_start;
4553 size += FILE_ALIGN - 1;
4554 size &= ~(FILE_ALIGN - 1);
4555 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4557 size += VIRT_ALIGN - 1;
4558 size &= ~(VIRT_ALIGN - 1);
4559 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4562 // Translate the PEFileKind value to the value expected by the Windows loader
4565 short kind = assemblyb->pekind;
4568 // PEFileKinds.ConsoleApplication == 2
4569 // PEFileKinds.WindowApplication == 3
4572 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4573 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4579 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4581 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4582 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4583 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4584 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4585 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4586 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4588 /* fill data directory entries */
4590 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4591 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4593 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4594 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4596 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4597 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4598 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4599 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4600 /* patch imported function RVA name */
4601 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4602 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4604 /* the import table */
4605 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4606 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4607 /* patch imported dll RVA name and other entries in the dir */
4608 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4609 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4610 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4611 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4612 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4613 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4615 p = (assembly->code.data + assembly->ilt_offset);
4616 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4617 *p++ = (value) & 0xff;
4618 *p++ = (value >> 8) & (0xff);
4619 *p++ = (value >> 16) & (0xff);
4620 *p++ = (value >> 24) & (0xff);
4622 /* the CLI header info */
4623 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4624 cli_header->ch_size = GUINT32_FROM_LE (72);
4625 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4626 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4627 if (assemblyb->entry_point) {
4628 guint32 table_idx = 0;
4629 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4630 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4631 table_idx = methodb->table_idx;
4634 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4635 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4638 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4639 /* The embedded managed resources */
4640 text_offset = assembly->text_rva + assembly->code.index;
4641 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4642 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4643 text_offset += assembly->resources.index;
4644 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4645 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4646 text_offset += assembly->meta_size;
4647 if (assembly->strong_name_size) {
4648 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4649 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4650 text_offset += assembly->strong_name_size;
4653 /* write the section tables and section content */
4654 section = (MonoSectionTable*)(pefile->data + section_start);
4655 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4656 static const char *section_names [] = {
4657 ".text", ".rsrc", ".reloc"
4659 if (!assembly->sections [i].size)
4661 strcpy (section->st_name, section_names [i]);
4662 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4663 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4664 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4665 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4666 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4667 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4668 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4670 case MONO_SECTION_TEXT:
4671 /* patch entry point */
4672 p = (assembly->code.data + 2);
4673 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4674 *p++ = (value) & 0xff;
4675 *p++ = (value >> 8) & 0xff;
4676 *p++ = (value >> 16) & 0xff;
4677 *p++ = (value >> 24) & 0xff;
4679 text_offset = assembly->sections [i].offset;
4680 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4681 text_offset += assembly->code.index;
4682 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4683 text_offset += assembly->resources.index;
4684 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4685 text_offset += assembly->meta_size;
4686 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4688 g_free (assembly->image.raw_metadata);
4690 case MONO_SECTION_RELOC:
4691 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4692 *rva = GUINT32_FROM_LE (assembly->text_rva);
4694 *rva = GUINT32_FROM_LE (12);
4696 data16 = (guint16*)rva;
4698 * the entrypoint is always at the start of the text section
4699 * 3 is IMAGE_REL_BASED_HIGHLOW
4700 * 2 is patch_size_rva - text_rva
4702 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4704 *data16 = 0; /* terminate */
4706 case MONO_SECTION_RSRC:
4707 if (assembly->win32_res) {
4708 text_offset = assembly->sections [i].offset;
4710 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4711 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4713 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4717 g_assert_not_reached ();
4722 /* check that the file is properly padded */
4725 FILE *f = fopen ("mypetest.exe", "w");
4726 fwrite (pefile->data, pefile->index, 1, f);
4732 MonoReflectionModule *
4733 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4737 MonoImageOpenStatus status;
4738 MonoDynamicAssembly *assembly;
4740 name = mono_string_to_utf8 (fileName);
4742 image = mono_image_open (name, &status);
4745 if (status == MONO_IMAGE_ERROR_ERRNO)
4746 exc = mono_get_exception_file_not_found (fileName);
4748 exc = mono_get_exception_bad_image_format (name);
4750 mono_raise_exception (exc);
4755 assembly = ab->dynamic_assembly;
4756 image->assembly = (MonoAssembly*)assembly;
4758 mono_assembly_load_references (image, &status);
4760 mono_image_close (image);
4761 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4764 return mono_module_get_object (mono_domain_get (), image);
4768 * We need to return always the same object for MethodInfo, FieldInfo etc..
4769 * but we need to consider the reflected type.
4770 * type uses a different hash, since it uses custom hash/equal functions.
4775 MonoClass *refclass;
4779 reflected_equal (gconstpointer a, gconstpointer b) {
4780 const ReflectedEntry *ea = a;
4781 const ReflectedEntry *eb = b;
4783 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4787 reflected_hash (gconstpointer a) {
4788 const ReflectedEntry *ea = a;
4789 return GPOINTER_TO_UINT (ea->item);
4792 #define CHECK_OBJECT(t,p,k) \
4798 mono_domain_lock (domain); \
4799 if (!domain->refobject_hash) \
4800 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4801 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4802 mono_domain_unlock (domain); \
4808 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4810 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4813 #define CACHE_OBJECT(p,o,k) \
4815 ReflectedEntry *e = ALLOC_REFENTRY; \
4817 e->refclass = (k); \
4818 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4819 mono_domain_unlock (domain); \
4823 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4825 /* this is done only once */
4826 mono_domain_lock (domain);
4827 CACHE_OBJECT (assembly, res, NULL);
4831 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4833 /* this is done only once */
4834 mono_domain_lock (domain);
4835 CACHE_OBJECT (module, res, NULL);
4839 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4841 MonoDynamicImage *image = moduleb->dynamic_image;
4842 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4845 * FIXME: we already created an image in mono_image_basic_init (), but
4846 * we don't know which module it belongs to, since that is only
4847 * determined at assembly save time.
4849 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4850 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4852 moduleb->module.image = &image->image;
4853 moduleb->dynamic_image = image;
4854 register_module (mono_object_domain (moduleb), moduleb, image);
4859 * mono_assembly_get_object:
4860 * @domain: an app domain
4861 * @assembly: an assembly
4863 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4865 MonoReflectionAssembly*
4866 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4868 static MonoClass *System_Reflection_Assembly;
4869 MonoReflectionAssembly *res;
4871 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4872 if (!System_Reflection_Assembly)
4873 System_Reflection_Assembly = mono_class_from_name (
4874 mono_defaults.corlib, "System.Reflection", "Assembly");
4875 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4876 res->assembly = assembly;
4877 CACHE_OBJECT (assembly, res, NULL);
4883 MonoReflectionModule*
4884 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4886 static MonoClass *System_Reflection_Module;
4887 MonoReflectionModule *res;
4889 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4890 if (!System_Reflection_Module)
4891 System_Reflection_Module = mono_class_from_name (
4892 mono_defaults.corlib, "System.Reflection", "Module");
4893 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4896 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4898 res->fqname = mono_string_new (domain, image->name);
4899 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4900 res->scopename = mono_string_new (domain, image->module_name);
4902 mono_image_addref (image);
4904 CACHE_OBJECT (image, res, NULL);
4908 MonoReflectionModule*
4909 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4911 static MonoClass *System_Reflection_Module;
4912 MonoReflectionModule *res;
4913 MonoTableInfo *table;
4914 guint32 cols [MONO_FILE_SIZE];
4916 guint32 i, name_idx;
4919 if (!System_Reflection_Module)
4920 System_Reflection_Module = mono_class_from_name (
4921 mono_defaults.corlib, "System.Reflection", "Module");
4922 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4924 table = &image->tables [MONO_TABLE_FILE];
4925 g_assert (table_index < table->rows);
4926 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4929 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4930 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4932 // Check whenever the row has a corresponding row in the moduleref table
4933 table = &image->tables [MONO_TABLE_MODULEREF];
4934 for (i = 0; i < table->rows; ++i) {
4935 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4936 val = mono_metadata_string_heap (image, name_idx);
4937 if (strcmp (val, name) == 0)
4938 res->image = image->modules [i];
4941 res->fqname = mono_string_new (domain, name);
4942 res->name = mono_string_new (domain, name);
4943 res->scopename = mono_string_new (domain, name);
4944 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4950 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4952 if ((t1->type != t2->type) ||
4953 (t1->byref != t2->byref))
4957 case MONO_TYPE_VOID:
4958 case MONO_TYPE_BOOLEAN:
4959 case MONO_TYPE_CHAR:
4970 case MONO_TYPE_STRING:
4973 case MONO_TYPE_OBJECT:
4974 case MONO_TYPE_TYPEDBYREF:
4976 case MONO_TYPE_VALUETYPE:
4977 case MONO_TYPE_CLASS:
4978 case MONO_TYPE_SZARRAY:
4979 return t1->data.klass == t2->data.klass;
4981 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4982 case MONO_TYPE_ARRAY:
4983 if (t1->data.array->rank != t2->data.array->rank)
4985 return t1->data.array->eklass == t2->data.array->eklass;
4986 case MONO_TYPE_GENERICINST: {
4988 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4990 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4992 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4993 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4999 case MONO_TYPE_MVAR:
5000 return t1->data.generic_param == t2->data.generic_param;
5002 g_error ("implement type compare for %0x!", t1->type);
5010 mymono_metadata_type_hash (MonoType *t1)
5016 hash |= t1->byref << 6; /* do not collide with t1->type values */
5018 case MONO_TYPE_VALUETYPE:
5019 case MONO_TYPE_CLASS:
5020 case MONO_TYPE_SZARRAY:
5021 /* check if the distribution is good enough */
5022 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5024 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5029 static MonoReflectionGenericInst*
5030 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5032 static MonoClass *System_Reflection_MonoGenericInst;
5033 MonoReflectionGenericInst *res;
5034 MonoGenericInst *ginst;
5037 if (!System_Reflection_MonoGenericInst) {
5038 System_Reflection_MonoGenericInst = mono_class_from_name (
5039 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5040 g_assert (System_Reflection_MonoGenericInst);
5043 ginst = geninst->data.generic_inst;
5044 gklass = mono_class_from_mono_type (ginst->generic_type);
5046 mono_class_init (ginst->klass);
5048 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5050 res->type.type = geninst;
5051 if (gklass->wastypebuilder && gklass->reflection_info)
5052 res->generic_type = gklass->reflection_info;
5054 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5060 * mono_type_get_object:
5061 * @domain: an app domain
5064 * Return an System.MonoType object representing the type @type.
5067 mono_type_get_object (MonoDomain *domain, MonoType *type)
5069 MonoReflectionType *res;
5070 MonoClass *klass = mono_class_from_mono_type (type);
5072 mono_domain_lock (domain);
5073 if (!domain->type_hash)
5074 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5075 (GCompareFunc)mymono_metadata_type_equal);
5076 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5077 mono_domain_unlock (domain);
5080 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5081 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5082 mono_g_hash_table_insert (domain->type_hash, type, res);
5083 mono_domain_unlock (domain);
5086 if (klass->reflection_info && !klass->wastypebuilder) {
5087 //g_assert_not_reached ();
5088 /* should this be considered an error condition? */
5090 mono_domain_unlock (domain);
5091 return klass->reflection_info;
5094 mono_class_init (klass);
5095 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5097 mono_g_hash_table_insert (domain->type_hash, type, res);
5098 mono_domain_unlock (domain);
5103 * mono_method_get_object:
5104 * @domain: an app domain
5106 * @refclass: the reflected type (can be NULL)
5108 * Return an System.Reflection.MonoMethod object representing the method @method.
5110 MonoReflectionMethod*
5111 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5114 * We use the same C representation for methods and constructors, but the type
5115 * name in C# is different.
5119 MonoReflectionMethod *ret;
5122 refclass = method->klass;
5124 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5125 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5126 cname = "MonoCMethod";
5128 cname = "MonoMethod";
5129 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5131 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5132 ret->method = method;
5133 ret->name = mono_string_new (domain, method->name);
5134 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5135 CACHE_OBJECT (method, ret, refclass);
5140 * mono_field_get_object:
5141 * @domain: an app domain
5145 * Return an System.Reflection.MonoField object representing the field @field
5148 MonoReflectionField*
5149 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5151 MonoReflectionField *res;
5154 CHECK_OBJECT (MonoReflectionField *, field, klass);
5155 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5156 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5159 res->name = mono_string_new (domain, field->name);
5160 res->attrs = field->type->attrs;
5161 res->type = mono_type_get_object (domain, field->type);
5162 CACHE_OBJECT (field, res, klass);
5167 * mono_property_get_object:
5168 * @domain: an app domain
5170 * @property: a property
5172 * Return an System.Reflection.MonoProperty object representing the property @property
5175 MonoReflectionProperty*
5176 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5178 MonoReflectionProperty *res;
5181 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5182 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5183 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5185 res->property = property;
5186 CACHE_OBJECT (property, res, klass);
5191 * mono_event_get_object:
5192 * @domain: an app domain
5196 * Return an System.Reflection.MonoEvent object representing the event @event
5199 MonoReflectionEvent*
5200 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5202 MonoReflectionEvent *res;
5205 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5206 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5207 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5210 CACHE_OBJECT (event, res, klass);
5215 * mono_param_get_objects:
5216 * @domain: an app domain
5219 * Return an System.Reflection.ParameterInfo array object representing the parameters
5220 * in the method @method.
5223 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5225 static MonoClass *System_Reflection_ParameterInfo;
5226 MonoArray *res = NULL;
5227 MonoReflectionMethod *member = NULL;
5228 MonoReflectionParameter *param = NULL;
5232 if (!System_Reflection_ParameterInfo)
5233 System_Reflection_ParameterInfo = mono_class_from_name (
5234 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5236 if (!method->signature->param_count)
5237 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5239 /* Note: the cache is based on the address of the signature into the method
5240 * since we already cache MethodInfos with the method as keys.
5242 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5244 member = mono_method_get_object (domain, method, NULL);
5245 names = g_new (char *, method->signature->param_count);
5246 mono_method_get_param_names (method, (const char **) names);
5248 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5249 for (i = 0; i < method->signature->param_count; ++i) {
5250 param = (MonoReflectionParameter *)mono_object_new (domain,
5251 System_Reflection_ParameterInfo);
5252 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5253 param->DefaultValueImpl = NULL; /* FIXME */
5254 param->MemberImpl = (MonoObject*)member;
5255 param->NameImpl = mono_string_new (domain, names [i]);
5256 param->PositionImpl = i;
5257 param->AttrsImpl = method->signature->params [i]->attrs;
5258 mono_array_set (res, gpointer, i, param);
5261 CACHE_OBJECT (&(method->signature), res, NULL);
5266 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5270 memset (assembly, 0, sizeof (MonoAssemblyName));
5272 assembly->culture = "";
5273 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5275 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5278 while (*p == ' ' || *p == ',') {
5287 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5289 assembly->major = strtoul (p, &s, 10);
5290 if (s == p || *s != '.')
5293 assembly->minor = strtoul (p, &s, 10);
5294 if (s == p || *s != '.')
5297 assembly->build = strtoul (p, &s, 10);
5298 if (s == p || *s != '.')
5301 assembly->revision = strtoul (p, &s, 10);
5305 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5307 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5308 assembly->culture = "";
5311 assembly->culture = p;
5312 while (*p && *p != ',') {
5316 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5318 if (strncmp (p, "null", 4) == 0) {
5323 while (*p && *p != ',') {
5326 len = (p - start + 1);
5327 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5328 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5329 g_strlcpy (assembly->public_key_token, start, len);
5332 while (*p && *p != ',')
5336 while (*p == ' ' || *p == ',') {
5350 * mono_reflection_parse_type:
5353 * Parse a type name as accepted by the GetType () method and output the info
5354 * extracted in the info structure.
5355 * the name param will be mangled, so, make a copy before passing it to this function.
5356 * The fields in info will be valid until the memory pointed to by name is valid.
5357 * Returns 0 on parse error.
5358 * See also mono_type_get_name () below.
5361 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5363 char *start, *p, *w, *last_point, *startn;
5364 int in_modifiers = 0;
5365 int isbyref = 0, rank;
5367 start = p = w = name;
5369 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5370 info->name = info->name_space = NULL;
5371 info->nested = NULL;
5372 info->modifiers = NULL;
5374 /* last_point separates the namespace from the name */
5380 *p = 0; /* NULL terminate the name */
5382 info->nested = g_list_append (info->nested, startn);
5383 /* we have parsed the nesting namespace + name */
5387 info->name_space = start;
5389 info->name = last_point + 1;
5391 info->name_space = (char *)"";
5417 info->name_space = start;
5419 info->name = last_point + 1;
5421 info->name_space = (char *)"";
5428 if (isbyref) /* only one level allowed by the spec */
5431 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5435 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5446 else if (*p != '*') /* '*' means unknown lower bound */
5452 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5464 return 0; /* missing assembly name */
5465 if (!assembly_name_to_aname (&info->assembly, p))
5472 if (info->assembly.name)
5475 *w = 0; /* terminate class name */
5476 if (!info->name || !*info->name)
5478 /* add other consistency checks */
5483 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5490 image = mono_defaults.corlib;
5493 klass = mono_class_from_name_case (image, info->name_space, info->name);
5495 klass = mono_class_from_name (image, info->name_space, info->name);
5498 for (mod = info->nested; mod; mod = mod->next) {
5501 mono_class_init (klass);
5502 nested = klass->nested_classes;
5505 klass = nested->data;
5507 if (g_strcasecmp (klass->name, mod->data) == 0)
5510 if (strcmp (klass->name, mod->data) == 0)
5514 nested = nested->next;
5521 mono_class_init (klass);
5522 for (mod = info->modifiers; mod; mod = mod->next) {
5523 modval = GPOINTER_TO_UINT (mod->data);
5524 if (!modval) { /* byref: must be last modifier */
5525 return &klass->this_arg;
5526 } else if (modval == -1) {
5527 klass = mono_ptr_class_get (&klass->byval_arg);
5528 } else { /* array rank */
5529 klass = mono_array_class_get (klass, modval);
5531 mono_class_init (klass);
5534 return &klass->byval_arg;
5538 * mono_reflection_get_type:
5539 * @image: a metadata context
5540 * @info: type description structure
5541 * @ignorecase: flag for case-insensitive string compares
5543 * Build a MonoType from the type description in @info.
5548 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5551 MonoReflectionAssembly *assembly;
5555 type = mono_reflection_get_type_internal (image, info, ignorecase);
5558 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5561 // Reconstruct the type name
5562 fullName = g_string_new ("");
5563 if (info->name_space && (info->name_space [0] != '\0'))
5564 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5566 g_string_printf (fullName, info->name);
5567 for (mod = info->nested; mod; mod = mod->next)
5568 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5571 mono_domain_try_type_resolve (
5572 mono_domain_get (), fullName->str, NULL);
5573 if (assembly && (!image || (assembly->assembly->image == image))) {
5575 if (assembly->assembly->dynamic) {
5576 /* Enumerate all modules */
5577 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5581 if (abuilder->modules) {
5582 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5583 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5584 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5590 if (!type && abuilder->loaded_modules) {
5591 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5592 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5593 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5600 type = mono_reflection_get_type_internal (assembly->assembly->image,
5603 g_string_free (fullName, TRUE);
5608 * mono_reflection_type_from_name:
5610 * @image: a metadata context (can be NULL).
5612 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5613 * it defaults to get the type from @image or, if @image is NULL or loading
5614 * from it fails, uses corlib.
5618 mono_reflection_type_from_name (char *name, MonoImage *image)
5621 MonoTypeNameParse info;
5622 MonoAssembly *assembly;
5625 /* Make a copy since parse_type modifies its argument */
5626 tmp = g_strdup (name);
5628 /*g_print ("requested type %s\n", str);*/
5629 if (!mono_reflection_parse_type (tmp, &info)) {
5631 g_list_free (info.modifiers);
5632 g_list_free (info.nested);
5636 if (info.assembly.name) {
5637 assembly = mono_assembly_loaded (&info.assembly);
5639 /* then we must load the assembly ourselve - see #60439 */
5640 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5643 g_list_free (info.modifiers);
5644 g_list_free (info.nested);
5648 image = assembly->image;
5649 } else if (image == NULL) {
5650 image = mono_defaults.corlib;
5653 type = mono_reflection_get_type (image, &info, FALSE);
5654 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5655 image = mono_defaults.corlib;
5656 type = mono_reflection_get_type (image, &info, FALSE);
5660 g_list_free (info.modifiers);
5661 g_list_free (info.nested);
5666 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5668 int slen, type = t->type;
5673 case MONO_TYPE_BOOLEAN: {
5674 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5679 case MONO_TYPE_CHAR:
5681 case MONO_TYPE_I2: {
5682 guint16 *val = g_malloc (sizeof (guint16));
5687 #if SIZEOF_VOID_P == 4
5693 case MONO_TYPE_I4: {
5694 guint32 *val = g_malloc (sizeof (guint32));
5699 #if SIZEOF_VOID_P == 8
5700 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5705 case MONO_TYPE_I8: {
5706 guint64 *val = g_malloc (sizeof (guint64));
5711 case MONO_TYPE_VALUETYPE:
5712 if (t->data.klass->enumtype) {
5713 type = t->data.klass->enum_basetype->type;
5716 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5719 case MONO_TYPE_STRING:
5720 if (*p == (char)0xFF) {
5724 slen = mono_metadata_decode_value (p, &p);
5726 return mono_string_new_len (mono_domain_get (), p, slen);
5727 case MONO_TYPE_CLASS: {
5730 if (*p == (char)0xFF) {
5735 slen = mono_metadata_decode_value (p, &p);
5736 n = g_memdup (p, slen + 1);
5738 t = mono_reflection_type_from_name (n, image);
5740 g_warning ("Cannot load type '%s'", n);
5744 return mono_type_get_object (mono_domain_get (), t);
5748 case MONO_TYPE_OBJECT: {
5751 MonoClass *subc = NULL;
5756 } else if (subt == 0x0E) {
5757 type = MONO_TYPE_STRING;
5759 } else if (subt == 0x55) {
5762 slen = mono_metadata_decode_value (p, &p);
5763 n = g_memdup (p, slen + 1);
5765 t = mono_reflection_type_from_name (n, image);
5767 g_warning ("Cannot load type '%s'", n);
5770 subc = mono_class_from_mono_type (t);
5771 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5772 MonoType simple_type = {{0}};
5773 simple_type.type = subt;
5774 subc = mono_class_from_mono_type (&simple_type);
5776 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5778 val = load_cattr_value (image, &subc->byval_arg, p, end);
5779 obj = mono_object_new (mono_domain_get (), subc);
5780 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5784 case MONO_TYPE_SZARRAY:
5787 guint32 i, alen, basetype;
5790 if (alen == 0xffffffff) {
5794 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5795 basetype = t->data.klass->byval_arg.type;
5800 case MONO_TYPE_BOOLEAN:
5801 for (i=0;i<alen;i++)
5803 MonoBoolean val=*p++;
5804 mono_array_set(arr,MonoBoolean,i,val);
5807 case MONO_TYPE_CHAR:
5810 for (i=0;i<alen;i++)
5812 guint16 val=read16(p);
5813 mono_array_set(arr,guint16,i,val);
5820 for (i=0;i<alen;i++)
5822 guint32 val=read32(p);
5823 mono_array_set(arr,guint32,i,val);
5830 for (i=0;i<alen;i++)
5832 guint64 val=read64(p);
5833 mono_array_set(arr,guint64,i,val);
5837 case MONO_TYPE_CLASS:
5838 case MONO_TYPE_STRING:
5839 for (i = 0; i < alen; i++) {
5840 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5841 mono_array_set (arr, gpointer, i, item);
5845 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5851 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5857 type_is_reference (MonoType *type)
5859 switch (type->type) {
5860 case MONO_TYPE_BOOLEAN:
5861 case MONO_TYPE_CHAR:
5874 case MONO_TYPE_VALUETYPE:
5882 free_param_data (MonoMethodSignature *sig, void **params) {
5884 for (i = 0; i < sig->param_count; ++i) {
5885 if (!type_is_reference (sig->params [i]))
5886 g_free (params [i]);
5891 * Find the method index in the metadata methodDef table.
5892 * Later put these three helper methods in metadata and export them.
5895 find_method_index (MonoMethod *method) {
5896 MonoClass *klass = method->klass;
5899 for (i = 0; i < klass->method.count; ++i) {
5900 if (method == klass->methods [i])
5901 return klass->method.first + 1 + i;
5907 * Find the field index in the metadata FieldDef table.
5910 find_field_index (MonoClass *klass, MonoClassField *field) {
5913 for (i = 0; i < klass->field.count; ++i) {
5914 if (field == &klass->fields [i])
5915 return klass->field.first + 1 + i;
5921 * Find the property index in the metadata Property table.
5924 find_property_index (MonoClass *klass, MonoProperty *property) {
5927 for (i = 0; i < klass->property.count; ++i) {
5928 if (property == &klass->properties [i])
5929 return klass->property.first + 1 + i;
5935 * Find the event index in the metadata Event table.
5938 find_event_index (MonoClass *klass, MonoEvent *event) {
5941 for (i = 0; i < klass->event.count; ++i) {
5942 if (event == &klass->events [i])
5943 return klass->event.first + 1 + i;
5949 create_custom_attr (MonoImage *image, MonoMethod *method,
5950 const char *data, guint32 len)
5952 const char *p = data;
5954 guint32 i, j, num_named;
5958 mono_class_init (method->klass);
5961 attr = mono_object_new (mono_domain_get (), method->klass);
5962 mono_runtime_invoke (method, attr, NULL, NULL);
5966 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5969 /*g_print ("got attr %s\n", method->klass->name);*/
5971 params = g_new (void*, method->signature->param_count);
5975 for (i = 0; i < method->signature->param_count; ++i) {
5976 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5980 attr = mono_object_new (mono_domain_get (), method->klass);
5981 mono_runtime_invoke (method, attr, params, NULL);
5982 free_param_data (method->signature, params);
5984 num_named = read16 (named);
5986 for (j = 0; j < num_named; j++) {
5988 char *name, named_type, data_type;
5989 named_type = *named++;
5990 data_type = *named++; /* type of data */
5991 if (data_type == 0x55) {
5994 type_len = mono_metadata_decode_blob_size (named, &named);
5995 type_name = g_malloc (type_len + 1);
5996 memcpy (type_name, named, type_len);
5997 type_name [type_len] = 0;
5999 /* FIXME: lookup the type and check type consistency */
6002 if (data_type == MONO_TYPE_SZARRAY)
6003 /* The spec does not mention this */
6005 name_len = mono_metadata_decode_blob_size (named, &named);
6006 name = g_malloc (name_len + 1);
6007 memcpy (name, named, name_len);
6008 name [name_len] = 0;
6010 if (named_type == 0x53) {
6011 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6012 void *val = load_cattr_value (image, field->type, named, &named);
6013 mono_field_set_value (attr, field, val);
6014 if (!type_is_reference (field->type))
6016 } else if (named_type == 0x54) {
6019 MonoType *prop_type;
6021 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6022 /* can we have more that 1 arg in a custom attr named property? */
6023 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6024 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6025 mono_property_set_value (prop, attr, pparams, NULL);
6026 if (!type_is_reference (prop_type))
6027 g_free (pparams [0]);
6036 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6043 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6044 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6045 for (i = 0; i < cinfo->num_attrs; ++i) {
6046 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6047 mono_array_set (result, gpointer, i, attr);
6053 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6055 guint32 mtoken, i, len;
6056 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6058 MonoCustomAttrInfo *ainfo;
6059 GList *tmp, *list = NULL;
6062 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6064 i = mono_metadata_custom_attrs_from_index (image, idx);
6068 while (i < ca->rows) {
6069 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6071 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6074 len = g_list_length (list);
6077 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6078 ainfo->num_attrs = len;
6079 ainfo->image = image;
6080 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6081 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6082 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6083 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6084 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6085 mtoken |= MONO_TOKEN_METHOD_DEF;
6087 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6088 mtoken |= MONO_TOKEN_MEMBER_REF;
6091 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6094 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6095 if (!ainfo->attrs [i].ctor)
6096 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6097 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6098 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6099 ainfo->attrs [i].data = data;
6107 mono_custom_attrs_from_method (MonoMethod *method)
6109 MonoCustomAttrInfo *cinfo;
6112 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6114 idx = find_method_index (method);
6115 idx <<= MONO_CUSTOM_ATTR_BITS;
6116 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6117 return mono_custom_attrs_from_index (method->klass->image, idx);
6121 mono_custom_attrs_from_class (MonoClass *klass)
6123 MonoCustomAttrInfo *cinfo;
6126 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6128 idx = mono_metadata_token_index (klass->type_token);
6129 idx <<= MONO_CUSTOM_ATTR_BITS;
6130 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6131 return mono_custom_attrs_from_index (klass->image, idx);
6135 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6137 MonoCustomAttrInfo *cinfo;
6140 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6142 idx = 1; /* there is only one assembly */
6143 idx <<= MONO_CUSTOM_ATTR_BITS;
6144 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6145 return mono_custom_attrs_from_index (assembly->image, idx);
6148 static MonoCustomAttrInfo*
6149 mono_custom_attrs_from_module (MonoImage *image)
6151 MonoCustomAttrInfo *cinfo;
6154 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6156 idx = 1; /* there is only one module */
6157 idx <<= MONO_CUSTOM_ATTR_BITS;
6158 idx |= MONO_CUSTOM_ATTR_MODULE;
6159 return mono_custom_attrs_from_index (image, idx);
6163 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6165 MonoCustomAttrInfo *cinfo;
6168 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6170 idx = find_property_index (klass, property);
6171 idx <<= MONO_CUSTOM_ATTR_BITS;
6172 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6173 return mono_custom_attrs_from_index (klass->image, idx);
6177 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6179 MonoCustomAttrInfo *cinfo;
6182 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6184 idx = find_event_index (klass, event);
6185 idx <<= MONO_CUSTOM_ATTR_BITS;
6186 idx |= MONO_CUSTOM_ATTR_EVENT;
6187 return mono_custom_attrs_from_index (klass->image, idx);
6191 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6193 MonoCustomAttrInfo *cinfo;
6196 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6198 idx = find_field_index (klass, field);
6199 idx <<= MONO_CUSTOM_ATTR_BITS;
6200 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6201 return mono_custom_attrs_from_index (klass->image, idx);
6205 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6208 guint32 i, idx, method_index;
6209 guint32 param_list, param_last, param_pos, found;
6211 MonoReflectionMethodAux *aux;
6213 if (method->klass->image->dynamic) {
6214 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6215 if (!aux || !aux->param_cattr)
6217 return aux->param_cattr [param];
6220 image = method->klass->image;
6221 method_index = find_method_index (method);
6222 ca = &image->tables [MONO_TABLE_METHOD];
6224 if (method->klass->generic_inst || method->klass->gen_params ||
6225 method->signature->generic_param_count) {
6226 // FIXME FIXME FIXME
6230 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6231 if (method_index == ca->rows) {
6232 ca = &image->tables [MONO_TABLE_PARAM];
6233 param_last = ca->rows + 1;
6235 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6236 ca = &image->tables [MONO_TABLE_PARAM];
6239 for (i = param_list; i < param_last; ++i) {
6240 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6241 if (param_pos == param) {
6249 idx <<= MONO_CUSTOM_ATTR_BITS;
6250 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6251 return mono_custom_attrs_from_index (image, idx);
6255 * mono_reflection_get_custom_attrs:
6256 * @obj: a reflection object handle
6258 * Return an array with all the custom attributes defined of the
6259 * reflection handle @obj. The objects are fully build.
6262 mono_reflection_get_custom_attrs (MonoObject *obj)
6266 MonoCustomAttrInfo *cinfo = NULL;
6268 MONO_ARCH_SAVE_REGS;
6270 klass = obj->vtable->klass;
6271 /* FIXME: need to handle: Module */
6272 if (klass == mono_defaults.monotype_class) {
6273 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6274 klass = mono_class_from_mono_type (rtype->type);
6275 cinfo = mono_custom_attrs_from_class (klass);
6276 } else if (strcmp ("Assembly", klass->name) == 0) {
6277 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6278 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6279 } else if (strcmp ("Module", klass->name) == 0) {
6280 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6281 cinfo = mono_custom_attrs_from_module (module->image);
6282 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6283 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6284 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6285 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6286 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6287 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6288 } else if (strcmp ("MonoField", klass->name) == 0) {
6289 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6290 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6291 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6292 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6293 cinfo = mono_custom_attrs_from_method (rmethod->method);
6294 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6295 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6296 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6297 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6298 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6299 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6300 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6301 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6302 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6303 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6304 } else { /* handle other types here... */
6305 g_error ("get custom attrs not yet supported for %s", klass->name);
6309 result = mono_custom_attrs_construct (cinfo);
6311 mono_custom_attrs_free (cinfo);
6313 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6314 result = mono_array_new (mono_domain_get (), klass, 0);
6320 static MonoMethodSignature*
6321 parameters_to_signature (MonoArray *parameters) {
6322 MonoMethodSignature *sig;
6325 count = parameters? mono_array_length (parameters): 0;
6327 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6328 sig->param_count = count;
6329 sig->sentinelpos = -1; /* FIXME */
6330 for (i = 0; i < count; ++i) {
6331 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6332 sig->params [i] = pt->type;
6337 static MonoMethodSignature*
6338 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6339 MonoMethodSignature *sig;
6341 sig = parameters_to_signature (ctor->parameters);
6342 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6343 sig->ret = &mono_defaults.void_class->byval_arg;
6347 static MonoMethodSignature*
6348 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6349 MonoMethodSignature *sig;
6351 sig = parameters_to_signature (method->parameters);
6352 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6353 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6354 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6358 static MonoMethodSignature*
6359 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6360 MonoMethodSignature *sig;
6362 sig = parameters_to_signature (method->parameters);
6363 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6364 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6365 sig->generic_param_count = 0;
6370 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6372 MonoClass *klass = mono_object_class (prop);
6373 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6374 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6375 *name = mono_string_to_utf8 (pb->name);
6376 *type = pb->type->type;
6378 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6379 *name = g_strdup (p->property->name);
6380 if (p->property->get)
6381 *type = p->property->get->signature->ret;
6383 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6388 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6390 MonoClass *klass = mono_object_class (field);
6391 if (strcmp (klass->name, "FieldBuilder") == 0) {
6392 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6393 *name = mono_string_to_utf8 (fb->name);
6394 *type = fb->type->type;
6396 MonoReflectionField *f = (MonoReflectionField *)field;
6397 *name = g_strdup (f->field->name);
6398 *type = f->field->type;
6403 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6406 MonoTypeEnum simple_type;
6408 if ((p-buffer) + 10 >= *buflen) {
6411 newbuf = g_realloc (buffer, *buflen);
6412 p = newbuf + (p-buffer);
6415 argval = ((char*)arg + sizeof (MonoObject));
6416 simple_type = type->type;
6418 switch (simple_type) {
6419 case MONO_TYPE_BOOLEAN:
6424 case MONO_TYPE_CHAR:
6427 swap_with_size (p, argval, 2, 1);
6433 swap_with_size (p, argval, 4, 1);
6439 swap_with_size (p, argval, 8, 1);
6442 case MONO_TYPE_VALUETYPE:
6443 if (type->data.klass->enumtype) {
6444 simple_type = type->data.klass->enum_basetype->type;
6447 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6450 case MONO_TYPE_STRING: {
6457 str = mono_string_to_utf8 ((MonoString*)arg);
6458 slen = strlen (str);
6459 if ((p-buffer) + 10 + slen >= *buflen) {
6463 newbuf = g_realloc (buffer, *buflen);
6464 p = newbuf + (p-buffer);
6467 mono_metadata_encode_value (slen, p, &p);
6468 memcpy (p, str, slen);
6473 case MONO_TYPE_CLASS: {
6481 k = mono_object_class (arg);
6482 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6483 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6484 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6486 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6487 slen = strlen (str);
6488 if ((p-buffer) + 10 + slen >= *buflen) {
6492 newbuf = g_realloc (buffer, *buflen);
6493 p = newbuf + (p-buffer);
6496 mono_metadata_encode_value (slen, p, &p);
6497 memcpy (p, str, slen);
6502 case MONO_TYPE_SZARRAY: {
6507 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6510 len = mono_array_length ((MonoArray*)arg);
6512 *p++ = (len >> 8) & 0xff;
6513 *p++ = (len >> 16) & 0xff;
6514 *p++ = (len >> 24) & 0xff;
6516 *retbuffer = buffer;
6517 eclass = type->data.klass;
6518 for (i = 0; i < len; ++i) {
6519 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6523 /* it may be a boxed value or a Type */
6524 case MONO_TYPE_OBJECT: {
6525 MonoClass *klass = mono_object_class (arg);
6529 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6532 } else if (klass->enumtype) {
6534 } else if (klass == mono_defaults.string_class) {
6535 simple_type = MONO_TYPE_STRING;
6538 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6539 *p++ = simple_type = klass->byval_arg.type;
6542 g_error ("unhandled type in custom attr");
6544 str = type_get_qualified_name (klass->enum_basetype, NULL);
6545 slen = strlen (str);
6546 if ((p-buffer) + 10 + slen >= *buflen) {
6550 newbuf = g_realloc (buffer, *buflen);
6551 p = newbuf + (p-buffer);
6554 mono_metadata_encode_value (slen, p, &p);
6555 memcpy (p, str, slen);
6558 simple_type = klass->enum_basetype->type;
6562 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6565 *retbuffer = buffer;
6569 * mono_reflection_get_custom_attrs_blob:
6570 * @ctor: custom attribute constructor
6571 * @ctorArgs: arguments o the constructor
6577 * Creates the blob of data that needs to be saved in the metadata and that represents
6578 * the custom attributed described by @ctor, @ctorArgs etc.
6579 * Returns: a Byte array representing the blob of data.
6582 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6585 MonoMethodSignature *sig;
6590 MONO_ARCH_SAVE_REGS;
6592 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6593 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6595 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6597 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6599 p = buffer = g_malloc (buflen);
6600 /* write the prolog */
6603 for (i = 0; i < sig->param_count; ++i) {
6604 arg = mono_array_get (ctorArgs, MonoObject*, i);
6605 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6609 i += mono_array_length (properties);
6611 i += mono_array_length (fields);
6613 *p++ = (i >> 8) & 0xff;
6616 for (i = 0; i < mono_array_length (properties); ++i) {
6621 prop = mono_array_get (properties, gpointer, i);
6622 get_prop_name_and_type (prop, &pname, &ptype);
6623 *p++ = 0x54; /* PROPERTY signature */
6625 /* Preallocate a large enough buffer */
6626 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6627 char *str = type_get_qualified_name (ptype, NULL);
6633 len += strlen (pname);
6635 if ((p-buffer) + 20 + len >= buflen) {
6639 newbuf = g_realloc (buffer, buflen);
6640 p = newbuf + (p-buffer);
6644 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6645 char *str = type_get_qualified_name (ptype, NULL);
6646 int slen = strlen (str);
6650 * This seems to be optional...
6653 mono_metadata_encode_value (slen, p, &p);
6654 memcpy (p, str, slen);
6658 mono_metadata_encode_value (ptype->type, p, &p);
6659 if (ptype->type == MONO_TYPE_SZARRAY)
6660 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6662 len = strlen (pname);
6663 mono_metadata_encode_value (len, p, &p);
6664 memcpy (p, pname, len);
6666 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6673 for (i = 0; i < mono_array_length (fields); ++i) {
6678 field = mono_array_get (fields, gpointer, i);
6679 get_field_name_and_type (field, &fname, &ftype);
6680 *p++ = 0x53; /* FIELD signature */
6681 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6682 char *str = type_get_qualified_name (ftype, NULL);
6683 int slen = strlen (str);
6684 if ((p-buffer) + 10 + slen >= buflen) {
6688 newbuf = g_realloc (buffer, buflen);
6689 p = newbuf + (p-buffer);
6694 * This seems to be optional...
6697 mono_metadata_encode_value (slen, p, &p);
6698 memcpy (p, str, slen);
6702 mono_metadata_encode_value (ftype->type, p, &p);
6704 len = strlen (fname);
6705 mono_metadata_encode_value (len, p, &p);
6706 memcpy (p, fname, len);
6708 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6713 g_assert (p - buffer <= buflen);
6714 buflen = p - buffer;
6715 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6716 p = mono_array_addr (result, char, 0);
6717 memcpy (p, buffer, buflen);
6719 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6725 * mono_reflection_setup_internal_class:
6726 * @tb: a TypeBuilder object
6728 * Creates a MonoClass that represents the TypeBuilder.
6729 * This is a trick that lets us simplify a lot of reflection code
6730 * (and will allow us to support Build and Run assemblies easier).
6733 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6735 MonoClass *klass, *parent;
6737 MONO_ARCH_SAVE_REGS;
6740 /* check so we can compile corlib correctly */
6741 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6742 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6743 parent = tb->parent->type->data.klass;
6745 parent = my_mono_class_from_mono_type (tb->parent->type);
6749 /* the type has already being created: it means we just have to change the parent */
6750 if (tb->type.type) {
6751 klass = mono_class_from_mono_type (tb->type.type);
6752 klass->parent = NULL;
6753 /* fool mono_class_setup_parent */
6754 g_free (klass->supertypes);
6755 klass->supertypes = NULL;
6756 mono_class_setup_parent (klass, parent);
6760 klass = g_new0 (MonoClass, 1);
6762 klass->image = &tb->module->dynamic_image->image;
6764 klass->inited = 1; /* we lie to the runtime */
6765 klass->name = mono_string_to_utf8 (tb->name);
6766 klass->name_space = mono_string_to_utf8 (tb->nspace);
6767 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6768 klass->flags = tb->attrs;
6770 klass->element_class = klass;
6771 klass->reflection_info = tb; /* need to pin. */
6773 /* Put into cache so mono_class_get () will find it */
6774 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6777 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6778 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6782 mono_class_setup_parent (klass, parent);
6783 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6784 const char *old_n = klass->name;
6785 /* trick to get relative numbering right when compiling corlib */
6786 klass->name = "BuildingObject";
6787 mono_class_setup_parent (klass, mono_defaults.object_class);
6788 klass->name = old_n;
6790 mono_class_setup_mono_type (klass);
6792 mono_class_setup_supertypes (klass);
6795 * FIXME: handle interfaces.
6798 tb->type.type = &klass->byval_arg;
6800 if (tb->nesting_type) {
6801 g_assert (tb->nesting_type->type);
6802 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6805 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6809 * mono_reflection_setup_generic_class:
6810 * @tb: a TypeBuilder object
6812 * Setup the generic class after all generic parameters have been added.
6815 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6820 MONO_ARCH_SAVE_REGS;
6822 klass = my_mono_class_from_mono_type (tb->type.type);
6824 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6826 if (klass->gen_params || (count == 0))
6829 klass->num_gen_params = count;
6830 klass->gen_params = g_new0 (MonoGenericParam, count);
6832 for (i = 0; i < count; i++) {
6833 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6834 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6839 * mono_reflection_create_internal_class:
6840 * @tb: a TypeBuilder object
6842 * Actually create the MonoClass that is associated with the TypeBuilder.
6845 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6849 MONO_ARCH_SAVE_REGS;
6851 klass = my_mono_class_from_mono_type (tb->type.type);
6853 if (klass->enumtype && klass->enum_basetype == NULL) {
6854 MonoReflectionFieldBuilder *fb;
6856 g_assert (tb->fields != NULL);
6857 g_assert (mono_array_length (tb->fields) >= 1);
6859 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6861 klass->enum_basetype = fb->type->type;
6862 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6863 if (!klass->element_class)
6864 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6865 klass->instance_size = klass->element_class->instance_size;
6866 klass->size_inited = 1;
6868 * this is almost safe to do with enums and it's needed to be able
6869 * to create objects of the enum type (for use in SetConstant).
6871 /* FIXME: Does this mean enums can't have method overrides ? */
6872 mono_class_setup_vtable (klass, NULL, 0);
6876 static MonoMarshalSpec*
6877 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6878 MonoReflectionMarshal *minfo)
6880 MonoMarshalSpec *res;
6882 res = g_new0 (MonoMarshalSpec, 1);
6883 res->native = minfo->type;
6885 switch (minfo->type) {
6886 case MONO_NATIVE_LPARRAY:
6887 res->data.array_data.elem_type = minfo->eltype;
6888 res->data.array_data.param_num = 0; /* Not yet */
6889 res->data.array_data.num_elem = minfo->count;
6892 case MONO_NATIVE_BYVALTSTR:
6893 case MONO_NATIVE_BYVALARRAY:
6894 res->data.array_data.num_elem = minfo->count;
6897 case MONO_NATIVE_CUSTOM:
6898 if (minfo->marshaltyperef)
6899 res->data.custom_data.custom_name =
6900 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6902 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6913 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6914 ReflectionMethodBuilder *rmb,
6915 MonoMethodSignature *sig)
6918 MonoMethodNormal *pm;
6919 MonoMarshalSpec **specs;
6920 MonoReflectionMethodAux *method_aux;
6923 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6924 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6925 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6928 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6930 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6932 pm = (MonoMethodNormal*)m;
6935 m->flags = rmb->attrs;
6936 m->iflags = rmb->iattrs;
6937 m->name = mono_string_to_utf8 (rmb->name);
6941 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6943 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6944 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6947 m->signature->pinvoke = 1;
6948 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6950 m->signature->pinvoke = 1;
6952 } else if (!m->klass->dummy &&
6953 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6954 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6955 MonoMethodHeader *header;
6957 gint32 max_stack, i;
6958 gint32 num_locals = 0;
6959 gint32 num_clauses = 0;
6963 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6964 code_size = rmb->ilgen->code_len;
6965 max_stack = rmb->ilgen->max_stack;
6966 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6967 if (rmb->ilgen->ex_handlers)
6968 num_clauses = method_count_clauses (rmb->ilgen);
6971 code = mono_array_addr (rmb->code, guint8, 0);
6972 code_size = mono_array_length (rmb->code);
6973 /* we probably need to run a verifier on the code... */
6983 header = g_malloc0 (sizeof (MonoMethodHeader) +
6984 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6985 header->code_size = code_size;
6986 header->code = g_malloc (code_size);
6987 memcpy ((char*)header->code, code, code_size);
6988 header->max_stack = max_stack;
6989 header->init_locals = rmb->init_locals;
6990 header->num_locals = num_locals;
6992 for (i = 0; i < num_locals; ++i) {
6993 MonoReflectionLocalBuilder *lb =
6994 mono_array_get (rmb->ilgen->locals,
6995 MonoReflectionLocalBuilder*, i);
6997 header->locals [i] = g_new0 (MonoType, 1);
6998 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7001 header->num_clauses = num_clauses;
7003 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7008 if (rmb->generic_params) {
7009 int count = mono_array_length (rmb->generic_params);
7010 header->gen_params = g_new0 (MonoGenericParam, count);
7011 for (i = 0; i < count; i++) {
7012 MonoReflectionGenericParam *gp =
7013 mono_array_get (rmb->generic_params,
7014 MonoReflectionGenericParam*, i);
7016 header->gen_params [i] = *gp->type.type->data.generic_param;
7020 pm->header = header;
7024 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7027 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7029 for (i = 0; i < rmb->nrefs; ++i)
7030 mw->data = g_list_append (mw->data, rmb->refs [i]);
7035 /* Parameter names */
7038 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7039 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7040 for (i = 0; i <= m->signature->param_count; ++i) {
7041 MonoReflectionParamBuilder *pb;
7042 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7044 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7046 if (!method_aux->param_cattr)
7047 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7048 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7054 /* Parameter marshalling */
7057 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7058 MonoReflectionParamBuilder *pb;
7059 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7060 if (pb->marshal_info) {
7062 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7063 specs [pb->position] =
7064 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7068 if (specs != NULL) {
7070 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7071 method_aux->param_marshall = specs;
7074 if (klass->image->dynamic && method_aux)
7075 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7081 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7083 ReflectionMethodBuilder rmb;
7084 MonoMethodSignature *sig;
7086 sig = ctor_builder_to_signature (mb);
7088 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7090 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7091 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7093 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7094 /* ilgen is no longer needed */
7102 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7104 ReflectionMethodBuilder rmb;
7105 MonoMethodSignature *sig;
7107 sig = method_builder_to_signature (mb);
7109 reflection_methodbuilder_from_method_builder (&rmb, mb);
7111 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7112 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7114 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7115 /* ilgen is no longer needed */
7121 static MonoClassField*
7122 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7124 MonoClassField *field;
7131 field = g_new0 (MonoClassField, 1);
7133 field->name = mono_string_to_utf8 (fb->name);
7135 /* FIXME: handle type modifiers */
7136 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7137 field->type->attrs = fb->attrs;
7139 field->type = fb->type->type;
7141 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7142 field->data = mono_array_addr (fb->rva_data, char, 0);
7143 if (fb->offset != -1)
7144 field->offset = fb->offset;
7145 field->parent = klass;
7147 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7149 if (fb->def_value) {
7150 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7151 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7152 field->def_value = g_new0 (MonoConstant, 1);
7153 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7154 /* Copy the data from the blob since it might get realloc-ed */
7155 p = assembly->blob.data + idx;
7156 len = mono_metadata_decode_blob_size (p, &p2);
7158 field->def_value->value = g_malloc (len);
7159 memcpy (field->def_value->value, p, len);
7166 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7170 MonoReflectionTypeBuilder *tb = NULL;
7171 MonoGenericInst *ginst;
7176 klass = mono_class_from_mono_type (type->type);
7177 if (!klass->gen_params && !klass->generic_inst &&
7178 !(klass->nested_in && klass->nested_in->gen_params))
7181 mono_loader_lock ();
7183 domain = mono_object_domain (type);
7185 ginst = g_new0 (MonoGenericInst, 1);
7187 if (!klass->generic_inst) {
7188 ginst->type_argc = type_argc;
7189 ginst->type_argv = types;
7191 for (i = 0; i < ginst->type_argc; ++i) {
7192 if (!ginst->is_open)
7193 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7196 ginst->generic_type = &klass->byval_arg;
7198 MonoGenericInst *kginst = klass->generic_inst;
7200 ginst->type_argc = kginst->type_argc;
7201 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7203 for (i = 0; i < ginst->type_argc; i++) {
7204 MonoType *t = kginst->type_argv [i];
7206 if (t->type == MONO_TYPE_VAR)
7207 t = types [t->data.generic_param->num];
7209 if (!ginst->is_open)
7210 ginst->is_open = mono_class_is_open_constructed_type (t);
7212 ginst->type_argv [i] = t;
7215 ginst->generic_type = kginst->generic_type;
7218 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7221 mono_loader_unlock ();
7225 ginst->context = g_new0 (MonoGenericContext, 1);
7226 ginst->context->ginst = ginst;
7228 geninst = g_new0 (MonoType, 1);
7229 geninst->type = MONO_TYPE_GENERICINST;
7230 geninst->data.generic_inst = ginst;
7232 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7233 tb = (MonoReflectionTypeBuilder *) type;
7235 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7236 ginst->is_dynamic = TRUE;
7237 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7238 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7239 MonoReflectionType *rgt = rgi->generic_type;
7241 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7242 tb = (MonoReflectionTypeBuilder *) rgt;
7244 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7245 ginst->is_dynamic = TRUE;
7247 icount = klass->interface_count;
7249 ginst->ifaces = g_new0 (MonoType *, icount);
7250 ginst->count_ifaces = icount;
7252 for (i = 0; i < icount; i++) {
7253 MonoReflectionType *itype;
7256 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7258 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7259 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7260 if (!ginst->ifaces [i])
7261 ginst->ifaces [i] = itype->type;
7264 mono_class_create_generic (ginst);
7266 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7268 mono_loader_unlock ();
7274 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7276 MonoClass *klass, *pklass = NULL;
7277 MonoReflectionType *parent = NULL;
7279 MonoReflectionTypeBuilder *tb = NULL;
7280 MonoGenericInst *ginst;
7283 domain = mono_object_domain (type);
7284 klass = mono_class_from_mono_type (type->type);
7286 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7287 tb = (MonoReflectionTypeBuilder *) type;
7290 parent = tb->parent;
7291 pklass = mono_class_from_mono_type (parent->type);
7294 pklass = klass->parent;
7296 parent = mono_type_get_object (domain, &pklass->byval_arg);
7299 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7303 ginst = geninst->data.generic_inst;
7305 if (pklass && pklass->generic_inst)
7306 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7311 MonoReflectionMethod*
7312 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7314 MonoMethod *method, *inflated;
7315 MonoReflectionMethodBuilder *mb = NULL;
7316 MonoGenericMethod *gmethod;
7317 MonoGenericContext *context;
7320 MONO_ARCH_SAVE_REGS;
7321 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7322 MonoReflectionTypeBuilder *tb;
7325 mb = (MonoReflectionMethodBuilder *) rmethod;
7326 tb = (MonoReflectionTypeBuilder *) mb->type;
7327 klass = mono_class_from_mono_type (tb->type.type);
7329 method = methodbuilder_to_mono_method (klass, mb);
7331 method = rmethod->method;
7333 count = method->signature->generic_param_count;
7334 if (count != mono_array_length (types))
7337 gmethod = g_new0 (MonoGenericMethod, 1);
7338 gmethod->mtype_argc = count;
7339 gmethod->mtype_argv = g_new0 (MonoType *, count);
7340 for (i = 0; i < count; i++) {
7341 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7342 gmethod->mtype_argv [i] = garg->type;
7345 context = g_new0 (MonoGenericContext, 1);
7346 context->ginst = method->klass->generic_inst;
7347 context->gmethod = gmethod;
7349 inflated = mono_class_inflate_generic_method (method, context, NULL);
7351 return mono_method_get_object (
7352 mono_object_domain (rmethod), inflated, NULL);
7356 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7358 MonoGenericMethod *gmethod;
7359 MonoGenericInst *ginst;
7360 MonoGenericContext *context;
7363 ginst = type->type.type->data.generic_inst;
7365 gmethod = g_new0 (MonoGenericMethod, 1);
7366 gmethod->reflection_info = obj;
7368 gmethod->mtype_argc = method->signature->generic_param_count;
7369 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7371 for (i = 0; i < gmethod->mtype_argc; i++) {
7372 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7373 MonoGenericParam *gparam = &mn->header->gen_params [i];
7375 g_assert (gparam->pklass);
7376 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7379 context = g_new0 (MonoGenericContext, 1);
7380 context->ginst = ginst;
7381 context->gmethod = gmethod;
7383 return mono_class_inflate_generic_method (method, context, ginst->klass);
7387 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7392 klass = mono_class_from_mono_type (type->type.type);
7394 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7395 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7396 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7397 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7398 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7399 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7400 method = ((MonoReflectionMethod *) obj)->method;
7402 method = NULL; /* prevent compiler warning */
7403 g_assert_not_reached ();
7406 return inflate_mono_method (type, method, obj);
7410 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7411 MonoArray *methods, MonoArray *ctors,
7412 MonoArray *fields, MonoArray *properties,
7415 MonoGenericInst *ginst;
7416 MonoDynamicGenericInst *dginst;
7417 MonoClass *klass, *gklass, *pklass;
7420 MONO_ARCH_SAVE_REGS;
7422 klass = mono_class_from_mono_type (type->type.type);
7423 ginst = type->type.type->data.generic_inst;
7425 if (ginst->initialized)
7428 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7430 gklass = mono_class_from_mono_type (ginst->generic_type);
7431 mono_class_init (gklass);
7434 pklass = mono_class_from_mono_type (ginst->parent);
7436 pklass = gklass->parent;
7438 mono_class_setup_parent (klass, pklass);
7440 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7441 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7442 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7443 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7444 dginst->count_events = events ? mono_array_length (events) : 0;
7446 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7447 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7448 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7449 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7450 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7452 for (i = 0; i < dginst->count_methods; i++) {
7453 MonoObject *obj = mono_array_get (methods, gpointer, i);
7455 dginst->methods [i] = inflate_method (type, obj);
7458 for (i = 0; i < dginst->count_ctors; i++) {
7459 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7461 dginst->ctors [i] = inflate_method (type, obj);
7464 for (i = 0; i < dginst->count_fields; i++) {
7465 MonoObject *obj = mono_array_get (fields, gpointer, i);
7466 MonoClassField *field;
7467 MonoInflatedField *ifield;
7469 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7470 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7471 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7472 field = ((MonoReflectionField *) obj)->field;
7474 field = NULL; /* prevent compiler warning */
7475 g_assert_not_reached ();
7478 ifield = g_new0 (MonoInflatedField, 1);
7479 ifield->generic_type = field->type;
7480 ifield->reflection_info = obj;
7482 dginst->fields [i] = *field;
7483 dginst->fields [i].generic_info = ifield;
7484 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7487 for (i = 0; i < dginst->count_properties; i++) {
7488 MonoObject *obj = mono_array_get (properties, gpointer, i);
7489 MonoProperty *property = &dginst->properties [i];
7491 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7492 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7494 property->parent = klass;
7495 property->attrs = pb->attrs;
7496 property->name = mono_string_to_utf8 (pb->name);
7498 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7500 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7501 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7502 *property = *((MonoReflectionProperty *) obj)->property;
7505 property->get = inflate_mono_method (type, property->get, NULL);
7507 property->set = inflate_mono_method (type, property->set, NULL);
7509 g_assert_not_reached ();
7512 for (i = 0; i < dginst->count_events; i++) {
7513 MonoObject *obj = mono_array_get (events, gpointer, i);
7514 MonoEvent *event = &dginst->events [i];
7516 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7517 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7519 event->parent = klass;
7520 event->attrs = eb->attrs;
7521 event->name = mono_string_to_utf8 (eb->name);
7523 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7524 if (eb->remove_method)
7525 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7526 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7527 *event = *((MonoReflectionEvent *) obj)->event;
7530 event->add = inflate_mono_method (type, event->add, NULL);
7532 event->remove = inflate_mono_method (type, event->remove, NULL);
7534 g_assert_not_reached ();
7537 ginst->initialized = TRUE;
7541 ensure_runtime_vtable (MonoClass *klass)
7543 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7544 int i, num, j, onum;
7545 MonoMethod **overrides;
7547 if (!tb || klass->wastypebuilder)
7550 ensure_runtime_vtable (klass->parent);
7552 num = tb->ctors? mono_array_length (tb->ctors): 0;
7553 num += tb->num_methods;
7554 klass->method.count = num;
7555 klass->methods = g_new (MonoMethod*, num);
7556 num = tb->ctors? mono_array_length (tb->ctors): 0;
7557 for (i = 0; i < num; ++i)
7558 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7559 num = tb->num_methods;
7561 for (i = 0; i < num; ++i)
7562 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7564 klass->wastypebuilder = TRUE;
7565 if (tb->interfaces) {
7566 klass->interface_count = mono_array_length (tb->interfaces);
7567 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7568 for (i = 0; i < klass->interface_count; ++i) {
7569 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7570 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7574 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7575 for (i = 0; i < klass->method.count; ++i)
7576 klass->methods [i]->slot = i;
7581 for (i = 0; i < tb->num_methods; ++i) {
7582 MonoReflectionMethodBuilder *mb =
7583 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7584 if (mb->override_method)
7589 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7593 for (i = 0; i < tb->num_methods; ++i) {
7594 MonoReflectionMethodBuilder *mb =
7595 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7596 if (mb->override_method) {
7597 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7598 overrides [onum * 2] =
7599 mb->override_method->method;
7600 overrides [onum * 2 + 1] =
7603 g_assert (mb->mhandle);
7610 mono_class_setup_vtable (klass, overrides, onum);
7614 typebuilder_setup_fields (MonoClass *klass)
7616 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7617 MonoReflectionFieldBuilder *fb;
7618 MonoClassField *field;
7623 klass->field.count = tb->num_fields;
7624 klass->field.first = 0;
7625 klass->field.last = klass->field.count;
7627 if (!klass->field.count)
7630 klass->fields = g_new0 (MonoClassField, klass->field.count);
7632 for (i = 0; i < klass->field.count; ++i) {
7633 fb = mono_array_get (tb->fields, gpointer, i);
7634 field = &klass->fields [i];
7635 field->name = mono_string_to_utf8 (fb->name);
7637 /* FIXME: handle type modifiers */
7638 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7639 field->type->attrs = fb->attrs;
7641 field->type = fb->type->type;
7643 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7644 field->data = mono_array_addr (fb->rva_data, char, 0);
7645 if (fb->offset != -1)
7646 field->offset = fb->offset;
7647 field->parent = klass;
7649 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7651 if (fb->def_value) {
7652 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7653 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7654 field->def_value = g_new0 (MonoConstant, 1);
7655 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7656 /* Copy the data from the blob since it might get realloc-ed */
7657 p = assembly->blob.data + idx;
7658 len = mono_metadata_decode_blob_size (p, &p2);
7660 field->def_value->value = g_malloc (len);
7661 memcpy (field->def_value->value, p, len);
7664 mono_class_layout_fields (klass);
7668 typebuilder_setup_properties (MonoClass *klass)
7670 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7671 MonoReflectionPropertyBuilder *pb;
7674 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7675 klass->property.first = 0;
7676 klass->property.last = klass->property.count;
7678 klass->properties = g_new0 (MonoProperty, klass->property.count);
7679 for (i = 0; i < klass->property.count; ++i) {
7680 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7681 klass->properties [i].parent = klass;
7682 klass->properties [i].attrs = pb->attrs;
7683 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7685 klass->properties [i].get = pb->get_method->mhandle;
7687 klass->properties [i].set = pb->set_method->mhandle;
7691 MonoReflectionEvent *
7692 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7694 MonoEvent *event = g_new0 (MonoEvent, 1);
7698 klass = my_mono_class_from_mono_type (tb->type.type);
7700 event->parent = klass;
7701 event->attrs = eb->attrs;
7702 event->name = mono_string_to_utf8 (eb->name);
7704 event->add = eb->add_method->mhandle;
7705 if (eb->remove_method)
7706 event->remove = eb->remove_method->mhandle;
7707 if (eb->raise_method)
7708 event->raise = eb->raise_method->mhandle;
7710 if (eb->other_methods) {
7711 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7712 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7713 MonoReflectionMethodBuilder *mb =
7714 mono_array_get (eb->other_methods,
7715 MonoReflectionMethodBuilder*, j);
7716 event->other [j] = mb->mhandle;
7720 return mono_event_get_object (mono_object_domain (tb), klass, event);
7724 typebuilder_setup_events (MonoClass *klass)
7726 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7727 MonoReflectionEventBuilder *eb;
7730 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7731 klass->event.first = 0;
7732 klass->event.last = klass->event.count;
7734 klass->events = g_new0 (MonoEvent, klass->event.count);
7735 for (i = 0; i < klass->event.count; ++i) {
7736 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7737 klass->events [i].parent = klass;
7738 klass->events [i].attrs = eb->attrs;
7739 klass->events [i].name = mono_string_to_utf8 (eb->name);
7741 klass->events [i].add = eb->add_method->mhandle;
7742 if (eb->remove_method)
7743 klass->events [i].remove = eb->remove_method->mhandle;
7744 if (eb->raise_method)
7745 klass->events [i].raise = eb->raise_method->mhandle;
7747 if (eb->other_methods) {
7748 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7749 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7750 MonoReflectionMethodBuilder *mb =
7751 mono_array_get (eb->other_methods,
7752 MonoReflectionMethodBuilder*, j);
7753 klass->events [i].other [j] = mb->mhandle;
7760 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7763 MonoReflectionType* res;
7765 MONO_ARCH_SAVE_REGS;
7767 klass = my_mono_class_from_mono_type (tb->type.type);
7769 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7772 * Fields to set in klass:
7773 * the various flags: delegate/unicode/contextbound etc.
7776 klass->flags = tb->attrs;
7778 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7779 /* No need to fully construct the type */
7780 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7782 /* enums are done right away */
7783 if (!klass->enumtype)
7784 ensure_runtime_vtable (klass);
7786 /* fields and object layout */
7787 if (klass->parent) {
7788 if (!klass->parent->size_inited)
7789 mono_class_init (klass->parent);
7790 klass->instance_size += klass->parent->instance_size;
7791 klass->class_size += klass->parent->class_size;
7792 klass->min_align = klass->parent->min_align;
7794 klass->instance_size = sizeof (MonoObject);
7795 klass->min_align = 1;
7798 /* FIXME: handle packing_size and instance_size */
7799 typebuilder_setup_fields (klass);
7801 typebuilder_setup_properties (klass);
7803 typebuilder_setup_events (klass);
7805 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7806 /* with enums res == tb: need to fix that. */
7807 if (!klass->enumtype)
7808 g_assert (res != (MonoReflectionType*)tb);
7813 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7815 MonoGenericParam *param;
7818 MONO_ARCH_SAVE_REGS;
7820 param = g_new0 (MonoGenericParam, 1);
7822 param->method = NULL;
7823 param->name = mono_string_to_utf8 (gparam->name);
7824 param->num = gparam->index;
7826 image = &gparam->tbuilder->module->dynamic_image->image;
7827 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7829 param->pklass->reflection_info = gparam;
7831 gparam->type.type = g_new0 (MonoType, 1);
7832 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7833 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7834 gparam->type.type->data.generic_param = param;
7838 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7840 MonoDynamicImage *assembly = sig->module->dynamic_image;
7841 guint32 na = mono_array_length (sig->arguments);
7846 MONO_ARCH_SAVE_REGS;
7848 p = buf = g_malloc (10 + na * 10);
7850 mono_metadata_encode_value (0x07, p, &p);
7851 mono_metadata_encode_value (na, p, &p);
7852 for (i = 0; i < na; ++i) {
7853 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7854 encode_reflection_type (assembly, type, p, &p);
7858 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7859 p = mono_array_addr (result, char, 0);
7860 memcpy (p, buf, buflen);
7867 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7869 MonoDynamicImage *assembly = sig->module->dynamic_image;
7870 guint32 na = mono_array_length (sig->arguments);
7875 MONO_ARCH_SAVE_REGS;
7877 p = buf = g_malloc (10 + na * 10);
7879 mono_metadata_encode_value (0x06, p, &p);
7880 for (i = 0; i < na; ++i) {
7881 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7882 encode_reflection_type (assembly, type, p, &p);
7886 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7887 p = mono_array_addr (result, char, 0);
7888 memcpy (p, buf, buflen);
7895 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7897 ReflectionMethodBuilder rmb;
7898 MonoMethodSignature *sig;
7901 sig = dynamic_method_to_signature (mb);
7903 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7906 * Resolve references.
7908 rmb.nrefs = mb->nrefs;
7909 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7910 for (i = 0; i < mb->nrefs; ++i) {
7911 gpointer ref = resolve_object (mb->module->image,
7912 mono_array_get (mb->refs, MonoObject*, i));
7915 mono_raise_exception (mono_get_exception_type_load (NULL));
7922 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7926 /* ilgen is no longer needed */
7931 * mono_reflection_lookup_dynamic_token:
7933 * Finish the Builder object pointed to by TOKEN and return the corresponding
7934 * runtime structure.
7937 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7939 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7942 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7945 return resolve_object (image, obj);
7949 resolve_object (MonoImage *image, MonoObject *obj)
7951 gpointer result = NULL;
7953 if (strcmp (obj->vtable->klass->name, "String") == 0) {
7954 result = mono_string_intern ((MonoString*)obj);
7957 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7958 MonoReflectionType *tb = (MonoReflectionType*)obj;
7959 result = mono_class_from_mono_type (tb->type);
7962 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7963 result = ((MonoReflectionMethod*)obj)->method;
7966 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7967 result = ((MonoReflectionMethod*)obj)->method;
7970 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7971 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7972 result = mb->mhandle;
7974 /* Type is not yet created */
7975 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7977 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7980 * Hopefully this has been filled in by calling CreateType() on the
7984 * TODO: This won't work if the application finishes another
7985 * TypeBuilder instance instead of this one.
7987 result = mb->mhandle;
7990 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7991 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7993 result = cb->mhandle;
7995 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7997 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7998 result = cb->mhandle;
8001 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8002 result = ((MonoReflectionField*)obj)->field;
8005 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8006 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8007 result = fb->handle;
8010 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8012 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8013 result = fb->handle;
8016 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8017 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8020 klass = tb->type.type->data.klass;
8021 if (klass->wastypebuilder) {
8022 /* Already created */
8026 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8027 result = tb->type.type->data.klass;
8031 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8032 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8033 MonoMethodSignature *sig;
8036 if (helper->arguments)
8037 nargs = mono_array_length (helper->arguments);
8041 sig = mono_metadata_signature_alloc (image, nargs);
8042 sig->explicit_this = helper->call_conv & 64;
8043 sig->hasthis = helper->call_conv & 32;
8045 if (helper->call_conv == 0) /* unmanaged */
8046 sig->call_convention = helper->unmanaged_call_conv - 1;
8048 if (helper->call_conv & 0x02)
8049 sig->call_convention = MONO_CALL_VARARG;
8051 sig->call_convention = MONO_CALL_DEFAULT;
8053 sig->param_count = nargs;
8054 /* TODO: Copy type ? */
8055 sig->ret = helper->return_type->type;
8056 for (i = 0; i < nargs; ++i) {
8057 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8058 sig->params [i] = rt->type;
8064 g_print (obj->vtable->klass->name);
8065 g_assert_not_reached ();