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;
65 int charset, lasterr, native_cc;
66 MonoString *dll, *dllentry;
67 } ReflectionMethodBuilder;
69 const unsigned char table_sizes [64] = {
79 MONO_INTERFACEIMPL_SIZE,
80 MONO_MEMBERREF_SIZE, /* 0x0A */
82 MONO_CUSTOM_ATTR_SIZE,
83 MONO_FIELD_MARSHAL_SIZE,
84 MONO_DECL_SECURITY_SIZE,
85 MONO_CLASS_LAYOUT_SIZE,
86 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
87 MONO_STAND_ALONE_SIGNATURE_SIZE,
91 MONO_PROPERTY_MAP_SIZE,
94 MONO_METHOD_SEMA_SIZE,
96 MONO_MODULEREF_SIZE, /* 0x1A */
102 MONO_ASSEMBLY_SIZE, /* 0x20 */
103 MONO_ASSEMBLY_PROCESSOR_SIZE,
104 MONO_ASSEMBLYOS_SIZE,
105 MONO_ASSEMBLYREF_SIZE,
106 MONO_ASSEMBLYREFPROC_SIZE,
107 MONO_ASSEMBLYREFOS_SIZE,
111 MONO_NESTED_CLASS_SIZE,
113 MONO_GENERICPARAM_SIZE, /* 0x2A */
114 MONO_METHODSPEC_SIZE,
115 MONO_GENPARCONSTRAINT_SIZE,
121 * These macros can be used to allocate long living atomic data so it won't be
122 * tracked by the garbage collector. We use libgc because it's apparently faster
126 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
127 #define FREE_ATOMIC(ptr)
128 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
130 #define ALLOC_ATOMIC(size) g_malloc (size)
131 #define FREE_ATOMIC(ptr) g_free (ptr)
132 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
135 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
136 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
137 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
138 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
139 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
140 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
141 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
142 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
143 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
144 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
145 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
146 static void ensure_runtime_vtable (MonoClass *klass);
147 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
148 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
149 static guint32 type_get_signature_size (MonoType *type);
153 alloc_table (MonoDynamicTable *table, guint nrows)
156 g_assert (table->columns);
157 if (nrows + 1 >= table->alloc_rows) {
158 while (nrows + 1 >= table->alloc_rows)
159 if (table->alloc_rows == 0)
160 table->alloc_rows = 16;
162 table->alloc_rows *= 2;
165 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
167 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
172 make_room_in_stream (MonoDynamicStream *stream, int size)
174 while (stream->alloc_size <= size) {
175 if (stream->alloc_size < 4096)
176 stream->alloc_size = 4096;
178 stream->alloc_size *= 2;
181 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
183 stream->data = ALLOC_ATOMIC (stream->alloc_size);
187 string_heap_insert (MonoDynamicStream *sh, const char *str)
191 gpointer oldkey, oldval;
193 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
194 return GPOINTER_TO_UINT (oldval);
196 len = strlen (str) + 1;
198 if (idx + len > sh->alloc_size)
199 make_room_in_stream (sh, idx + len);
202 * We strdup the string even if we already copy them in sh->data
203 * so that the string pointers in the hash remain valid even if
204 * we need to realloc sh->data. We may want to avoid that later.
206 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
207 memcpy (sh->data + idx, str, len);
213 string_heap_init (MonoDynamicStream *sh)
216 sh->alloc_size = 4096;
217 sh->data = ALLOC_ATOMIC (4096);
218 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
219 string_heap_insert (sh, "");
222 #if 0 /* never used */
224 string_heap_free (MonoDynamicStream *sh)
226 FREE_ATOMIC (sh->data);
227 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
228 g_hash_table_destroy (sh->hash);
233 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
236 if (stream->alloc_size < stream->index + len)
237 make_room_in_stream (stream, stream->index + len);
238 memcpy (stream->data + stream->index, data, len);
240 stream->index += len;
242 * align index? Not without adding an additional param that controls it since
243 * we may store a blob value in pieces.
249 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
252 if (stream->alloc_size < stream->index + len)
253 make_room_in_stream (stream, stream->index + len);
254 memset (stream->data + stream->index, 0, len);
256 stream->index += len;
261 stream_data_align (MonoDynamicStream *stream)
264 guint32 count = stream->index % 4;
266 /* we assume the stream data will be aligned */
268 mono_image_add_stream_data (stream, buf, 4 - count);
272 mono_blob_entry_hash (const char* str)
276 len = mono_metadata_decode_blob_size (str, &str);
280 for (str += 1; str < end; str++)
281 h = (h << 5) - h + *str;
289 mono_blob_entry_equal (const char *str1, const char *str2) {
293 len = mono_metadata_decode_blob_size (str1, &end1);
294 len2 = mono_metadata_decode_blob_size (str2, &end2);
297 return memcmp (end1, end2, len) == 0;
301 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
305 gpointer oldkey, oldval;
307 copy = ALLOC_ATOMIC (s1+s2);
308 memcpy (copy, b1, s1);
309 memcpy (copy + s1, b2, s2);
310 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
312 idx = GPOINTER_TO_UINT (oldval);
314 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
315 mono_image_add_stream_data (&assembly->blob, b2, s2);
316 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
322 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
323 * dest may be misaligned.
326 swap_with_size (char *dest, const char* val, int len, int nelem) {
327 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
330 for (elem = 0; elem < nelem; ++elem) {
356 g_assert_not_reached ();
362 memcpy (dest, val, len * nelem);
367 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
371 guint32 idx = 0, len;
373 len = str->length * 2;
374 mono_metadata_encode_value (len, b, &b);
375 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
377 char *swapped = g_malloc (2 * mono_string_length (str));
378 const char *p = (const char*)mono_string_chars (str);
380 swap_with_size (swapped, p, 2, mono_string_length (str));
381 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
385 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
390 /* modified version needed to handle building corlib */
392 my_mono_class_from_mono_type (MonoType *type) {
393 switch (type->type) {
394 case MONO_TYPE_ARRAY:
396 case MONO_TYPE_SZARRAY:
397 case MONO_TYPE_GENERICINST:
398 return mono_class_from_mono_type (type);
401 g_assert (type->data.generic_param->pklass);
402 return type->data.generic_param->pklass;
404 /* should be always valid when we reach this case... */
405 return type->data.klass;
410 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
415 g_assert_not_reached ();
419 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
420 encode_type (assembly, ginst->generic_type, p, &p);
421 mono_metadata_encode_value (ginst->type_argc, p, &p);
422 for (i = 0; i < ginst->type_argc; ++i)
423 encode_type (assembly, ginst->type_argv [i], p, &p);
429 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
432 g_assert_not_reached ();
437 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
441 case MONO_TYPE_BOOLEAN:
455 case MONO_TYPE_STRING:
456 case MONO_TYPE_OBJECT:
457 case MONO_TYPE_TYPEDBYREF:
458 mono_metadata_encode_value (type->type, p, &p);
461 mono_metadata_encode_value (type->type, p, &p);
462 encode_type (assembly, type->data.type, p, &p);
464 case MONO_TYPE_SZARRAY:
465 mono_metadata_encode_value (type->type, p, &p);
466 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
469 case MONO_TYPE_VALUETYPE:
470 case MONO_TYPE_CLASS: {
471 MonoClass *k = mono_class_from_mono_type (type);
472 mono_metadata_encode_value (type->type, p, &p);
474 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
475 * otherwise two typerefs could point to the same type, leading to
476 * verification errors.
478 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
482 case MONO_TYPE_ARRAY:
483 mono_metadata_encode_value (type->type, p, &p);
484 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
485 mono_metadata_encode_value (type->data.array->rank, p, &p);
486 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
487 mono_metadata_encode_value (0, p, &p);
489 case MONO_TYPE_GENERICINST:
490 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
494 mono_metadata_encode_value (type->type, p, &p);
495 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
499 g_error ("need to encode type %x", type->type);
505 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
508 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
512 encode_type (assembly, type->type, p, endbuf);
516 g_assert_not_reached ();
521 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
526 for (i = 0; i < mono_array_length (modreq); ++i) {
527 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
528 *p = MONO_TYPE_CMOD_REQD;
530 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
534 for (i = 0; i < mono_array_length (modopt); ++i) {
535 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
536 *p = MONO_TYPE_CMOD_OPT;
538 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
545 generic_inst_get_signature_size (MonoGenericInst *ginst)
551 g_assert_not_reached ();
554 size += 1 + type_get_signature_size (ginst->generic_type);
556 for (i = 0; i < ginst->type_argc; ++i)
557 size += type_get_signature_size (ginst->type_argv [i]);
563 type_get_signature_size (MonoType *type)
568 g_assert_not_reached ();
576 case MONO_TYPE_BOOLEAN:
590 case MONO_TYPE_STRING:
591 case MONO_TYPE_OBJECT:
592 case MONO_TYPE_TYPEDBYREF:
595 return size + 1 + type_get_signature_size (type->data.type);
596 case MONO_TYPE_SZARRAY:
597 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
599 case MONO_TYPE_VALUETYPE:
600 case MONO_TYPE_CLASS:
603 case MONO_TYPE_ARRAY:
604 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
605 case MONO_TYPE_GENERICINST:
606 return size + generic_inst_get_signature_size (type->data.generic_inst);
612 g_error ("need to encode type %x", type->type);
618 method_get_signature_size (MonoMethodSignature *sig)
623 size = type_get_signature_size (sig->ret);
624 for (i = 0; i < sig->param_count; i++)
625 size += type_get_signature_size (sig->params [i]);
627 if (sig->generic_param_count)
629 if (sig->sentinelpos >= 0)
636 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
641 guint32 nparams = sig->param_count;
642 guint32 size = 11 + method_get_signature_size (sig);
650 p = buf = g_malloc (size);
652 * FIXME: vararg, explicit_this, differenc call_conv values...
654 *p = sig->call_convention;
656 *p |= 0x20; /* hasthis */
657 if (sig->generic_param_count)
658 *p |= 0x10; /* generic */
660 if (sig->generic_param_count)
661 mono_metadata_encode_value (sig->generic_param_count, p, &p);
662 mono_metadata_encode_value (nparams, p, &p);
663 encode_type (assembly, sig->ret, p, &p);
664 for (i = 0; i < nparams; ++i) {
665 if (i == sig->sentinelpos)
666 *p++ = MONO_TYPE_SENTINEL;
667 encode_type (assembly, sig->params [i], p, &p);
670 g_assert (p - buf < size);
671 mono_metadata_encode_value (p-buf, b, &b);
672 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
678 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
681 * FIXME: reuse code from method_encode_signature().
686 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
687 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
688 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
689 guint32 size = 21 + nparams * 20 + notypes * 20;
694 p = buf = g_malloc (size);
695 /* LAMESPEC: all the call conv spec is foobared */
696 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
697 if (mb->call_conv & 2)
698 *p |= 0x5; /* vararg */
699 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
700 *p |= 0x20; /* hasthis */
702 *p |= 0x10; /* generic */
705 mono_metadata_encode_value (ngparams, p, &p);
706 mono_metadata_encode_value (nparams + notypes, p, &p);
707 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
708 encode_reflection_type (assembly, mb->rtype, p, &p);
709 for (i = 0; i < nparams; ++i) {
710 MonoArray *modreq = NULL;
711 MonoArray *modopt = NULL;
712 MonoReflectionType *pt;
714 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
715 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
716 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
717 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
718 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
719 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
720 encode_reflection_type (assembly, pt, p, &p);
723 *p++ = MONO_TYPE_SENTINEL;
724 for (i = 0; i < notypes; ++i) {
725 MonoReflectionType *pt;
727 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
728 encode_reflection_type (assembly, pt, p, &p);
732 g_assert (p - buf < size);
733 mono_metadata_encode_value (p-buf, b, &b);
734 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
740 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
742 MonoDynamicTable *table;
745 guint32 idx, sig_idx, size;
746 guint nl = mono_array_length (ilgen->locals);
753 p = buf = g_malloc (size);
754 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
755 idx = table->next_idx ++;
757 alloc_table (table, table->rows);
758 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
760 mono_metadata_encode_value (0x07, p, &p);
761 mono_metadata_encode_value (nl, p, &p);
762 for (i = 0; i < nl; ++i) {
763 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
766 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
768 encode_reflection_type (assembly, lb->type, p, &p);
770 g_assert (p - buf < size);
771 mono_metadata_encode_value (p-buf, b, &b);
772 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
775 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
781 method_count_clauses (MonoReflectionILGen *ilgen)
783 guint32 num_clauses = 0;
786 MonoILExceptionInfo *ex_info;
787 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
788 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
789 if (ex_info->handlers)
790 num_clauses += mono_array_length (ex_info->handlers);
798 static MonoExceptionClause*
799 method_encode_clauses (MonoDynamicImage *assembly,
800 MonoReflectionILGen *ilgen, guint32 num_clauses)
802 MonoExceptionClause *clauses;
803 MonoExceptionClause *clause;
804 MonoILExceptionInfo *ex_info;
805 MonoILExceptionBlock *ex_block;
806 guint32 finally_start;
807 int i, j, clause_index;;
809 clauses = g_new0 (MonoExceptionClause, num_clauses);
812 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
813 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
814 finally_start = ex_info->start + ex_info->len;
815 g_assert (ex_info->handlers);
816 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
817 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
818 clause = &(clauses [clause_index]);
820 clause->flags = ex_block->type;
821 clause->try_offset = ex_info->start;
823 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
824 clause->try_len = finally_start - ex_info->start;
826 clause->try_len = ex_info->len;
827 clause->handler_offset = ex_block->start;
828 clause->handler_len = ex_block->len;
829 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
830 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
831 if (ex_block->extype) {
832 mono_g_hash_table_insert (assembly->tokens,
833 GUINT_TO_POINTER (clause->token_or_filter),
836 finally_start = ex_block->start + ex_block->len;
846 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
852 gint32 num_locals = 0;
853 gint32 num_exception = 0;
856 char fat_header [12];
859 guint32 local_sig = 0;
860 guint32 header_size = 12;
863 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
864 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
865 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
866 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
870 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
872 code = mb->ilgen->code;
873 code_size = mb->ilgen->code_len;
874 max_stack = mb->ilgen->max_stack;
875 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
876 if (mb->ilgen->ex_handlers)
877 num_exception = method_count_clauses (mb->ilgen);
881 char *name = mono_string_to_utf8 (mb->name);
882 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
883 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
886 mono_raise_exception (exception);
889 code_size = mono_array_length (code);
890 max_stack = 8; /* we probably need to run a verifier on the code... */
893 stream_data_align (&assembly->code);
895 /* check for exceptions, maxstack, locals */
896 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
898 if (code_size < 64 && !(code_size & 1)) {
899 flags = (code_size << 2) | 0x2;
900 } else if (code_size < 32 && (code_size & 1)) {
901 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
905 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
906 /* add to the fixup todo list */
907 if (mb->ilgen && mb->ilgen->num_token_fixups)
908 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
909 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
910 return assembly->text_rva + idx;
914 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
916 * FIXME: need to set also the header size in fat_flags.
917 * (and more sects and init locals flags)
921 fat_flags |= METHOD_HEADER_MORE_SECTS;
923 fat_flags |= METHOD_HEADER_INIT_LOCALS;
924 fat_header [0] = fat_flags;
925 fat_header [1] = (header_size / 4 ) << 4;
926 shortp = (guint16*)(fat_header + 2);
927 *shortp = GUINT16_TO_LE (max_stack);
928 intp = (guint32*)(fat_header + 4);
929 *intp = GUINT32_TO_LE (code_size);
930 intp = (guint32*)(fat_header + 8);
931 *intp = GUINT32_TO_LE (local_sig);
932 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
933 /* add to the fixup todo list */
934 if (mb->ilgen && mb->ilgen->num_token_fixups)
935 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
937 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
939 unsigned char sheader [4];
940 MonoExceptionClause clause;
941 MonoILExceptionInfo * ex_info;
942 MonoILExceptionBlock * ex_block;
945 stream_data_align (&assembly->code);
946 /* always use fat format for now */
947 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
948 num_exception *= sizeof (MonoExceptionClause);
949 num_exception += 4; /* include the size of the header */
950 sheader [1] = num_exception & 0xff;
951 sheader [2] = (num_exception >> 8) & 0xff;
952 sheader [3] = (num_exception >> 16) & 0xff;
953 mono_image_add_stream_data (&assembly->code, sheader, 4);
954 /* fat header, so we are already aligned */
956 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
957 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
958 if (ex_info->handlers) {
959 int finally_start = ex_info->start + ex_info->len;
960 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
961 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
962 clause.flags = GUINT32_TO_LE (ex_block->type);
963 clause.try_offset = GUINT32_TO_LE (ex_info->start);
964 /* need fault, too, probably */
965 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
966 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
968 clause.try_len = GUINT32_TO_LE (ex_info->len);
969 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
970 clause.handler_len = GUINT32_TO_LE (ex_block->len);
971 finally_start = ex_block->start + ex_block->len;
972 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
973 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
974 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
975 /*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",
976 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);*/
977 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
980 g_error ("No clauses for ex info block %d", i);
984 return assembly->text_rva + idx;
988 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
991 MonoDynamicTable *table;
994 table = &assembly->tables [table_idx];
996 g_assert (col < table->columns);
998 values = table->values + table->columns;
999 for (i = 1; i <= table->rows; ++i) {
1000 if (values [col] == token)
1002 values += table->columns;
1007 static GHashTable *dynamic_custom_attrs = NULL;
1009 static MonoCustomAttrInfo*
1010 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1013 MonoCustomAttrInfo *ainfo;
1014 MonoReflectionCustomAttr *cattr;
1018 /* FIXME: check in assembly the Run flag is set */
1020 count = mono_array_length (cattrs);
1022 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1024 ainfo->image = image;
1025 ainfo->num_attrs = count;
1026 for (i = 0; i < count; ++i) {
1027 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1028 ainfo->attrs [i].ctor = cattr->ctor->method;
1029 /* FIXME: might want to memdup the data here */
1030 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1031 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1038 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1040 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1045 if (!dynamic_custom_attrs)
1046 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1048 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1049 ainfo->cached = TRUE;
1053 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1055 /* they are cached, so we don't free them */
1056 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1062 * idx is the table index of the object
1063 * type is one of MONO_CUSTOM_ATTR_*
1066 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1068 MonoDynamicTable *table;
1069 MonoReflectionCustomAttr *cattr;
1071 guint32 count, i, token;
1073 char *p = blob_size;
1075 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1078 count = mono_array_length (cattrs);
1079 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1080 table->rows += count;
1081 alloc_table (table, table->rows);
1082 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1083 idx <<= MONO_CUSTOM_ATTR_BITS;
1085 for (i = 0; i < count; ++i) {
1086 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1087 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1088 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
1089 type = mono_metadata_token_index (token);
1090 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1091 switch (mono_metadata_token_table (token)) {
1092 case MONO_TABLE_METHOD:
1093 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1095 case MONO_TABLE_MEMBERREF:
1096 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1099 g_warning ("got wrong token in custom attr");
1102 values [MONO_CUSTOM_ATTR_TYPE] = type;
1104 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1105 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1106 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1107 values += MONO_CUSTOM_ATTR_SIZE;
1113 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
1114 MonoArray *permissions)
1116 MonoDynamicTable *table;
1118 guint32 count, i, idx;
1119 MonoReflectionPermissionSet *perm;
1124 count = mono_array_length (permissions);
1125 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1126 table->rows += count;
1127 alloc_table (table, table->rows);
1129 for (i = 0; i < mono_array_length (permissions); ++i) {
1130 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1132 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1134 idx = mono_metadata_token_index (parent_token);
1135 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1136 switch (mono_metadata_token_table (parent_token)) {
1137 case MONO_TABLE_TYPEDEF:
1138 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1140 case MONO_TABLE_METHOD:
1141 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1143 case MONO_TABLE_ASSEMBLY:
1144 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1147 g_assert_not_reached ();
1150 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1151 values [MONO_DECL_SECURITY_PARENT] = idx;
1152 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1159 * Fill in the MethodDef and ParamDef tables for a method.
1160 * This is used for both normal methods and constructors.
1163 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1165 MonoDynamicTable *table;
1170 /* room in this table is already allocated */
1171 table = &assembly->tables [MONO_TABLE_METHOD];
1172 *mb->table_idx = table->next_idx ++;
1173 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1174 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1175 name = mono_string_to_utf8 (mb->name);
1176 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1178 values [MONO_METHOD_FLAGS] = mb->attrs;
1179 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1180 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1181 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1183 table = &assembly->tables [MONO_TABLE_PARAM];
1184 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1186 mono_image_add_decl_security (assembly,
1187 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1191 MonoDynamicTable *mtable;
1194 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1195 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1198 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1199 if (mono_array_get (mb->pinfo, gpointer, i))
1202 table->rows += count;
1203 alloc_table (table, table->rows);
1204 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1205 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1206 MonoReflectionParamBuilder *pb;
1207 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1208 values [MONO_PARAM_FLAGS] = pb->attrs;
1209 values [MONO_PARAM_SEQUENCE] = i;
1210 if (pb->name != NULL) {
1211 name = mono_string_to_utf8 (pb->name);
1212 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1215 values [MONO_PARAM_NAME] = 0;
1217 values += MONO_PARAM_SIZE;
1218 if (pb->marshal_info) {
1220 alloc_table (mtable, mtable->rows);
1221 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1222 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1223 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1225 pb->table_idx = table->next_idx++;
1226 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1227 guint32 field_type = 0;
1228 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1230 alloc_table (mtable, mtable->rows);
1231 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1232 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1233 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1234 mvalues [MONO_CONSTANT_TYPE] = field_type;
1235 mvalues [MONO_CONSTANT_PADDING] = 0;
1243 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1244 MonoReflectionMethodBuilder *mb)
1246 rmb->ilgen = mb->ilgen;
1247 rmb->rtype = mb->rtype;
1248 rmb->parameters = mb->parameters;
1249 rmb->generic_params = mb->generic_params;
1250 rmb->opt_types = NULL;
1251 rmb->pinfo = mb->pinfo;
1252 rmb->attrs = mb->attrs;
1253 rmb->iattrs = mb->iattrs;
1254 rmb->call_conv = mb->call_conv;
1255 rmb->code = mb->code;
1256 rmb->type = mb->type;
1257 rmb->name = mb->name;
1258 rmb->table_idx = &mb->table_idx;
1259 rmb->init_locals = mb->init_locals;
1260 rmb->return_modreq = mb->return_modreq;
1261 rmb->return_modopt = mb->return_modopt;
1262 rmb->param_modreq = mb->param_modreq;
1263 rmb->param_modopt = mb->param_modopt;
1264 rmb->permissions = mb->permissions;
1265 rmb->mhandle = mb->mhandle;
1270 rmb->charset = rmb->charset & 0xf;
1271 rmb->lasterr = rmb->charset & 0x40;
1272 rmb->native_cc = rmb->native_cc;
1273 rmb->dllentry = mb->dllentry;
1279 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1280 MonoReflectionCtorBuilder *mb)
1282 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1284 rmb->ilgen = mb->ilgen;
1285 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1286 rmb->parameters = mb->parameters;
1287 rmb->generic_params = NULL;
1288 rmb->opt_types = NULL;
1289 rmb->pinfo = mb->pinfo;
1290 rmb->attrs = mb->attrs;
1291 rmb->iattrs = mb->iattrs;
1292 rmb->call_conv = mb->call_conv;
1294 rmb->type = mb->type;
1295 rmb->name = mono_string_new (mono_domain_get (), name);
1296 rmb->table_idx = &mb->table_idx;
1297 rmb->init_locals = mb->init_locals;
1298 rmb->return_modreq = NULL;
1299 rmb->return_modopt = NULL;
1300 rmb->param_modreq = mb->param_modreq;
1301 rmb->param_modopt = mb->param_modopt;
1302 rmb->permissions = mb->permissions;
1303 rmb->mhandle = mb->mhandle;
1309 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1310 MonoReflectionDynamicMethod *mb)
1312 rmb->ilgen = mb->ilgen;
1313 rmb->rtype = mb->rtype;
1314 rmb->parameters = mb->parameters;
1315 rmb->generic_params = NULL;
1316 rmb->opt_types = NULL;
1318 rmb->attrs = mb->attrs;
1320 rmb->call_conv = mb->call_conv;
1323 rmb->name = mb->name;
1324 rmb->table_idx = NULL;
1325 rmb->init_locals = mb->init_locals;
1326 rmb->return_modreq = NULL;
1327 rmb->return_modopt = NULL;
1328 rmb->param_modreq = NULL;
1329 rmb->param_modopt = NULL;
1330 rmb->permissions = NULL;
1331 rmb->mhandle = mb->mhandle;
1337 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1339 MonoDynamicTable *table;
1342 ReflectionMethodBuilder rmb;
1345 reflection_methodbuilder_from_method_builder (&rmb, mb);
1347 mono_image_basic_method (&rmb, assembly);
1349 if (mb->dll) { /* It's a P/Invoke method */
1351 int charset = mb->charset & 0xf;
1352 int lasterr = mb->charset & 0x40;
1353 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1355 alloc_table (table, table->rows);
1356 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1357 /* map CharSet values to on-disk values */
1359 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1360 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1361 name = mono_string_to_utf8 (mb->dllentry);
1362 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1364 name = mono_string_to_utf8 (mb->dll);
1365 moduleref = string_heap_insert (&assembly->sheap, name);
1367 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1368 table = &assembly->tables [MONO_TABLE_MODULEREF];
1370 alloc_table (table, table->rows);
1371 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1372 values [MONO_IMPLMAP_SCOPE] = table->rows;
1376 if (mb->override_method) {
1377 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1379 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1381 alloc_table (table, table->rows);
1382 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1383 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1384 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1385 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
1386 switch (mono_metadata_token_table (tok)) {
1387 case MONO_TABLE_MEMBERREF:
1388 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1390 case MONO_TABLE_METHOD:
1391 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1394 g_assert_not_reached ();
1396 values [MONO_METHODIMPL_DECLARATION] = tok;
1399 if (mb->generic_params) {
1400 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1401 table->rows += mono_array_length (mb->generic_params);
1402 alloc_table (table, table->rows);
1403 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1404 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1406 mono_image_get_generic_param_info (
1407 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1414 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1416 ReflectionMethodBuilder rmb;
1418 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1420 mono_image_basic_method (&rmb, assembly);
1424 type_get_fully_qualified_name (MonoType *type) {
1425 char *name, *result;
1429 name = mono_type_get_name (type);
1430 klass = my_mono_class_from_mono_type (type);
1431 ta = klass->image->assembly;
1433 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1434 name, ta->aname.name,
1435 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1436 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1437 ta->aname.public_key_token [0] ? ta->aname.public_key_token : "null");
1443 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1447 klass = my_mono_class_from_mono_type (type);
1448 ta = klass->image->assembly;
1449 if (ta == ass || klass->image == mono_defaults.corlib)
1450 return mono_type_get_name (type);
1452 return type_get_fully_qualified_name (type);
1456 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1458 char blob_size [64];
1459 char *b = blob_size;
1464 if (!assembly->save)
1467 p = buf = g_malloc (64);
1469 mono_metadata_encode_value (0x06, p, &p);
1470 /* encode custom attributes before the type */
1471 encode_type (assembly, type, p, &p);
1472 g_assert (p-buf < 64);
1473 mono_metadata_encode_value (p-buf, b, &b);
1474 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1480 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1482 char blob_size [64];
1483 char *b = blob_size;
1488 p = buf = g_malloc (64);
1490 mono_metadata_encode_value (0x06, p, &p);
1491 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1492 /* encode custom attributes before the type */
1493 encode_reflection_type (assembly, fb->type, p, &p);
1494 g_assert (p-buf < 64);
1495 mono_metadata_encode_value (p-buf, b, &b);
1496 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1502 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1503 char blob_size [64];
1504 char *b = blob_size;
1507 guint32 idx = 0, len = 0, dummy = 0;
1509 p = buf = g_malloc (64);
1511 *ret_type = MONO_TYPE_CLASS;
1513 box_val = (char*)&dummy;
1515 box_val = ((char*)val) + sizeof (MonoObject);
1516 *ret_type = val->vtable->klass->byval_arg.type;
1519 switch (*ret_type) {
1520 case MONO_TYPE_BOOLEAN:
1525 case MONO_TYPE_CHAR:
1540 case MONO_TYPE_VALUETYPE:
1541 if (val->vtable->klass->enumtype) {
1542 *ret_type = val->vtable->klass->enum_basetype->type;
1545 g_error ("we can't encode valuetypes");
1546 case MONO_TYPE_CLASS:
1548 case MONO_TYPE_STRING: {
1549 MonoString *str = (MonoString*)val;
1550 /* there is no signature */
1551 len = str->length * 2;
1552 mono_metadata_encode_value (len, b, &b);
1553 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1555 char *swapped = g_malloc (2 * mono_string_length (str));
1556 const char *p = (const char*)mono_string_chars (str);
1558 swap_with_size (swapped, p, 2, mono_string_length (str));
1559 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1563 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1570 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1573 /* there is no signature */
1574 mono_metadata_encode_value (len, b, &b);
1575 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1576 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1577 swap_with_size (blob_size, box_val, len, 1);
1578 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1580 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1588 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1589 char blob_size [64];
1590 char *b = blob_size;
1591 char *p, *buf, *str;
1592 guint32 idx, len, bufsize = 256;
1594 p = buf = g_malloc (bufsize);
1596 switch (minfo->type) {
1597 case MONO_NATIVE_BYVALTSTR:
1598 case MONO_NATIVE_BYVALARRAY:
1599 mono_metadata_encode_value (minfo->type, p, &p);
1600 mono_metadata_encode_value (minfo->count, p, &p);
1602 case MONO_NATIVE_LPARRAY:
1603 mono_metadata_encode_value (minfo->type, p, &p);
1604 if (minfo->eltype || (minfo->count > 0)) {
1605 mono_metadata_encode_value (minfo->eltype, p, &p);
1606 if (minfo->count > 0) {
1607 mono_metadata_encode_value (0, p, &p);
1608 mono_metadata_encode_value (minfo->count, p, &p);
1612 case MONO_NATIVE_CUSTOM:
1613 mono_metadata_encode_value (minfo->type, p, &p);
1615 str = mono_string_to_utf8 (minfo->guid);
1617 mono_metadata_encode_value (len, p, &p);
1618 memcpy (p, str, len);
1622 mono_metadata_encode_value (0, p, &p);
1624 if (minfo->marshaltype) {
1625 str = mono_string_to_utf8 (minfo->marshaltype);
1627 mono_metadata_encode_value (len, p, &p);
1628 if (p + len >= buf + bufsize) {
1631 buf = g_realloc (buf, bufsize);
1634 memcpy (p, str, len);
1638 mono_metadata_encode_value (0, p, &p);
1640 if (minfo->marshaltyperef) {
1641 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1643 mono_metadata_encode_value (len, p, &p);
1644 if (p + len >= buf + bufsize) {
1647 buf = g_realloc (buf, bufsize);
1650 memcpy (p, str, len);
1654 mono_metadata_encode_value (0, p, &p);
1656 if (minfo->mcookie) {
1657 str = mono_string_to_utf8 (minfo->mcookie);
1659 mono_metadata_encode_value (len, p, &p);
1660 if (p + len >= buf + bufsize) {
1663 buf = g_realloc (buf, bufsize);
1666 memcpy (p, str, len);
1670 mono_metadata_encode_value (0, p, &p);
1674 mono_metadata_encode_value (minfo->type, p, &p);
1678 mono_metadata_encode_value (len, b, &b);
1679 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1685 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1687 MonoDynamicTable *table;
1691 /* maybe this fixup should be done in the C# code */
1692 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1693 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1694 table = &assembly->tables [MONO_TABLE_FIELD];
1695 fb->table_idx = table->next_idx ++;
1696 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1697 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1698 name = mono_string_to_utf8 (fb->name);
1699 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1701 values [MONO_FIELD_FLAGS] = fb->attrs;
1702 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1704 if (fb->offset != -1) {
1705 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1707 alloc_table (table, table->rows);
1708 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1709 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1710 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1712 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1713 guint32 field_type = 0;
1714 table = &assembly->tables [MONO_TABLE_CONSTANT];
1716 alloc_table (table, table->rows);
1717 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1718 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1719 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1720 values [MONO_CONSTANT_TYPE] = field_type;
1721 values [MONO_CONSTANT_PADDING] = 0;
1723 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1725 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1727 alloc_table (table, table->rows);
1728 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1729 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1731 * We store it in the code section because it's simpler for now.
1734 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1736 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1737 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1739 if (fb->marshal_info) {
1740 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1742 alloc_table (table, table->rows);
1743 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1744 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1745 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1750 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1754 char *b = blob_size;
1755 guint32 nparams = 0;
1756 MonoReflectionMethodBuilder *mb = fb->get_method;
1757 MonoReflectionMethodBuilder *smb = fb->set_method;
1758 guint32 idx, i, size;
1760 if (mb && mb->parameters)
1761 nparams = mono_array_length (mb->parameters);
1762 if (!mb && smb && smb->parameters)
1763 nparams = mono_array_length (smb->parameters) - 1;
1764 size = 24 + nparams * 10;
1765 buf = p = g_malloc (size);
1768 mono_metadata_encode_value (nparams, p, &p);
1770 encode_reflection_type (assembly, mb->rtype, p, &p);
1771 for (i = 0; i < nparams; ++i) {
1772 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1773 encode_reflection_type (assembly, pt, p, &p);
1776 /* the property type is the last param */
1777 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1778 for (i = 0; i < nparams; ++i) {
1779 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1780 encode_reflection_type (assembly, pt, p, &p);
1784 g_assert (p - buf < size);
1785 mono_metadata_encode_value (p-buf, b, &b);
1786 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1792 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1794 MonoDynamicTable *table;
1797 guint num_methods = 0;
1801 * we need to set things in the following tables:
1802 * PROPERTYMAP (info already filled in _get_type_info ())
1803 * PROPERTY (rows already preallocated in _get_type_info ())
1804 * METHOD (method info already done with the generic method code)
1807 table = &assembly->tables [MONO_TABLE_PROPERTY];
1808 pb->table_idx = table->next_idx ++;
1809 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1810 name = mono_string_to_utf8 (pb->name);
1811 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1813 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1814 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1816 /* FIXME: we still don't handle 'other' methods */
1817 if (pb->get_method) num_methods ++;
1818 if (pb->set_method) num_methods ++;
1820 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1821 table->rows += num_methods;
1822 alloc_table (table, table->rows);
1824 if (pb->get_method) {
1825 semaidx = table->next_idx ++;
1826 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1827 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1828 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1829 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1831 if (pb->set_method) {
1832 semaidx = table->next_idx ++;
1833 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1834 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1835 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1836 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1841 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1843 MonoDynamicTable *table;
1846 guint num_methods = 0;
1850 * we need to set things in the following tables:
1851 * EVENTMAP (info already filled in _get_type_info ())
1852 * EVENT (rows already preallocated in _get_type_info ())
1853 * METHOD (method info already done with the generic method code)
1856 table = &assembly->tables [MONO_TABLE_EVENT];
1857 eb->table_idx = table->next_idx ++;
1858 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1859 name = mono_string_to_utf8 (eb->name);
1860 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1862 values [MONO_EVENT_FLAGS] = eb->attrs;
1863 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1866 * FIXME: we still don't handle 'other' methods
1868 if (eb->add_method) num_methods ++;
1869 if (eb->remove_method) num_methods ++;
1870 if (eb->raise_method) num_methods ++;
1872 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1873 table->rows += num_methods;
1874 alloc_table (table, table->rows);
1876 if (eb->add_method) {
1877 semaidx = table->next_idx ++;
1878 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1879 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1880 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1881 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1883 if (eb->remove_method) {
1884 semaidx = table->next_idx ++;
1885 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1886 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1887 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1888 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1890 if (eb->raise_method) {
1891 semaidx = table->next_idx ++;
1892 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1893 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1894 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1895 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1900 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1902 static MonoClass *NewConstraintAttr;
1903 static MonoMethod *NewConstraintAttr_ctor;
1904 MonoDynamicTable *table;
1906 guint32 token, type;
1907 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1910 if (!NewConstraintAttr)
1911 NewConstraintAttr = mono_class_from_name (
1912 mono_defaults.corlib, "System.Runtime.CompilerServices",
1913 "NewConstraintAttribute");
1914 g_assert (NewConstraintAttr);
1916 if (!NewConstraintAttr_ctor) {
1919 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1920 MonoMethod *m = NewConstraintAttr->methods [i];
1922 if (strcmp (m->name, ".ctor"))
1925 NewConstraintAttr_ctor = m;
1929 g_assert (NewConstraintAttr_ctor);
1932 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1934 alloc_table (table, table->rows);
1936 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1937 owner <<= MONO_CUSTOM_ATTR_BITS;
1938 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1939 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1941 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1943 type = mono_metadata_token_index (token);
1944 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1945 switch (mono_metadata_token_table (token)) {
1946 case MONO_TABLE_METHOD:
1947 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1949 case MONO_TABLE_MEMBERREF:
1950 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1953 g_warning ("got wrong token in custom attr");
1956 values [MONO_CUSTOM_ATTR_TYPE] = type;
1958 buf = p = g_malloc (1);
1959 mono_metadata_encode_value (4, p, &p);
1960 g_assert (p-buf == 1);
1962 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1964 values += MONO_CUSTOM_ATTR_SIZE;
1969 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1971 MonoDynamicTable *table;
1972 guint32 num_constraints, i;
1976 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1977 num_constraints = gparam->iface_constraints ?
1978 mono_array_length (gparam->iface_constraints) : 0;
1979 table->rows += num_constraints;
1980 if (gparam->base_type)
1982 alloc_table (table, table->rows);
1984 if (gparam->base_type) {
1985 table_idx = table->next_idx ++;
1986 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1988 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1989 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1990 assembly, gparam->base_type->type);
1993 for (i = 0; i < num_constraints; i++) {
1994 MonoReflectionType *constraint = mono_array_get (
1995 gparam->iface_constraints, gpointer, i);
1997 table_idx = table->next_idx ++;
1998 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2000 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2001 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2002 assembly, constraint->type);
2005 if (gparam->has_ctor_constraint)
2006 encode_new_constraint (assembly, owner);
2010 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2012 MonoDynamicTable *table;
2013 MonoGenericParam *param;
2017 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2018 table_idx = table->next_idx ++;
2019 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2021 param = gparam->type.type->data.generic_param;
2023 values [MONO_GENERICPARAM_OWNER] = owner;
2024 if (gparam->has_value_type)
2025 values [MONO_GENERICPARAM_FLAGS] = 0x18;
2026 else if (gparam->has_reference_type)
2027 values [MONO_GENERICPARAM_FLAGS] = 0x04;
2029 values [MONO_GENERICPARAM_FLAGS] = 0x00;
2030 values [MONO_GENERICPARAM_NUMBER] = param->num;
2031 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2032 values [MONO_GENERICPARAM_KIND] = 0;
2034 encode_constraints (gparam, table_idx, assembly);
2038 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2040 MonoDynamicTable *table;
2043 guint32 cols [MONO_ASSEMBLY_SIZE];
2047 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2050 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2051 table = &assembly->tables [MONO_TABLE_MODULEREF];
2052 token = table->next_idx ++;
2054 alloc_table (table, table->rows);
2055 values = table->values + token * MONO_MODULEREF_SIZE;
2056 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2058 token <<= MONO_RESOLTION_SCOPE_BITS;
2059 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2060 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2065 if (image->assembly->dynamic)
2067 memset (cols, 0, sizeof (cols));
2069 /* image->assembly->image is the manifest module */
2070 image = image->assembly->image;
2071 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2074 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2075 token = table->next_idx ++;
2077 alloc_table (table, table->rows);
2078 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2079 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2080 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2081 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2082 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2083 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2084 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2085 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2086 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2088 if (strcmp ("", image->assembly->aname.culture)) {
2089 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2090 image->assembly->aname.culture);
2093 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2094 guchar pubtoken [9];
2096 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2097 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2099 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2101 token <<= MONO_RESOLTION_SCOPE_BITS;
2102 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2103 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2108 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2110 MonoDynamicTable *table;
2116 char *b = blob_size;
2118 switch (type->type) {
2119 case MONO_TYPE_FNPTR:
2121 case MONO_TYPE_SZARRAY:
2122 case MONO_TYPE_ARRAY:
2124 case MONO_TYPE_MVAR:
2125 case MONO_TYPE_GENERICINST:
2126 encode_type (assembly, type, p, &p);
2128 case MONO_TYPE_CLASS:
2129 case MONO_TYPE_VALUETYPE: {
2130 MonoClass *k = mono_class_from_mono_type (type);
2131 if (!k || !k->generic_inst)
2133 encode_generic_inst (assembly, k->generic_inst, p, &p);
2140 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2141 if (assembly->save) {
2142 g_assert (p-sig < 128);
2143 mono_metadata_encode_value (p-sig, b, &b);
2144 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2145 alloc_table (table, table->rows + 1);
2146 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2147 values [MONO_TYPESPEC_SIGNATURE] = token;
2150 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2151 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2157 * Despite the name, we handle also TypeSpec (with the above helper).
2160 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2162 MonoDynamicTable *table;
2164 guint32 token, scope, enclosing;
2167 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2170 token = create_typespec (assembly, type);
2173 klass = my_mono_class_from_mono_type (type);
2175 klass = mono_class_from_mono_type (type);
2178 * If it's in the same module and not a generic type parameter:
2180 if ((klass->image == &assembly->image) &&
2181 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2182 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2183 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2184 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2188 if (klass->nested_in) {
2189 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2190 /* get the typeref idx of the enclosing type */
2191 enclosing >>= MONO_TYPEDEFORREF_BITS;
2192 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2194 scope = resolution_scope_from_image (assembly, klass->image);
2196 table = &assembly->tables [MONO_TABLE_TYPEREF];
2197 if (assembly->save) {
2198 alloc_table (table, table->rows + 1);
2199 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2200 values [MONO_TYPEREF_SCOPE] = scope;
2201 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2202 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2204 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2205 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2207 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2212 * Insert a memberef row into the metadata: the token that point to the memberref
2213 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2214 * mono_image_get_fieldref_token()).
2215 * The sig param is an index to an already built signature.
2218 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2220 MonoDynamicTable *table;
2222 guint32 token, pclass;
2225 parent = mono_image_typedef_or_ref (assembly, type);
2226 switch (parent & MONO_TYPEDEFORREF_MASK) {
2227 case MONO_TYPEDEFORREF_TYPEREF:
2228 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2230 case MONO_TYPEDEFORREF_TYPESPEC:
2231 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2233 case MONO_TYPEDEFORREF_TYPEDEF:
2234 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2237 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2240 /* extract the index */
2241 parent >>= MONO_TYPEDEFORREF_BITS;
2243 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2245 if (assembly->save) {
2246 alloc_table (table, table->rows + 1);
2247 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2248 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2249 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2250 values [MONO_MEMBERREF_SIGNATURE] = sig;
2253 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2260 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2264 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2267 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2268 method->name, method_encode_signature (assembly, method->signature));
2269 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2274 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2275 const gchar *name, guint32 sig)
2277 MonoDynamicTable *table;
2278 guint32 parent, token;
2281 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2283 if (assembly->save) {
2284 alloc_table (table, table->rows + 1);
2285 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2286 values [MONO_MEMBERREF_CLASS] = original;
2287 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2288 values [MONO_MEMBERREF_SIGNATURE] = sig;
2291 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2298 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2301 ReflectionMethodBuilder rmb;
2303 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2307 reflection_methodbuilder_from_method_builder (&rmb, mb);
2309 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2310 mono_string_to_utf8 (rmb.name),
2311 method_builder_encode_signature (assembly, &rmb));
2312 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2317 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2320 ReflectionMethodBuilder rmb;
2322 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2326 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2328 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2329 mono_string_to_utf8 (rmb.name),
2330 method_builder_encode_signature (assembly, &rmb));
2331 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2336 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2341 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2344 g_assert (f->field->parent);
2345 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2346 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2347 f->field->name, fieldref_encode_signature (assembly, type));
2348 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2353 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2358 guint32 nparams = gmethod->mtype_argc;
2359 guint32 size = 10 + nparams * 10;
2362 char *b = blob_size;
2364 if (!assembly->save)
2367 p = buf = g_malloc (size);
2369 * FIXME: vararg, explicit_this, differenc call_conv values...
2371 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2372 mono_metadata_encode_value (nparams, p, &p);
2374 for (i = 0; i < nparams; i++)
2375 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2378 g_assert (p - buf < size);
2379 mono_metadata_encode_value (p-buf, b, &b);
2380 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2386 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2388 MonoDynamicTable *table;
2390 guint32 token, mtoken = 0, sig;
2391 MonoMethodInflated *imethod;
2392 MonoMethod *declaring;
2394 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2396 g_assert (method->signature->is_inflated);
2397 imethod = (MonoMethodInflated *) method;
2398 declaring = imethod->declaring;
2400 sig = method_encode_signature (assembly, declaring->signature);
2401 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2402 declaring->name, sig);
2404 if (!declaring->signature->generic_param_count)
2407 switch (mono_metadata_token_table (mtoken)) {
2408 case MONO_TABLE_MEMBERREF:
2409 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2411 case MONO_TABLE_METHOD:
2412 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2415 g_assert_not_reached ();
2418 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2420 if (assembly->save) {
2421 alloc_table (table, table->rows + 1);
2422 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2423 values [MONO_METHODSPEC_METHOD] = mtoken;
2424 values [MONO_METHODSPEC_SIGNATURE] = sig;
2427 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2434 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2436 MonoMethodInflated *imethod;
2439 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2443 g_assert (m->signature->is_inflated);
2444 imethod = (MonoMethodInflated *) m;
2446 if (imethod->declaring->signature->generic_param_count)
2447 token = method_encode_methodspec (assembly, m);
2449 guint32 sig = method_encode_signature (
2450 assembly, imethod->declaring->signature);
2451 token = mono_image_get_memberref_token (
2452 assembly, &m->klass->byval_arg, m->name, sig);
2455 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2460 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2462 MonoDynamicTable *table;
2469 char *b = blob_size;
2473 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2474 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2475 * Because of this, we must not insert it into the `typeref' hash table.
2478 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2482 g_assert (tb->generic_params);
2483 klass = mono_class_from_mono_type (tb->type.type);
2485 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2486 encode_type (assembly, &klass->byval_arg, p, &p);
2488 count = mono_array_length (tb->generic_params);
2489 mono_metadata_encode_value (count, p, &p);
2490 for (i = 0; i < count; i++) {
2491 MonoReflectionGenericParam *gparam;
2493 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2495 encode_type (assembly, gparam->type.type, p, &p);
2498 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2499 if (assembly->save) {
2500 g_assert (p-sig < 128);
2501 mono_metadata_encode_value (p-sig, b, &b);
2502 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2503 alloc_table (table, table->rows + 1);
2504 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2505 values [MONO_TYPESPEC_SIGNATURE] = token;
2508 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2509 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2515 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2517 MonoDynamicTable *table;
2520 guint32 token, pclass, parent, sig;
2523 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2527 klass = mono_class_from_mono_type (fb->typeb->type);
2528 name = mono_string_to_utf8 (fb->name);
2530 sig = fieldref_encode_signature (assembly, fb->type->type);
2532 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2533 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2535 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2536 parent >>= MONO_TYPEDEFORREF_BITS;
2538 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2540 if (assembly->save) {
2541 alloc_table (table, table->rows + 1);
2542 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2543 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2544 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2545 values [MONO_MEMBERREF_SIGNATURE] = sig;
2548 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2550 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2555 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2563 char *b = blob_size;
2565 if (!assembly->save)
2569 g_assert (helper->type == 2);
2571 if (helper->arguments)
2572 nargs = mono_array_length (helper->arguments);
2576 size = 10 + (nargs * 10);
2578 p = buf = g_malloc (size);
2580 /* Encode calling convention */
2581 /* Change Any to Standard */
2582 if ((helper->call_conv & 0x03) == 0x03)
2583 helper->call_conv = 0x01;
2584 /* explicit_this implies has_this */
2585 if (helper->call_conv & 0x40)
2586 helper->call_conv &= 0x20;
2588 if (helper->call_conv == 0) /* Unmanaged */
2589 *p = helper->unmanaged_call_conv - 1;
2592 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2593 if (helper->call_conv & 0x02) /* varargs */
2598 mono_metadata_encode_value (nargs, p, &p);
2599 encode_reflection_type (assembly, helper->return_type, p, &p);
2600 for (i = 0; i < nargs; ++i) {
2601 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2602 encode_reflection_type (assembly, pt, p, &p);
2605 g_assert (p - buf < size);
2606 mono_metadata_encode_value (p-buf, b, &b);
2607 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2614 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2617 MonoDynamicTable *table;
2620 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2621 idx = table->next_idx ++;
2623 alloc_table (table, table->rows);
2624 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2626 values [MONO_STAND_ALONE_SIGNATURE] =
2627 mono_reflection_encode_sighelper (assembly, helper);
2633 reflection_cc_to_file (int call_conv) {
2634 switch (call_conv & 0x3) {
2636 case 1: return MONO_CALL_DEFAULT;
2637 case 2: return MONO_CALL_VARARG;
2639 g_assert_not_reached ();
2646 MonoMethodSignature *sig;
2652 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2657 MonoMethodSignature *sig;
2660 name = mono_string_to_utf8 (m->name);
2661 nparams = mono_array_length (m->parameters);
2662 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2664 sig->sentinelpos = -1;
2665 sig->call_convention = reflection_cc_to_file (m->call_conv);
2666 sig->param_count = nparams;
2667 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2668 for (i = 0; i < nparams; ++i) {
2669 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2670 sig->params [i] = t->type;
2673 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2675 if (strcmp (name, am->name) == 0 &&
2676 mono_metadata_type_equal (am->parent, m->parent->type) &&
2677 mono_metadata_signature_equal (am->sig, sig)) {
2680 m->table_idx = am->token & 0xffffff;
2684 am = g_new0 (ArrayMethod, 1);
2687 am->parent = m->parent->type;
2688 am->token = mono_image_get_memberref_token (assembly, am->parent,
2689 name, method_encode_signature (assembly, sig));
2690 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2691 m->table_idx = am->token & 0xffffff;
2696 * Insert into the metadata tables all the info about the TypeBuilder tb.
2697 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2700 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2702 MonoDynamicTable *table;
2704 int i, is_object = 0, is_system = 0;
2707 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2708 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2709 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2710 n = mono_string_to_utf8 (tb->name);
2711 if (strcmp (n, "Object") == 0)
2713 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2715 n = mono_string_to_utf8 (tb->nspace);
2716 if (strcmp (n, "System") == 0)
2718 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2720 if (tb->parent && !(is_system && is_object) &&
2721 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2722 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2724 values [MONO_TYPEDEF_EXTENDS] = 0;
2725 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2726 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2729 * if we have explicitlayout or sequentiallayouts, output data in the
2730 * ClassLayout table.
2732 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2733 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2734 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2736 alloc_table (table, table->rows);
2737 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2738 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2739 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2740 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2743 /* handle interfaces */
2744 if (tb->interfaces) {
2745 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2747 table->rows += mono_array_length (tb->interfaces);
2748 alloc_table (table, table->rows);
2749 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2750 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2751 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2752 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2753 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2754 values += MONO_INTERFACEIMPL_SIZE;
2758 /* handle generic parameters */
2759 if (tb->generic_params) {
2760 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2761 table->rows += mono_array_length (tb->generic_params);
2762 alloc_table (table, table->rows);
2763 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2764 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2766 mono_image_get_generic_param_info (
2767 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2773 table = &assembly->tables [MONO_TABLE_FIELD];
2774 table->rows += tb->num_fields;
2775 alloc_table (table, table->rows);
2776 for (i = 0; i < tb->num_fields; ++i)
2777 mono_image_get_field_info (
2778 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2781 /* handle constructors */
2783 table = &assembly->tables [MONO_TABLE_METHOD];
2784 table->rows += mono_array_length (tb->ctors);
2785 alloc_table (table, table->rows);
2786 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2787 mono_image_get_ctor_info (domain,
2788 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2791 /* handle methods */
2793 table = &assembly->tables [MONO_TABLE_METHOD];
2794 table->rows += tb->num_methods;
2795 alloc_table (table, table->rows);
2796 for (i = 0; i < tb->num_methods; ++i)
2797 mono_image_get_method_info (
2798 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2801 /* Do the same with properties etc.. */
2802 if (tb->events && mono_array_length (tb->events)) {
2803 table = &assembly->tables [MONO_TABLE_EVENT];
2804 table->rows += mono_array_length (tb->events);
2805 alloc_table (table, table->rows);
2806 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2808 alloc_table (table, table->rows);
2809 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2810 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2811 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2812 for (i = 0; i < mono_array_length (tb->events); ++i)
2813 mono_image_get_event_info (
2814 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2816 if (tb->properties && mono_array_length (tb->properties)) {
2817 table = &assembly->tables [MONO_TABLE_PROPERTY];
2818 table->rows += mono_array_length (tb->properties);
2819 alloc_table (table, table->rows);
2820 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2822 alloc_table (table, table->rows);
2823 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2824 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2825 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2826 for (i = 0; i < mono_array_length (tb->properties); ++i)
2827 mono_image_get_property_info (
2828 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2831 mono_image_add_decl_security (assembly,
2832 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2836 MonoDynamicTable *ntable;
2838 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2839 ntable->rows += mono_array_length (tb->subtypes);
2840 alloc_table (ntable, ntable->rows);
2841 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2843 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2844 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2846 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2847 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2848 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2849 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2850 mono_string_to_utf8 (tb->name), tb->table_idx,
2851 ntable->next_idx, ntable->rows);*/
2852 values += MONO_NESTED_CLASS_SIZE;
2859 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2863 g_ptr_array_add (types, type);
2865 if (!type->subtypes)
2868 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2869 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2870 collect_types (types, subtype);
2875 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2876 MonoReflectionTypeBuilder **type2)
2878 if ((*type1)->table_idx < (*type2)->table_idx)
2881 if ((*type1)->table_idx > (*type2)->table_idx)
2888 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2893 for (i = 0; i < mono_array_length (pinfo); ++i) {
2894 MonoReflectionParamBuilder *pb;
2895 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2898 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2903 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2906 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2908 for (i = 0; i < tb->num_fields; ++i) {
2909 MonoReflectionFieldBuilder* fb;
2910 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2911 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2915 for (i = 0; i < mono_array_length (tb->events); ++i) {
2916 MonoReflectionEventBuilder* eb;
2917 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2918 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2921 if (tb->properties) {
2922 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2923 MonoReflectionPropertyBuilder* pb;
2924 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2925 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2929 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2930 MonoReflectionCtorBuilder* cb;
2931 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2932 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2933 params_add_cattrs (assembly, cb->pinfo);
2938 for (i = 0; i < tb->num_methods; ++i) {
2939 MonoReflectionMethodBuilder* mb;
2940 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2941 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2942 params_add_cattrs (assembly, mb->pinfo);
2947 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2948 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2953 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2956 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
2958 /* no types in the module */
2962 for (i = 0; i < mb->num_types; ++i)
2963 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2967 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2968 MonoDynamicImage *assembly)
2970 MonoDynamicTable *table;
2974 char *b = blob_size;
2977 table = &assembly->tables [MONO_TABLE_FILE];
2979 alloc_table (table, table->rows);
2980 values = table->values + table->next_idx * MONO_FILE_SIZE;
2981 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2982 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2983 if (module->image->dynamic) {
2984 /* This depends on the fact that the main module is emitted last */
2985 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2986 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2990 path = g_strdup (module->image->name);
2992 mono_sha1_get_digest_from_file (path, hash);
2995 mono_metadata_encode_value (20, b, &b);
2996 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2997 mono_image_add_stream_data (&assembly->blob, hash, 20);
3002 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3004 MonoDynamicTable *table;
3008 table = &assembly->tables [MONO_TABLE_MODULE];
3009 mb->table_idx = table->next_idx ++;
3010 name = mono_string_to_utf8 (mb->module.name);
3011 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3013 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3016 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3017 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3018 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3022 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3023 guint32 module_index, guint32 parent_index,
3024 MonoDynamicImage *assembly)
3026 MonoDynamicTable *table;
3030 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3031 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3034 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3036 alloc_table (table, table->rows);
3037 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3039 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3040 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3041 if (klass->nested_in)
3042 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3044 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3045 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3046 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3048 res = table->next_idx;
3052 /* Emit nested types */
3053 if (klass->nested_classes) {
3056 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3057 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3064 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3065 guint32 module_index, guint32 parent_index,
3066 MonoDynamicImage *assembly)
3071 klass = mono_class_from_mono_type (tb->type.type);
3073 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3075 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3076 parent_index, assembly);
3080 * We need to do this ourselves since klass->nested_classes is not set up.
3083 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3084 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3089 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3090 guint32 module_index,
3091 MonoDynamicImage *assembly)
3093 MonoImage *image = module->image;
3097 t = &image->tables [MONO_TABLE_TYPEDEF];
3099 for (i = 0; i < t->rows; ++i) {
3100 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3102 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3103 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3107 #define align_pointer(base,p)\
3109 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3111 (p) += 4 - (__diff & 3);\
3115 compare_semantics (const void *a, const void *b)
3117 const guint32 *a_values = a;
3118 const guint32 *b_values = b;
3119 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3122 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3126 compare_custom_attrs (const void *a, const void *b)
3128 const guint32 *a_values = a;
3129 const guint32 *b_values = b;
3131 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3135 compare_field_marshal (const void *a, const void *b)
3137 const guint32 *a_values = a;
3138 const guint32 *b_values = b;
3140 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3144 compare_nested (const void *a, const void *b)
3146 const guint32 *a_values = a;
3147 const guint32 *b_values = b;
3149 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3153 pad_heap (MonoDynamicStream *sh)
3155 if (sh->index & 3) {
3156 int sz = 4 - (sh->index & 3);
3157 memset (sh->data + sh->index, 0, sz);
3163 * build_compressed_metadata() fills in the blob of data that represents the
3164 * raw metadata as it will be saved in the PE file. The five streams are output
3165 * and the metadata tables are comnpressed from the guint32 array representation,
3166 * to the compressed on-disk format.
3169 build_compressed_metadata (MonoDynamicImage *assembly)
3171 MonoDynamicTable *table;
3173 guint64 valid_mask = 0;
3174 guint64 sorted_mask;
3175 guint32 heapt_size = 0;
3176 guint32 meta_size = 256; /* allow for header and other stuff */
3177 guint32 table_offset;
3178 guint32 ntables = 0;
3187 MonoDynamicStream *stream;
3190 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3191 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3192 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3193 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3194 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3196 /* tables that are sorted */
3197 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3198 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3199 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3200 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3201 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3202 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
3204 /* Compute table sizes */
3205 /* the MonoImage has already been created in mono_image_basic_init() */
3206 meta = &assembly->image;
3208 /* sizes should be multiple of 4 */
3209 pad_heap (&assembly->blob);
3210 pad_heap (&assembly->guid);
3211 pad_heap (&assembly->sheap);
3212 pad_heap (&assembly->us);
3214 /* Setup the info used by compute_sizes () */
3215 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3216 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3217 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3219 meta_size += assembly->blob.index;
3220 meta_size += assembly->guid.index;
3221 meta_size += assembly->sheap.index;
3222 meta_size += assembly->us.index;
3224 for (i=0; i < 64; ++i)
3225 meta->tables [i].rows = assembly->tables [i].rows;
3227 for (i = 0; i < 64; i++){
3228 if (meta->tables [i].rows == 0)
3230 valid_mask |= (guint64)1 << i;
3232 meta->tables [i].row_size = mono_metadata_compute_size (
3233 meta, i, &meta->tables [i].size_bitfield);
3234 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3236 heapt_size += 24; /* #~ header size */
3237 heapt_size += ntables * 4;
3238 /* make multiple of 4 */
3241 meta_size += heapt_size;
3242 meta->raw_metadata = g_malloc0 (meta_size);
3243 p = meta->raw_metadata;
3244 /* the metadata signature */
3245 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3246 /* version numbers and 4 bytes reserved */
3247 int16val = (guint16*)p;
3248 *int16val++ = GUINT16_TO_LE (1);
3249 *int16val = GUINT16_TO_LE (1);
3251 /* version string */
3252 int32val = (guint32*)p;
3253 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3255 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3256 p += GUINT32_FROM_LE (*int32val);
3257 align_pointer (meta->raw_metadata, p);
3258 int16val = (guint16*)p;
3259 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3260 *int16val = GUINT16_TO_LE (5); /* number of streams */
3264 * write the stream info.
3266 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3267 table_offset += 3; table_offset &= ~3;
3269 assembly->tstream.index = heapt_size;
3270 for (i = 0; i < 5; ++i) {
3271 int32val = (guint32*)p;
3272 stream_desc [i].stream->offset = table_offset;
3273 *int32val++ = GUINT32_TO_LE (table_offset);
3274 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3275 table_offset += GUINT32_FROM_LE (*int32val);
3276 table_offset += 3; table_offset &= ~3;
3278 strcpy (p, stream_desc [i].name);
3279 p += strlen (stream_desc [i].name) + 1;
3280 align_pointer (meta->raw_metadata, p);
3283 * now copy the data, the table stream header and contents goes first.
3285 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3286 p = meta->raw_metadata + assembly->tstream.offset;
3287 int32val = (guint32*)p;
3288 *int32val = GUINT32_TO_LE (0); /* reserved */
3291 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3292 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3293 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3294 *p++ = 1; /* version */
3297 *p++ = 1; /* version */
3301 if (meta->idx_string_wide)
3303 if (meta->idx_guid_wide)
3305 if (meta->idx_blob_wide)
3308 *p++ = 0; /* reserved */
3309 int64val = (guint64*)p;
3310 *int64val++ = GUINT64_TO_LE (valid_mask);
3311 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3313 int32val = (guint32*)p;
3314 for (i = 0; i < 64; i++){
3315 if (meta->tables [i].rows == 0)
3317 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3319 p = (unsigned char*)int32val;
3321 /* sort the tables that still need sorting */
3322 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3324 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3325 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3327 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3328 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3330 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3331 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3333 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3335 /* compress the tables */
3336 for (i = 0; i < 64; i++){
3339 guint32 bitfield = meta->tables [i].size_bitfield;
3340 if (!meta->tables [i].rows)
3342 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3343 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3344 meta->tables [i].base = p;
3345 for (row = 1; row <= meta->tables [i].rows; ++row) {
3346 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3347 for (col = 0; col < assembly->tables [i].columns; ++col) {
3348 switch (mono_metadata_table_size (bitfield, col)) {
3350 *p++ = values [col];
3353 *p++ = values [col] & 0xff;
3354 *p++ = (values [col] >> 8) & 0xff;
3357 *p++ = values [col] & 0xff;
3358 *p++ = (values [col] >> 8) & 0xff;
3359 *p++ = (values [col] >> 16) & 0xff;
3360 *p++ = (values [col] >> 24) & 0xff;
3363 g_assert_not_reached ();
3367 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3370 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3371 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3372 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3373 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3374 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3376 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3380 * Some tables in metadata need to be sorted according to some criteria, but
3381 * when methods and fields are first created with reflection, they may be assigned a token
3382 * that doesn't correspond to the final token they will get assigned after the sorting.
3383 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3384 * with the reflection objects that represent them. Once all the tables are set up, the
3385 * reflection objects will contains the correct table index. fixup_method() will fixup the
3386 * tokens for the method with ILGenerator @ilgen.
3389 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3390 guint32 code_idx = GPOINTER_TO_UINT (value);
3391 MonoReflectionILTokenInfo *iltoken;
3392 MonoReflectionFieldBuilder *field;
3393 MonoReflectionCtorBuilder *ctor;
3394 MonoReflectionMethodBuilder *method;
3395 MonoReflectionTypeBuilder *tb;
3396 MonoReflectionArrayMethod *am;
3398 unsigned char *target;
3400 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3401 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3402 target = assembly->code.data + code_idx + iltoken->code_pos;
3403 switch (target [3]) {
3404 case MONO_TABLE_FIELD:
3405 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3406 field = (MonoReflectionFieldBuilder *)iltoken->member;
3407 idx = field->table_idx;
3408 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3409 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3410 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3412 g_assert_not_reached ();
3415 case MONO_TABLE_METHOD:
3416 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3417 method = (MonoReflectionMethodBuilder *)iltoken->member;
3418 idx = method->table_idx;
3419 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3420 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3421 idx = ctor->table_idx;
3422 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3423 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3424 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3425 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3427 g_assert_not_reached ();
3430 case MONO_TABLE_TYPEDEF:
3431 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3432 g_assert_not_reached ();
3433 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3434 idx = tb->table_idx;
3436 case MONO_TABLE_MEMBERREF:
3437 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3438 am = (MonoReflectionArrayMethod*)iltoken->member;
3439 idx = am->table_idx;
3440 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3441 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3442 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3443 g_assert (m->klass->generic_inst);
3445 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3447 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3448 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3449 g_assert (f->generic_info);
3451 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3454 g_assert_not_reached ();
3457 case MONO_TABLE_METHODSPEC:
3458 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3459 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3460 g_assert (m->signature->generic_param_count);
3463 g_assert_not_reached ();
3467 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3469 target [0] = idx & 0xff;
3470 target [1] = (idx >> 8) & 0xff;
3471 target [2] = (idx >> 16) & 0xff;
3478 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3479 * value is not known when the table is emitted.
3482 fixup_cattrs (MonoDynamicImage *assembly)
3484 MonoDynamicTable *table;
3486 guint32 type, i, idx, token;
3489 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3491 for (i = 0; i < table->rows; ++i) {
3492 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3494 type = values [MONO_CUSTOM_ATTR_TYPE];
3495 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3496 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3497 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3498 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3501 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3502 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3503 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3504 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3511 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3513 MonoDynamicTable *table;
3517 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3519 alloc_table (table, table->rows);
3520 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3521 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3522 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3523 name = mono_string_to_utf8 (rsrc->name);
3524 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3526 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3531 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3533 MonoDynamicTable *table;
3537 char *b = blob_size;
3539 guint32 idx, offset;
3541 if (rsrc->filename) {
3542 name = mono_string_to_utf8 (rsrc->filename);
3543 sname = g_path_get_basename (name);
3545 table = &assembly->tables [MONO_TABLE_FILE];
3547 alloc_table (table, table->rows);
3548 values = table->values + table->next_idx * MONO_FILE_SIZE;
3549 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3550 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3553 mono_sha1_get_digest_from_file (name, hash);
3554 mono_metadata_encode_value (20, b, &b);
3555 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3556 mono_image_add_stream_data (&assembly->blob, hash, 20);
3558 idx = table->next_idx++;
3560 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3563 offset = mono_array_length (rsrc->data);
3564 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3565 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3566 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3567 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3571 * The entry should be emitted into the MANIFESTRESOURCE table of
3572 * the main module, but that needs to reference the FILE table
3573 * which isn't emitted yet.
3580 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3584 set_version_from_string (MonoString *version, guint32 *values)
3586 gchar *ver, *p, *str;
3589 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3590 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3591 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3592 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3595 ver = str = mono_string_to_utf8 (version);
3596 for (i = 0; i < 4; ++i) {
3597 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3603 /* handle Revision and Build */
3613 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3617 char *b = blob_size;
3622 len = mono_array_length (pkey);
3623 mono_metadata_encode_value (len, b, &b);
3624 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3625 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3627 /* need to get the actual value from the key type... */
3628 assembly->strong_name_size = 128;
3629 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3635 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3637 MonoDynamicTable *table;
3638 MonoDynamicImage *assembly;
3639 MonoReflectionAssemblyBuilder *assemblyb;
3644 guint32 module_index;
3646 assemblyb = moduleb->assemblyb;
3647 assembly = moduleb->dynamic_image;
3648 domain = mono_object_domain (assemblyb);
3650 /* Emit ASSEMBLY table */
3651 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3652 alloc_table (table, 1);
3653 values = table->values + MONO_ASSEMBLY_SIZE;
3654 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3655 name = mono_string_to_utf8 (assemblyb->name);
3656 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3658 if (assemblyb->culture) {
3659 name = mono_string_to_utf8 (assemblyb->culture);
3660 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3663 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3665 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3666 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3667 set_version_from_string (assemblyb->version, values);
3669 /* Emit FILE + EXPORTED_TYPE table */
3671 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3673 MonoReflectionModuleBuilder *file_module =
3674 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3675 if (file_module != moduleb) {
3676 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3678 if (file_module->types) {
3679 for (j = 0; j < file_module->num_types; ++j) {
3680 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3681 mono_image_fill_export_table (domain, tb, module_index, 0,
3687 if (assemblyb->loaded_modules) {
3688 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3689 MonoReflectionModule *file_module =
3690 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3691 mono_image_fill_file_table (domain, file_module, assembly);
3693 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3697 /* Emit MANIFESTRESOURCE table */
3699 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3701 MonoReflectionModuleBuilder *file_module =
3702 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3703 /* The table for the main module is emitted later */
3704 if (file_module != moduleb) {
3706 if (file_module->resources) {
3707 int len = mono_array_length (file_module->resources);
3708 for (j = 0; j < len; ++j) {
3709 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3710 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3718 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3719 * for the modulebuilder @moduleb.
3720 * At the end of the process, method and field tokens are fixed up and the
3721 * on-disk compressed metadata representation is created.
3724 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3726 MonoDynamicTable *table;
3727 MonoDynamicImage *assembly;
3728 MonoReflectionAssemblyBuilder *assemblyb;
3733 assemblyb = moduleb->assemblyb;
3734 assembly = moduleb->dynamic_image;
3735 domain = mono_object_domain (assemblyb);
3737 if (assembly->text_rva)
3740 assembly->text_rva = START_TEXT_RVA;
3742 if (moduleb->is_main) {
3743 mono_image_emit_manifest (moduleb);
3746 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3747 table->rows = 1; /* .<Module> */
3749 alloc_table (table, table->rows);
3751 * Set the first entry.
3753 values = table->values + table->columns;
3754 values [MONO_TYPEDEF_FLAGS] = 0;
3755 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3756 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3757 values [MONO_TYPEDEF_EXTENDS] = 0;
3758 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3759 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3762 * handle global methods
3763 * FIXME: test what to do when global methods are defined in multiple modules.
3765 if (moduleb->global_methods) {
3766 table = &assembly->tables [MONO_TABLE_METHOD];
3767 table->rows += mono_array_length (moduleb->global_methods);
3768 alloc_table (table, table->rows);
3769 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3770 mono_image_get_method_info (
3771 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3773 if (moduleb->global_fields) {
3774 table = &assembly->tables [MONO_TABLE_FIELD];
3775 table->rows += mono_array_length (moduleb->global_fields);
3776 alloc_table (table, table->rows);
3777 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3778 mono_image_get_field_info (
3779 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3782 table = &assembly->tables [MONO_TABLE_MODULE];
3783 alloc_table (table, 1);
3784 mono_image_fill_module_table (domain, moduleb, assembly);
3788 /* Collect all types into a list sorted by their table_idx */
3789 GPtrArray *types = g_ptr_array_new ();
3792 for (i = 0; i < moduleb->num_types; ++i) {
3793 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3794 collect_types (types, type);
3797 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3798 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3799 table->rows += types->len;
3800 alloc_table (table, table->rows);
3802 for (i = 0; i < types->len; ++i) {
3803 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3804 mono_image_get_type_info (domain, type, assembly);
3806 g_ptr_array_free (types, TRUE);
3810 * table->rows is already set above and in mono_image_fill_module_table.
3812 /* add all the custom attributes at the end, once all the indexes are stable */
3813 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3815 module_add_cattrs (assembly, moduleb);
3818 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3819 fixup_cattrs (assembly);
3823 * mono_image_insert_string:
3824 * @module: module builder object
3827 * Insert @str into the user string stream of @module.
3830 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3832 MonoDynamicImage *assembly;
3837 MONO_ARCH_SAVE_REGS;
3839 if (!module->dynamic_image)
3840 mono_image_module_basic_init (module);
3842 assembly = module->dynamic_image;
3844 if (assembly->save) {
3845 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3846 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3847 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3849 char *swapped = g_malloc (2 * mono_string_length (str));
3850 const char *p = (const char*)mono_string_chars (str);
3852 swap_with_size (swapped, p, 2, mono_string_length (str));
3853 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3857 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3859 mono_image_add_stream_data (&assembly->us, "", 1);
3862 idx = assembly->us.index ++;
3864 mono_g_hash_table_insert (assembly->tokens,
3865 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3867 return MONO_TOKEN_STRING | idx;
3871 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj,
3872 MonoArray *opt_param_types)
3877 klass = obj->vtable->klass;
3878 if (strcmp (klass->name, "MonoMethod") == 0) {
3879 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3880 MonoMethodSignature *sig, *old;
3881 guint32 sig_token, parent;
3884 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3886 nargs = mono_array_length (opt_param_types);
3887 old = method->signature;
3888 sig = mono_metadata_signature_alloc (
3889 &assembly->image, old->param_count + nargs);
3891 sig->hasthis = old->hasthis;
3892 sig->explicit_this = old->explicit_this;
3893 sig->call_convention = old->call_convention;
3894 sig->generic_param_count = old->generic_param_count;
3895 sig->param_count = old->param_count + nargs;
3896 sig->sentinelpos = old->param_count;
3897 sig->ret = old->ret;
3899 for (i = 0; i < old->param_count; i++)
3900 sig->params [i] = old->params [i];
3902 for (i = 0; i < nargs; i++) {
3903 MonoReflectionType *rt = mono_array_get (
3904 opt_param_types, MonoReflectionType *, i);
3905 sig->params [old->param_count + i] = rt->type;
3908 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
3909 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
3910 parent >>= MONO_TYPEDEFORREF_BITS;
3912 parent <<= MONO_MEMBERREF_PARENT_BITS;
3913 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
3915 sig_token = method_encode_signature (assembly, sig);
3916 token = mono_image_get_varargs_method_token (
3917 assembly, parent, method->name, sig_token);
3918 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
3919 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3920 ReflectionMethodBuilder rmb;
3921 guint32 parent, sig;
3923 reflection_methodbuilder_from_method_builder (&rmb, mb);
3924 rmb.opt_types = opt_param_types;
3926 sig = method_builder_encode_signature (assembly, &rmb);
3928 parent = mono_image_create_token (assembly, obj);
3929 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
3931 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
3932 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
3934 token = mono_image_get_varargs_method_token (
3935 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
3937 g_error ("requested method token for %s\n", klass->name);
3943 * mono_image_create_token:
3944 * @assembly: a dynamic assembly
3947 * Get a token to insert in the IL code stream for the given MemberInfo.
3948 * @obj can be one of:
3949 * ConstructorBuilder
3959 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3964 klass = obj->vtable->klass;
3965 if (strcmp (klass->name, "MethodBuilder") == 0) {
3966 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3968 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3969 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3971 token = mono_image_get_methodbuilder_token (assembly, mb);
3972 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3974 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3975 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3977 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3978 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3980 token = mono_image_get_ctorbuilder_token (assembly, mb);
3981 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3983 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3984 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3985 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3986 if (tb->generic_params) {
3987 token = mono_image_get_generic_field_token (assembly, fb);
3989 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3992 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3993 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3994 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3996 else if (strcmp (klass->name, "MonoType") == 0 ||
3997 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
3998 MonoReflectionType *tb = (MonoReflectionType *)obj;
3999 token = mono_metadata_token_from_dor (
4000 mono_image_typedef_or_ref (assembly, tb->type));
4002 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
4003 MonoReflectionType *tb = (MonoReflectionType *)obj;
4004 token = mono_metadata_token_from_dor (
4005 mono_image_typedef_or_ref (assembly, tb->type));
4007 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4008 strcmp (klass->name, "MonoMethod") == 0) {
4009 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4010 if (m->method->signature->is_inflated) {
4011 token = mono_image_get_methodspec_token (assembly, m->method);
4012 } else if (m->method->signature->generic_param_count) {
4013 g_assert_not_reached ();
4014 } else if ((m->method->klass->image == &assembly->image) &&
4015 !m->method->klass->generic_inst) {
4016 static guint32 method_table_idx = 0xffffff;
4017 if (m->method->klass->wastypebuilder) {
4018 /* we use the same token as the one that was assigned
4019 * to the Methodbuilder.
4020 * FIXME: do the equivalent for Fields.
4022 token = m->method->token;
4025 * Each token should have a unique index, but the indexes are
4026 * assigned by managed code, so we don't know about them. An
4027 * easy solution is to count backwards...
4029 method_table_idx --;
4030 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4033 token = mono_image_get_methodref_token (assembly, m->method);
4034 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4036 else if (strcmp (klass->name, "MonoField") == 0) {
4037 MonoReflectionField *f = (MonoReflectionField *)obj;
4038 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4039 static guint32 field_table_idx = 0xffffff;
4041 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4043 token = mono_image_get_fieldref_token (assembly, f);
4044 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4046 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4047 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4048 token = mono_image_get_array_token (assembly, m);
4050 else if (strcmp (klass->name, "SignatureHelper") == 0) {
4051 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4052 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4055 g_error ("requested token for %s\n", klass->name);
4057 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
4064 guint32 import_lookup_table;
4068 guint32 import_address_table_rva;
4076 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4078 static MonoDynamicImage*
4079 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
4080 char *assembly_name, char *module_name)
4082 static const guchar entrycode [16] = {0xff, 0x25, 0};
4083 MonoDynamicImage *image;
4087 * We need to use the current ms version or the ms runtime it won't find
4088 * the support dlls. D'oh!
4089 * const char *version = "mono-" VERSION;
4092 * To make binaries default to the .Net 1.0 version
4093 * const char *version = "v1.0.3705";
4095 const char *version = "v1.1.4322";
4098 image = GC_MALLOC (sizeof (MonoDynamicImage));
4100 image = g_new0 (MonoDynamicImage, 1);
4103 /* keep in sync with image.c */
4104 image->image.name = assembly_name;
4105 image->image.assembly_name = image->image.name; /* they may be different */
4106 image->image.module_name = module_name;
4107 image->image.version = g_strdup (version);
4108 image->image.dynamic = TRUE;
4110 image->image.references = g_new0 (MonoAssembly*, 1);
4111 image->image.references [0] = NULL;
4113 mono_image_init (&image->image);
4115 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4116 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4117 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4118 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4119 image->handleref = g_hash_table_new (NULL, NULL);
4120 image->tokens = mono_g_hash_table_new (NULL, NULL);
4121 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4122 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4123 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4125 string_heap_init (&image->sheap);
4126 mono_image_add_stream_data (&image->us, "", 1);
4127 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4128 /* import tables... */
4129 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4130 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4131 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4132 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4133 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4134 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4135 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4136 stream_data_align (&image->code);
4138 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4140 for (i=0; i < 64; ++i) {
4141 image->tables [i].next_idx = 1;
4142 image->tables [i].columns = table_sizes [i];
4145 image->image.assembly = (MonoAssembly*)assembly;
4146 image->run = assembly->run;
4147 image->save = assembly->save;
4153 * mono_image_basic_init:
4154 * @assembly: an assembly builder object
4156 * Create the MonoImage that represents the assembly builder and setup some
4157 * of the helper hash table and the basic metadata streams.
4160 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4162 MonoDynamicAssembly *assembly;
4163 MonoDynamicImage *image;
4165 MONO_ARCH_SAVE_REGS;
4167 if (assemblyb->dynamic_assembly)
4171 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4173 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4176 assembly->assembly.dynamic = TRUE;
4177 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4178 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4179 if (assemblyb->culture)
4180 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4182 assembly->assembly.aname.culture = g_strdup ("");
4184 assembly->run = assemblyb->access != 2;
4185 assembly->save = assemblyb->access != 1;
4187 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4188 assembly->assembly.aname.name = image->image.name;
4189 assembly->assembly.image = &image->image;
4191 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4192 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4196 calc_section_size (MonoDynamicImage *assembly)
4200 /* alignment constraints */
4201 assembly->code.index += 3;
4202 assembly->code.index &= ~3;
4203 assembly->meta_size += 3;
4204 assembly->meta_size &= ~3;
4205 assembly->resources.index += 3;
4206 assembly->resources.index &= ~3;
4208 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4209 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4212 if (assembly->win32_res) {
4213 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4215 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4216 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4220 assembly->sections [MONO_SECTION_RELOC].size = 12;
4221 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4231 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4235 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4237 ResTreeNode *t1 = (ResTreeNode*)a;
4238 ResTreeNode *t2 = (ResTreeNode*)b;
4240 return t1->id - t2->id;
4244 * resource_tree_create:
4246 * Organize the resources into a resource tree.
4248 static ResTreeNode *
4249 resource_tree_create (MonoArray *win32_resources)
4251 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4255 tree = g_new0 (ResTreeNode, 1);
4257 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4258 MonoReflectionWin32Resource *win32_res =
4259 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4263 lang_node = g_new0 (ResTreeNode, 1);
4264 lang_node->id = win32_res->lang_id;
4265 lang_node->win32_res = win32_res;
4267 /* Create type node if neccesary */
4269 for (l = tree->children; l; l = l->next)
4270 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4271 type_node = (ResTreeNode*)l->data;
4276 type_node = g_new0 (ResTreeNode, 1);
4277 type_node->id = win32_res->res_type;
4280 * The resource types have to be sorted otherwise
4281 * Windows Explorer can't display the version information.
4283 tree->children = g_slist_insert_sorted (tree->children, type_node,
4284 resource_tree_compare_by_id);
4287 /* Create res node if neccesary */
4289 for (l = type_node->children; l; l = l->next)
4290 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4291 res_node = (ResTreeNode*)l->data;
4296 res_node = g_new0 (ResTreeNode, 1);
4297 res_node->id = win32_res->res_id;
4298 type_node->children = g_slist_append (type_node->children, res_node);
4301 res_node->children = g_slist_append (res_node->children, lang_node);
4308 * resource_tree_encode:
4310 * Encode the resource tree into the format used in the PE file.
4313 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4316 MonoPEResourceDir dir;
4317 MonoPEResourceDirEntry dir_entry;
4318 MonoPEResourceDataEntry data_entry;
4322 * For the format of the resource directory, see the article
4323 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4327 memset (&dir, 0, sizeof (dir));
4328 memset (&dir_entry, 0, sizeof (dir_entry));
4329 memset (&data_entry, 0, sizeof (data_entry));
4331 g_assert (sizeof (dir) == 16);
4332 g_assert (sizeof (dir_entry) == 8);
4333 g_assert (sizeof (data_entry) == 16);
4335 node->offset = p - begin;
4337 /* IMAGE_RESOURCE_DIRECTORY */
4338 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4340 memcpy (p, &dir, sizeof (dir));
4343 /* Reserve space for entries */
4345 p += sizeof (dir_entry) * dir.res_id_entries;
4347 /* Write children */
4348 for (l = node->children; l; l = l->next) {
4349 ResTreeNode *child = (ResTreeNode*)l->data;
4351 if (child->win32_res) {
4353 child->offset = p - begin;
4355 /* IMAGE_RESOURCE_DATA_ENTRY */
4356 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4357 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4359 memcpy (p, &data_entry, sizeof (data_entry));
4360 p += sizeof (data_entry);
4362 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4363 p += data_entry.rde_size;
4366 resource_tree_encode (child, begin, p, &p);
4369 /* IMAGE_RESOURCE_ENTRY */
4370 for (l = node->children; l; l = l->next) {
4371 ResTreeNode *child = (ResTreeNode*)l->data;
4372 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4374 dir_entry.is_dir = child->win32_res ? 0 : 1;
4375 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4377 memcpy (entries, &dir_entry, sizeof (dir_entry));
4378 entries += sizeof (dir_entry);
4385 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4390 MonoReflectionWin32Resource *win32_res;
4393 if (!assemblyb->win32_resources)
4397 * Resources are stored in a three level tree inside the PE file.
4398 * - level one contains a node for each type of resource
4399 * - level two contains a node for each resource
4400 * - level three contains a node for each instance of a resource for a
4401 * specific language.
4404 tree = resource_tree_create (assemblyb->win32_resources);
4406 /* Estimate the size of the encoded tree */
4408 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4409 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4410 size += mono_array_length (win32_res->res_data);
4412 /* Directory structure */
4413 size += mono_array_length (assemblyb->win32_resources) * 256;
4414 p = buf = g_malloc (size);
4416 resource_tree_encode (tree, p, p, &p);
4418 g_assert (p - buf < size);
4420 assembly->win32_res = g_malloc (p - buf);
4421 assembly->win32_res_size = p - buf;
4422 memcpy (assembly->win32_res, buf, p - buf);
4428 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4430 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4433 p += sizeof (MonoPEResourceDir);
4434 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4435 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4436 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4437 if (dir_entry->is_dir)
4438 fixup_resource_directory (res_section, child, rva);
4440 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4441 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4444 p += sizeof (MonoPEResourceDirEntry);
4449 * mono_image_create_pefile:
4450 * @mb: a module builder object
4452 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4453 * assembly->pefile where it can be easily retrieved later in chunks.
4456 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4457 MonoMSDOSHeader *msdos;
4458 MonoDotNetHeader *header;
4459 MonoSectionTable *section;
4460 MonoCLIHeader *cli_header;
4461 guint32 size, image_size, virtual_base, text_offset;
4462 guint32 header_start, section_start, file_offset, virtual_offset;
4463 MonoDynamicImage *assembly;
4464 MonoReflectionAssemblyBuilder *assemblyb;
4465 MonoDynamicStream *pefile;
4467 guint32 *rva, value;
4470 static const unsigned char msheader[] = {
4471 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4472 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4475 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4476 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4477 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4478 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4481 assemblyb = mb->assemblyb;
4483 mono_image_basic_init (assemblyb);
4484 assembly = mb->dynamic_image;
4486 /* already created */
4487 if (assembly->pefile.index)
4490 mono_image_build_metadata (mb);
4492 if (mb->is_main && assemblyb->resources) {
4493 int len = mono_array_length (assemblyb->resources);
4494 for (i = 0; i < len; ++i)
4495 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4498 if (mb->resources) {
4499 int len = mono_array_length (mb->resources);
4500 for (i = 0; i < len; ++i)
4501 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4504 build_compressed_metadata (assembly);
4507 assembly_add_win32_resources (assembly, assemblyb);
4509 nsections = calc_section_size (assembly);
4511 pefile = &assembly->pefile;
4513 /* The DOS header and stub */
4514 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4515 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4517 /* the dotnet header */
4518 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4520 /* the section tables */
4521 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4523 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4524 virtual_offset = VIRT_ALIGN;
4527 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4528 if (!assembly->sections [i].size)
4531 file_offset += FILE_ALIGN - 1;
4532 file_offset &= ~(FILE_ALIGN - 1);
4533 virtual_offset += VIRT_ALIGN - 1;
4534 virtual_offset &= ~(VIRT_ALIGN - 1);
4536 assembly->sections [i].offset = file_offset;
4537 assembly->sections [i].rva = virtual_offset;
4539 file_offset += assembly->sections [i].size;
4540 virtual_offset += assembly->sections [i].size;
4541 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4544 file_offset += FILE_ALIGN - 1;
4545 file_offset &= ~(FILE_ALIGN - 1);
4546 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4548 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4550 /* back-patch info */
4551 msdos = (MonoMSDOSHeader*)pefile->data;
4552 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4553 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4554 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4556 header = (MonoDotNetHeader*)(pefile->data + header_start);
4557 header->pesig [0] = 'P';
4558 header->pesig [1] = 'E';
4560 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4561 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4562 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4563 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4564 if (assemblyb->pekind == 1) {
4566 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4569 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4572 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4574 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4575 header->pe.pe_major = 6;
4576 header->pe.pe_minor = 0;
4577 size = assembly->sections [MONO_SECTION_TEXT].size;
4578 size += FILE_ALIGN - 1;
4579 size &= ~(FILE_ALIGN - 1);
4580 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4581 size = assembly->sections [MONO_SECTION_RSRC].size;
4582 size += FILE_ALIGN - 1;
4583 size &= ~(FILE_ALIGN - 1);
4584 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4585 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4586 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4587 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4588 /* pe_rva_entry_point always at the beginning of the text section */
4589 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4591 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4592 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4593 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4594 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4595 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4596 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4597 size = section_start;
4598 size += FILE_ALIGN - 1;
4599 size &= ~(FILE_ALIGN - 1);
4600 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4602 size += VIRT_ALIGN - 1;
4603 size &= ~(VIRT_ALIGN - 1);
4604 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4607 // Translate the PEFileKind value to the value expected by the Windows loader
4613 // PEFileKinds.Dll == 1
4614 // PEFileKinds.ConsoleApplication == 2
4615 // PEFileKinds.WindowApplication == 3
4618 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4619 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4621 if (assemblyb->pekind == 3)
4626 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4628 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4629 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4630 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4631 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4632 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4633 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4635 /* fill data directory entries */
4637 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4638 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4640 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4641 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4643 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4644 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4645 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4646 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4647 /* patch imported function RVA name */
4648 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4649 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4651 /* the import table */
4652 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4653 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4654 /* patch imported dll RVA name and other entries in the dir */
4655 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4656 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4657 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4658 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4659 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4660 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4662 p = (assembly->code.data + assembly->ilt_offset);
4663 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4664 *p++ = (value) & 0xff;
4665 *p++ = (value >> 8) & (0xff);
4666 *p++ = (value >> 16) & (0xff);
4667 *p++ = (value >> 24) & (0xff);
4669 /* the CLI header info */
4670 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4671 cli_header->ch_size = GUINT32_FROM_LE (72);
4672 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4673 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4674 if (assemblyb->entry_point) {
4675 guint32 table_idx = 0;
4676 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4677 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4678 table_idx = methodb->table_idx;
4681 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4682 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4685 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4686 /* The embedded managed resources */
4687 text_offset = assembly->text_rva + assembly->code.index;
4688 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4689 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4690 text_offset += assembly->resources.index;
4691 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4692 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4693 text_offset += assembly->meta_size;
4694 if (assembly->strong_name_size) {
4695 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4696 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4697 text_offset += assembly->strong_name_size;
4700 /* write the section tables and section content */
4701 section = (MonoSectionTable*)(pefile->data + section_start);
4702 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4703 static const char *section_names [] = {
4704 ".text", ".rsrc", ".reloc"
4706 if (!assembly->sections [i].size)
4708 strcpy (section->st_name, section_names [i]);
4709 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4710 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4711 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4712 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4713 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4714 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4715 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4717 case MONO_SECTION_TEXT:
4718 /* patch entry point */
4719 p = (assembly->code.data + 2);
4720 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4721 *p++ = (value) & 0xff;
4722 *p++ = (value >> 8) & 0xff;
4723 *p++ = (value >> 16) & 0xff;
4724 *p++ = (value >> 24) & 0xff;
4726 text_offset = assembly->sections [i].offset;
4727 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4728 text_offset += assembly->code.index;
4729 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4730 text_offset += assembly->resources.index;
4731 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4732 text_offset += assembly->meta_size;
4733 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4735 g_free (assembly->image.raw_metadata);
4737 case MONO_SECTION_RELOC:
4738 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4739 *rva = GUINT32_FROM_LE (assembly->text_rva);
4741 *rva = GUINT32_FROM_LE (12);
4743 data16 = (guint16*)rva;
4745 * the entrypoint is always at the start of the text section
4746 * 3 is IMAGE_REL_BASED_HIGHLOW
4747 * 2 is patch_size_rva - text_rva
4749 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4751 *data16 = 0; /* terminate */
4753 case MONO_SECTION_RSRC:
4754 if (assembly->win32_res) {
4755 text_offset = assembly->sections [i].offset;
4757 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4758 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4760 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4764 g_assert_not_reached ();
4769 /* check that the file is properly padded */
4772 FILE *f = fopen ("mypetest.exe", "w");
4773 fwrite (pefile->data, pefile->index, 1, f);
4779 MonoReflectionModule *
4780 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4784 MonoImageOpenStatus status;
4785 MonoDynamicAssembly *assembly;
4787 name = mono_string_to_utf8 (fileName);
4789 image = mono_image_open (name, &status);
4792 if (status == MONO_IMAGE_ERROR_ERRNO)
4793 exc = mono_get_exception_file_not_found (fileName);
4795 exc = mono_get_exception_bad_image_format (name);
4797 mono_raise_exception (exc);
4802 assembly = ab->dynamic_assembly;
4803 image->assembly = (MonoAssembly*)assembly;
4805 mono_assembly_load_references (image, &status);
4807 mono_image_close (image);
4808 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4811 return mono_module_get_object (mono_domain_get (), image);
4815 * We need to return always the same object for MethodInfo, FieldInfo etc..
4816 * but we need to consider the reflected type.
4817 * type uses a different hash, since it uses custom hash/equal functions.
4822 MonoClass *refclass;
4826 reflected_equal (gconstpointer a, gconstpointer b) {
4827 const ReflectedEntry *ea = a;
4828 const ReflectedEntry *eb = b;
4830 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4834 reflected_hash (gconstpointer a) {
4835 const ReflectedEntry *ea = a;
4836 return GPOINTER_TO_UINT (ea->item);
4839 #define CHECK_OBJECT(t,p,k) \
4845 mono_domain_lock (domain); \
4846 if (!domain->refobject_hash) \
4847 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4848 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4849 mono_domain_unlock (domain); \
4855 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4857 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4860 #define CACHE_OBJECT(p,o,k) \
4862 ReflectedEntry *e = ALLOC_REFENTRY; \
4864 e->refclass = (k); \
4865 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4866 mono_domain_unlock (domain); \
4870 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4872 /* this is done only once */
4873 mono_domain_lock (domain);
4874 CACHE_OBJECT (assembly, res, NULL);
4878 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4880 /* this is done only once */
4881 mono_domain_lock (domain);
4882 CACHE_OBJECT (module, res, NULL);
4886 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4888 MonoDynamicImage *image = moduleb->dynamic_image;
4889 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4892 * FIXME: we already created an image in mono_image_basic_init (), but
4893 * we don't know which module it belongs to, since that is only
4894 * determined at assembly save time.
4896 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
4897 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4899 moduleb->module.image = &image->image;
4900 moduleb->dynamic_image = image;
4901 register_module (mono_object_domain (moduleb), moduleb, image);
4906 * mono_assembly_get_object:
4907 * @domain: an app domain
4908 * @assembly: an assembly
4910 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4912 MonoReflectionAssembly*
4913 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4915 static MonoClass *System_Reflection_Assembly;
4916 MonoReflectionAssembly *res;
4918 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4919 if (!System_Reflection_Assembly)
4920 System_Reflection_Assembly = mono_class_from_name (
4921 mono_defaults.corlib, "System.Reflection", "Assembly");
4922 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4923 res->assembly = assembly;
4924 CACHE_OBJECT (assembly, res, NULL);
4930 MonoReflectionModule*
4931 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4933 static MonoClass *System_Reflection_Module;
4934 MonoReflectionModule *res;
4936 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4937 if (!System_Reflection_Module)
4938 System_Reflection_Module = mono_class_from_name (
4939 mono_defaults.corlib, "System.Reflection", "Module");
4940 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4943 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4945 res->fqname = mono_string_new (domain, image->name);
4946 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4947 res->scopename = mono_string_new (domain, image->module_name);
4949 mono_image_addref (image);
4951 CACHE_OBJECT (image, res, NULL);
4955 MonoReflectionModule*
4956 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4958 static MonoClass *System_Reflection_Module;
4959 MonoReflectionModule *res;
4960 MonoTableInfo *table;
4961 guint32 cols [MONO_FILE_SIZE];
4963 guint32 i, name_idx;
4966 if (!System_Reflection_Module)
4967 System_Reflection_Module = mono_class_from_name (
4968 mono_defaults.corlib, "System.Reflection", "Module");
4969 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4971 table = &image->tables [MONO_TABLE_FILE];
4972 g_assert (table_index < table->rows);
4973 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4976 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4977 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4979 /* Check whenever the row has a corresponding row in the moduleref table */
4980 table = &image->tables [MONO_TABLE_MODULEREF];
4981 for (i = 0; i < table->rows; ++i) {
4982 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4983 val = mono_metadata_string_heap (image, name_idx);
4984 if (strcmp (val, name) == 0)
4985 res->image = image->modules [i];
4988 res->fqname = mono_string_new (domain, name);
4989 res->name = mono_string_new (domain, name);
4990 res->scopename = mono_string_new (domain, name);
4991 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4997 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4999 if ((t1->type != t2->type) ||
5000 (t1->byref != t2->byref))
5004 case MONO_TYPE_VOID:
5005 case MONO_TYPE_BOOLEAN:
5006 case MONO_TYPE_CHAR:
5017 case MONO_TYPE_STRING:
5020 case MONO_TYPE_OBJECT:
5021 case MONO_TYPE_TYPEDBYREF:
5023 case MONO_TYPE_VALUETYPE:
5024 case MONO_TYPE_CLASS:
5025 case MONO_TYPE_SZARRAY:
5026 return t1->data.klass == t2->data.klass;
5028 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5029 case MONO_TYPE_ARRAY:
5030 if (t1->data.array->rank != t2->data.array->rank)
5032 return t1->data.array->eklass == t2->data.array->eklass;
5033 case MONO_TYPE_GENERICINST: {
5035 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5037 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5039 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5040 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5046 case MONO_TYPE_MVAR:
5047 return t1->data.generic_param == t2->data.generic_param;
5049 g_error ("implement type compare for %0x!", t1->type);
5057 mymono_metadata_type_hash (MonoType *t1)
5063 hash |= t1->byref << 6; /* do not collide with t1->type values */
5065 case MONO_TYPE_VALUETYPE:
5066 case MONO_TYPE_CLASS:
5067 case MONO_TYPE_SZARRAY:
5068 /* check if the distribution is good enough */
5069 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5071 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5076 static MonoReflectionGenericInst*
5077 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5079 static MonoClass *System_Reflection_MonoGenericInst;
5080 MonoReflectionGenericInst *res;
5081 MonoGenericInst *ginst;
5084 if (!System_Reflection_MonoGenericInst) {
5085 System_Reflection_MonoGenericInst = mono_class_from_name (
5086 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5087 g_assert (System_Reflection_MonoGenericInst);
5090 ginst = geninst->data.generic_inst;
5091 gklass = mono_class_from_mono_type (ginst->generic_type);
5093 mono_class_init (ginst->klass);
5095 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5097 res->type.type = geninst;
5098 if (gklass->wastypebuilder && gklass->reflection_info)
5099 res->generic_type = gklass->reflection_info;
5101 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5107 * mono_type_get_object:
5108 * @domain: an app domain
5111 * Return an System.MonoType object representing the type @type.
5114 mono_type_get_object (MonoDomain *domain, MonoType *type)
5116 MonoReflectionType *res;
5117 MonoClass *klass = mono_class_from_mono_type (type);
5119 mono_domain_lock (domain);
5120 if (!domain->type_hash)
5121 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5122 (GCompareFunc)mymono_metadata_type_equal);
5123 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5124 mono_domain_unlock (domain);
5127 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5128 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5129 mono_g_hash_table_insert (domain->type_hash, type, res);
5130 mono_domain_unlock (domain);
5133 if (klass->reflection_info && !klass->wastypebuilder) {
5134 /* g_assert_not_reached (); */
5135 /* should this be considered an error condition? */
5137 mono_domain_unlock (domain);
5138 return klass->reflection_info;
5141 mono_class_init (klass);
5142 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5144 mono_g_hash_table_insert (domain->type_hash, type, res);
5145 mono_domain_unlock (domain);
5150 * mono_method_get_object:
5151 * @domain: an app domain
5153 * @refclass: the reflected type (can be NULL)
5155 * Return an System.Reflection.MonoMethod object representing the method @method.
5157 MonoReflectionMethod*
5158 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5161 * We use the same C representation for methods and constructors, but the type
5162 * name in C# is different.
5166 MonoReflectionMethod *ret;
5169 refclass = method->klass;
5171 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5172 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5173 cname = "MonoCMethod";
5175 cname = "MonoMethod";
5176 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5178 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5179 ret->method = method;
5180 ret->name = mono_string_new (domain, method->name);
5181 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5182 CACHE_OBJECT (method, ret, refclass);
5187 * mono_field_get_object:
5188 * @domain: an app domain
5192 * Return an System.Reflection.MonoField object representing the field @field
5195 MonoReflectionField*
5196 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5198 MonoReflectionField *res;
5201 CHECK_OBJECT (MonoReflectionField *, field, klass);
5202 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5203 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5206 res->name = mono_string_new (domain, field->name);
5207 res->attrs = field->type->attrs;
5208 res->type = mono_type_get_object (domain, field->type);
5209 CACHE_OBJECT (field, res, klass);
5214 * mono_property_get_object:
5215 * @domain: an app domain
5217 * @property: a property
5219 * Return an System.Reflection.MonoProperty object representing the property @property
5222 MonoReflectionProperty*
5223 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5225 MonoReflectionProperty *res;
5228 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5229 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5230 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5232 res->property = property;
5233 CACHE_OBJECT (property, res, klass);
5238 * mono_event_get_object:
5239 * @domain: an app domain
5243 * Return an System.Reflection.MonoEvent object representing the event @event
5246 MonoReflectionEvent*
5247 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5249 MonoReflectionEvent *res;
5252 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5253 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5254 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5257 CACHE_OBJECT (event, res, klass);
5262 * mono_param_get_objects:
5263 * @domain: an app domain
5266 * Return an System.Reflection.ParameterInfo array object representing the parameters
5267 * in the method @method.
5270 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5272 static MonoClass *System_Reflection_ParameterInfo;
5273 static MonoClassField *dbnull_value_field;
5275 MonoArray *res = NULL;
5276 MonoReflectionMethod *member = NULL;
5277 MonoReflectionParameter *param = NULL;
5281 if (!dbnull_value_field) {
5282 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5283 mono_class_init (klass);
5284 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5285 g_assert (dbnull_value_field);
5288 if (!System_Reflection_ParameterInfo)
5289 System_Reflection_ParameterInfo = mono_class_from_name (
5290 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5292 if (!method->signature->param_count)
5293 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5295 /* Note: the cache is based on the address of the signature into the method
5296 * since we already cache MethodInfos with the method as keys.
5298 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5300 member = mono_method_get_object (domain, method, NULL);
5301 names = g_new (char *, method->signature->param_count);
5302 mono_method_get_param_names (method, (const char **) names);
5304 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5305 for (i = 0; i < method->signature->param_count; ++i) {
5306 param = (MonoReflectionParameter *)mono_object_new (domain,
5307 System_Reflection_ParameterInfo);
5308 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5309 param->DefaultValueImpl = mono_field_get_value_object (domain, dbnull_value_field, NULL); /* FIXME */
5310 param->MemberImpl = (MonoObject*)member;
5311 param->NameImpl = mono_string_new (domain, names [i]);
5312 param->PositionImpl = i;
5313 param->AttrsImpl = method->signature->params [i]->attrs;
5314 mono_array_set (res, gpointer, i, param);
5317 CACHE_OBJECT (&(method->signature), res, NULL);
5322 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5326 memset (assembly, 0, sizeof (MonoAssemblyName));
5328 assembly->culture = "";
5329 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5331 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5334 while (*p == ' ' || *p == ',') {
5343 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5345 assembly->major = strtoul (p, &s, 10);
5346 if (s == p || *s != '.')
5349 assembly->minor = strtoul (p, &s, 10);
5350 if (s == p || *s != '.')
5353 assembly->build = strtoul (p, &s, 10);
5354 if (s == p || *s != '.')
5357 assembly->revision = strtoul (p, &s, 10);
5361 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5363 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5364 assembly->culture = "";
5367 assembly->culture = p;
5368 while (*p && *p != ',') {
5372 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5374 if (strncmp (p, "null", 4) == 0) {
5379 while (*p && *p != ',') {
5382 len = (p - start + 1);
5383 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5384 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5385 g_strlcpy (assembly->public_key_token, start, len);
5388 while (*p && *p != ',')
5392 while (*p == ' ' || *p == ',') {
5406 * mono_reflection_parse_type:
5409 * Parse a type name as accepted by the GetType () method and output the info
5410 * extracted in the info structure.
5411 * the name param will be mangled, so, make a copy before passing it to this function.
5412 * The fields in info will be valid until the memory pointed to by name is valid.
5413 * Returns 0 on parse error.
5414 * See also mono_type_get_name () below.
5417 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5419 char *start, *p, *w, *last_point, *startn;
5420 int in_modifiers = 0;
5421 int isbyref = 0, rank;
5423 start = p = w = name;
5425 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5426 info->name = info->name_space = NULL;
5427 info->nested = NULL;
5428 info->modifiers = NULL;
5430 /* last_point separates the namespace from the name */
5436 *p = 0; /* NULL terminate the name */
5438 info->nested = g_list_append (info->nested, startn);
5439 /* we have parsed the nesting namespace + name */
5443 info->name_space = start;
5445 info->name = last_point + 1;
5447 info->name_space = (char *)"";
5473 info->name_space = start;
5475 info->name = last_point + 1;
5477 info->name_space = (char *)"";
5484 if (isbyref) /* only one level allowed by the spec */
5487 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5491 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5502 else if (*p != '*') /* '*' means unknown lower bound */
5508 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5520 return 0; /* missing assembly name */
5521 if (!assembly_name_to_aname (&info->assembly, p))
5528 if (info->assembly.name)
5531 *w = 0; /* terminate class name */
5532 if (!info->name || !*info->name)
5534 /* add other consistency checks */
5539 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5546 image = mono_defaults.corlib;
5549 klass = mono_class_from_name_case (image, info->name_space, info->name);
5551 klass = mono_class_from_name (image, info->name_space, info->name);
5554 for (mod = info->nested; mod; mod = mod->next) {
5557 mono_class_init (klass);
5558 nested = klass->nested_classes;
5561 klass = nested->data;
5563 if (g_strcasecmp (klass->name, mod->data) == 0)
5566 if (strcmp (klass->name, mod->data) == 0)
5570 nested = nested->next;
5577 mono_class_init (klass);
5578 for (mod = info->modifiers; mod; mod = mod->next) {
5579 modval = GPOINTER_TO_UINT (mod->data);
5580 if (!modval) { /* byref: must be last modifier */
5581 return &klass->this_arg;
5582 } else if (modval == -1) {
5583 klass = mono_ptr_class_get (&klass->byval_arg);
5584 } else { /* array rank */
5585 klass = mono_array_class_get (klass, modval);
5587 mono_class_init (klass);
5590 return &klass->byval_arg;
5594 * mono_reflection_get_type:
5595 * @image: a metadata context
5596 * @info: type description structure
5597 * @ignorecase: flag for case-insensitive string compares
5599 * Build a MonoType from the type description in @info.
5604 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5607 MonoReflectionAssembly *assembly;
5611 type = mono_reflection_get_type_internal (image, info, ignorecase);
5614 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5617 /* Reconstruct the type name */
5618 fullName = g_string_new ("");
5619 if (info->name_space && (info->name_space [0] != '\0'))
5620 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5622 g_string_printf (fullName, info->name);
5623 for (mod = info->nested; mod; mod = mod->next)
5624 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5627 mono_domain_try_type_resolve (
5628 mono_domain_get (), fullName->str, NULL);
5629 if (assembly && (!image || (assembly->assembly->image == image))) {
5631 if (assembly->assembly->dynamic) {
5632 /* Enumerate all modules */
5633 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5637 if (abuilder->modules) {
5638 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5639 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5640 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5646 if (!type && abuilder->loaded_modules) {
5647 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5648 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5649 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5656 type = mono_reflection_get_type_internal (assembly->assembly->image,
5659 g_string_free (fullName, TRUE);
5664 * mono_reflection_type_from_name:
5666 * @image: a metadata context (can be NULL).
5668 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5669 * it defaults to get the type from @image or, if @image is NULL or loading
5670 * from it fails, uses corlib.
5674 mono_reflection_type_from_name (char *name, MonoImage *image)
5677 MonoTypeNameParse info;
5678 MonoAssembly *assembly;
5681 /* Make a copy since parse_type modifies its argument */
5682 tmp = g_strdup (name);
5684 /*g_print ("requested type %s\n", str);*/
5685 if (!mono_reflection_parse_type (tmp, &info)) {
5687 g_list_free (info.modifiers);
5688 g_list_free (info.nested);
5692 if (info.assembly.name) {
5693 assembly = mono_assembly_loaded (&info.assembly);
5695 /* then we must load the assembly ourselve - see #60439 */
5696 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5699 g_list_free (info.modifiers);
5700 g_list_free (info.nested);
5704 image = assembly->image;
5705 } else if (image == NULL) {
5706 image = mono_defaults.corlib;
5709 type = mono_reflection_get_type (image, &info, FALSE);
5710 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5711 image = mono_defaults.corlib;
5712 type = mono_reflection_get_type (image, &info, FALSE);
5716 g_list_free (info.modifiers);
5717 g_list_free (info.nested);
5722 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5724 int slen, type = t->type;
5729 case MONO_TYPE_BOOLEAN: {
5730 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5735 case MONO_TYPE_CHAR:
5737 case MONO_TYPE_I2: {
5738 guint16 *val = g_malloc (sizeof (guint16));
5743 #if SIZEOF_VOID_P == 4
5749 case MONO_TYPE_I4: {
5750 guint32 *val = g_malloc (sizeof (guint32));
5755 #if SIZEOF_VOID_P == 8
5756 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5761 case MONO_TYPE_I8: {
5762 guint64 *val = g_malloc (sizeof (guint64));
5767 case MONO_TYPE_VALUETYPE:
5768 if (t->data.klass->enumtype) {
5769 type = t->data.klass->enum_basetype->type;
5772 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5775 case MONO_TYPE_STRING:
5776 if (*p == (char)0xFF) {
5780 slen = mono_metadata_decode_value (p, &p);
5782 return mono_string_new_len (mono_domain_get (), p, slen);
5783 case MONO_TYPE_CLASS: {
5786 if (*p == (char)0xFF) {
5791 slen = mono_metadata_decode_value (p, &p);
5792 n = g_memdup (p, slen + 1);
5794 t = mono_reflection_type_from_name (n, image);
5796 g_warning ("Cannot load type '%s'", n);
5800 return mono_type_get_object (mono_domain_get (), t);
5804 case MONO_TYPE_OBJECT: {
5807 MonoClass *subc = NULL;
5812 } else if (subt == 0x0E) {
5813 type = MONO_TYPE_STRING;
5815 } else if (subt == 0x55) {
5818 slen = mono_metadata_decode_value (p, &p);
5819 n = g_memdup (p, slen + 1);
5821 t = mono_reflection_type_from_name (n, image);
5823 g_warning ("Cannot load type '%s'", n);
5826 subc = mono_class_from_mono_type (t);
5827 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5828 MonoType simple_type = {{0}};
5829 simple_type.type = subt;
5830 subc = mono_class_from_mono_type (&simple_type);
5832 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5834 val = load_cattr_value (image, &subc->byval_arg, p, end);
5835 obj = mono_object_new (mono_domain_get (), subc);
5836 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5840 case MONO_TYPE_SZARRAY:
5843 guint32 i, alen, basetype;
5846 if (alen == 0xffffffff) {
5850 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5851 basetype = t->data.klass->byval_arg.type;
5856 case MONO_TYPE_BOOLEAN:
5857 for (i=0;i<alen;i++)
5859 MonoBoolean val=*p++;
5860 mono_array_set(arr,MonoBoolean,i,val);
5863 case MONO_TYPE_CHAR:
5866 for (i=0;i<alen;i++)
5868 guint16 val=read16(p);
5869 mono_array_set(arr,guint16,i,val);
5876 for (i=0;i<alen;i++)
5878 guint32 val=read32(p);
5879 mono_array_set(arr,guint32,i,val);
5886 for (i=0;i<alen;i++)
5888 guint64 val=read64(p);
5889 mono_array_set(arr,guint64,i,val);
5893 case MONO_TYPE_CLASS:
5894 case MONO_TYPE_OBJECT:
5895 case MONO_TYPE_STRING:
5896 for (i = 0; i < alen; i++) {
5897 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5898 mono_array_set (arr, gpointer, i, item);
5902 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5908 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5914 type_is_reference (MonoType *type)
5916 switch (type->type) {
5917 case MONO_TYPE_BOOLEAN:
5918 case MONO_TYPE_CHAR:
5931 case MONO_TYPE_VALUETYPE:
5939 free_param_data (MonoMethodSignature *sig, void **params) {
5941 for (i = 0; i < sig->param_count; ++i) {
5942 if (!type_is_reference (sig->params [i]))
5943 g_free (params [i]);
5948 * Find the method index in the metadata methodDef table.
5949 * Later put these three helper methods in metadata and export them.
5952 find_method_index (MonoMethod *method) {
5953 MonoClass *klass = method->klass;
5956 for (i = 0; i < klass->method.count; ++i) {
5957 if (method == klass->methods [i])
5958 return klass->method.first + 1 + i;
5964 * Find the field index in the metadata FieldDef table.
5967 find_field_index (MonoClass *klass, MonoClassField *field) {
5970 for (i = 0; i < klass->field.count; ++i) {
5971 if (field == &klass->fields [i])
5972 return klass->field.first + 1 + i;
5978 * Find the property index in the metadata Property table.
5981 find_property_index (MonoClass *klass, MonoProperty *property) {
5984 for (i = 0; i < klass->property.count; ++i) {
5985 if (property == &klass->properties [i])
5986 return klass->property.first + 1 + i;
5992 * Find the event index in the metadata Event table.
5995 find_event_index (MonoClass *klass, MonoEvent *event) {
5998 for (i = 0; i < klass->event.count; ++i) {
5999 if (event == &klass->events [i])
6000 return klass->event.first + 1 + i;
6006 create_custom_attr (MonoImage *image, MonoMethod *method,
6007 const char *data, guint32 len)
6009 const char *p = data;
6011 guint32 i, j, num_named;
6015 mono_class_init (method->klass);
6018 attr = mono_object_new (mono_domain_get (), method->klass);
6019 mono_runtime_invoke (method, attr, NULL, NULL);
6023 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6026 /*g_print ("got attr %s\n", method->klass->name);*/
6028 params = g_new (void*, method->signature->param_count);
6032 for (i = 0; i < method->signature->param_count; ++i) {
6033 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6037 attr = mono_object_new (mono_domain_get (), method->klass);
6038 mono_runtime_invoke (method, attr, params, NULL);
6039 free_param_data (method->signature, params);
6041 num_named = read16 (named);
6043 for (j = 0; j < num_named; j++) {
6045 char *name, named_type, data_type;
6046 named_type = *named++;
6047 data_type = *named++; /* type of data */
6048 if (data_type == 0x55) {
6051 type_len = mono_metadata_decode_blob_size (named, &named);
6052 type_name = g_malloc (type_len + 1);
6053 memcpy (type_name, named, type_len);
6054 type_name [type_len] = 0;
6056 /* FIXME: lookup the type and check type consistency */
6057 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6058 /* this seems to be the type of the element of the array */
6059 /* g_print ("skipping 0x%02x after prop\n", *named); */
6062 name_len = mono_metadata_decode_blob_size (named, &named);
6063 name = g_malloc (name_len + 1);
6064 memcpy (name, named, name_len);
6065 name [name_len] = 0;
6067 if (named_type == 0x53) {
6068 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6069 void *val = load_cattr_value (image, field->type, named, &named);
6070 mono_field_set_value (attr, field, val);
6071 if (!type_is_reference (field->type))
6073 } else if (named_type == 0x54) {
6076 MonoType *prop_type;
6078 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6079 /* can we have more that 1 arg in a custom attr named property? */
6080 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6081 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6082 mono_property_set_value (prop, attr, pparams, NULL);
6083 if (!type_is_reference (prop_type))
6084 g_free (pparams [0]);
6093 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6100 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6101 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6102 for (i = 0; i < cinfo->num_attrs; ++i) {
6103 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6104 mono_array_set (result, gpointer, i, attr);
6110 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6112 guint32 mtoken, i, len;
6113 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6115 MonoCustomAttrInfo *ainfo;
6116 GList *tmp, *list = NULL;
6119 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6121 i = mono_metadata_custom_attrs_from_index (image, idx);
6125 while (i < ca->rows) {
6126 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6128 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6131 len = g_list_length (list);
6134 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6135 ainfo->num_attrs = len;
6136 ainfo->image = image;
6137 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6138 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6139 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6140 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6141 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6142 mtoken |= MONO_TOKEN_METHOD_DEF;
6144 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6145 mtoken |= MONO_TOKEN_MEMBER_REF;
6148 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6151 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6152 if (!ainfo->attrs [i].ctor)
6153 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6154 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6155 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6156 ainfo->attrs [i].data = data;
6164 mono_custom_attrs_from_method (MonoMethod *method)
6166 MonoCustomAttrInfo *cinfo;
6169 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6171 idx = find_method_index (method);
6172 idx <<= MONO_CUSTOM_ATTR_BITS;
6173 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6174 return mono_custom_attrs_from_index (method->klass->image, idx);
6178 mono_custom_attrs_from_class (MonoClass *klass)
6180 MonoCustomAttrInfo *cinfo;
6183 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6185 idx = mono_metadata_token_index (klass->type_token);
6186 idx <<= MONO_CUSTOM_ATTR_BITS;
6187 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6188 return mono_custom_attrs_from_index (klass->image, idx);
6192 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6194 MonoCustomAttrInfo *cinfo;
6197 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6199 idx = 1; /* there is only one assembly */
6200 idx <<= MONO_CUSTOM_ATTR_BITS;
6201 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6202 return mono_custom_attrs_from_index (assembly->image, idx);
6205 static MonoCustomAttrInfo*
6206 mono_custom_attrs_from_module (MonoImage *image)
6208 MonoCustomAttrInfo *cinfo;
6211 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6213 idx = 1; /* there is only one module */
6214 idx <<= MONO_CUSTOM_ATTR_BITS;
6215 idx |= MONO_CUSTOM_ATTR_MODULE;
6216 return mono_custom_attrs_from_index (image, idx);
6220 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6222 MonoCustomAttrInfo *cinfo;
6225 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6227 idx = find_property_index (klass, property);
6228 idx <<= MONO_CUSTOM_ATTR_BITS;
6229 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6230 return mono_custom_attrs_from_index (klass->image, idx);
6234 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6236 MonoCustomAttrInfo *cinfo;
6239 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6241 idx = find_event_index (klass, event);
6242 idx <<= MONO_CUSTOM_ATTR_BITS;
6243 idx |= MONO_CUSTOM_ATTR_EVENT;
6244 return mono_custom_attrs_from_index (klass->image, idx);
6248 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6250 MonoCustomAttrInfo *cinfo;
6253 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6255 idx = find_field_index (klass, field);
6256 idx <<= MONO_CUSTOM_ATTR_BITS;
6257 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6258 return mono_custom_attrs_from_index (klass->image, idx);
6262 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6265 guint32 i, idx, method_index;
6266 guint32 param_list, param_last, param_pos, found;
6268 MonoReflectionMethodAux *aux;
6270 if (method->klass->image->dynamic) {
6271 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6272 if (!aux || !aux->param_cattr)
6274 return aux->param_cattr [param];
6277 image = method->klass->image;
6278 method_index = find_method_index (method);
6279 ca = &image->tables [MONO_TABLE_METHOD];
6281 if (method->klass->generic_inst || method->klass->gen_params ||
6282 method->signature->generic_param_count) {
6283 /* FIXME FIXME FIXME */
6287 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6288 if (method_index == ca->rows) {
6289 ca = &image->tables [MONO_TABLE_PARAM];
6290 param_last = ca->rows + 1;
6292 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6293 ca = &image->tables [MONO_TABLE_PARAM];
6296 for (i = param_list; i < param_last; ++i) {
6297 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6298 if (param_pos == param) {
6306 idx <<= MONO_CUSTOM_ATTR_BITS;
6307 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6308 return mono_custom_attrs_from_index (image, idx);
6312 * mono_reflection_get_custom_attrs:
6313 * @obj: a reflection object handle
6315 * Return an array with all the custom attributes defined of the
6316 * reflection handle @obj. The objects are fully build.
6319 mono_reflection_get_custom_attrs (MonoObject *obj)
6323 MonoCustomAttrInfo *cinfo = NULL;
6325 MONO_ARCH_SAVE_REGS;
6327 klass = obj->vtable->klass;
6328 /* FIXME: need to handle: Module */
6329 if (klass == mono_defaults.monotype_class) {
6330 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6331 klass = mono_class_from_mono_type (rtype->type);
6332 cinfo = mono_custom_attrs_from_class (klass);
6333 } else if (strcmp ("Assembly", klass->name) == 0) {
6334 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6335 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6336 } else if (strcmp ("Module", klass->name) == 0) {
6337 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6338 cinfo = mono_custom_attrs_from_module (module->image);
6339 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6340 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6341 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6342 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6343 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6344 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6345 } else if (strcmp ("MonoField", klass->name) == 0) {
6346 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6347 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6348 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6349 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6350 cinfo = mono_custom_attrs_from_method (rmethod->method);
6351 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6352 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6353 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6354 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6355 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6356 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6357 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6358 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6359 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6360 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6361 } else { /* handle other types here... */
6362 g_error ("get custom attrs not yet supported for %s", klass->name);
6366 result = mono_custom_attrs_construct (cinfo);
6368 mono_custom_attrs_free (cinfo);
6370 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6371 result = mono_array_new (mono_domain_get (), klass, 0);
6377 static MonoMethodSignature*
6378 parameters_to_signature (MonoArray *parameters) {
6379 MonoMethodSignature *sig;
6382 count = parameters? mono_array_length (parameters): 0;
6384 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6385 sig->param_count = count;
6386 sig->sentinelpos = -1; /* FIXME */
6387 for (i = 0; i < count; ++i) {
6388 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6389 sig->params [i] = pt->type;
6394 static MonoMethodSignature*
6395 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6396 MonoMethodSignature *sig;
6398 sig = parameters_to_signature (ctor->parameters);
6399 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6400 sig->ret = &mono_defaults.void_class->byval_arg;
6404 static MonoMethodSignature*
6405 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6406 MonoMethodSignature *sig;
6408 sig = parameters_to_signature (method->parameters);
6409 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6410 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6411 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6415 static MonoMethodSignature*
6416 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6417 MonoMethodSignature *sig;
6419 sig = parameters_to_signature (method->parameters);
6420 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6421 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6422 sig->generic_param_count = 0;
6427 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6429 MonoClass *klass = mono_object_class (prop);
6430 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6431 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6432 *name = mono_string_to_utf8 (pb->name);
6433 *type = pb->type->type;
6435 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6436 *name = g_strdup (p->property->name);
6437 if (p->property->get)
6438 *type = p->property->get->signature->ret;
6440 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6445 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6447 MonoClass *klass = mono_object_class (field);
6448 if (strcmp (klass->name, "FieldBuilder") == 0) {
6449 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6450 *name = mono_string_to_utf8 (fb->name);
6451 *type = fb->type->type;
6453 MonoReflectionField *f = (MonoReflectionField *)field;
6454 *name = g_strdup (f->field->name);
6455 *type = f->field->type;
6460 * Encode a value in a custom attribute stream of bytes.
6461 * The value to encode is either supplied as an object in argument val
6462 * (valuetypes are boxed), or as a pointer to the data in the
6464 * @type represents the type of the value
6465 * @buffer is the start of the buffer
6466 * @p the current position in the buffer
6467 * @buflen contains the size of the buffer and is used to return the new buffer size
6468 * if this needs to be realloced.
6469 * @retbuffer and @retp return the start and the position of the buffer
6472 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6474 MonoTypeEnum simple_type;
6476 if ((p-buffer) + 10 >= *buflen) {
6479 newbuf = g_realloc (buffer, *buflen);
6480 p = newbuf + (p-buffer);
6484 argval = ((char*)arg + sizeof (MonoObject));
6485 simple_type = type->type;
6487 switch (simple_type) {
6488 case MONO_TYPE_BOOLEAN:
6493 case MONO_TYPE_CHAR:
6496 swap_with_size (p, argval, 2, 1);
6502 swap_with_size (p, argval, 4, 1);
6508 swap_with_size (p, argval, 8, 1);
6511 case MONO_TYPE_VALUETYPE:
6512 if (type->data.klass->enumtype) {
6513 simple_type = type->data.klass->enum_basetype->type;
6516 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6519 case MONO_TYPE_STRING: {
6526 str = mono_string_to_utf8 ((MonoString*)arg);
6527 slen = strlen (str);
6528 if ((p-buffer) + 10 + slen >= *buflen) {
6532 newbuf = g_realloc (buffer, *buflen);
6533 p = newbuf + (p-buffer);
6536 mono_metadata_encode_value (slen, p, &p);
6537 memcpy (p, str, slen);
6542 case MONO_TYPE_CLASS: {
6550 k = mono_object_class (arg);
6551 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6552 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6553 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6555 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6556 slen = strlen (str);
6557 if ((p-buffer) + 10 + slen >= *buflen) {
6561 newbuf = g_realloc (buffer, *buflen);
6562 p = newbuf + (p-buffer);
6565 mono_metadata_encode_value (slen, p, &p);
6566 memcpy (p, str, slen);
6571 case MONO_TYPE_SZARRAY: {
6573 MonoClass *eclass, *arg_eclass;
6576 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6579 len = mono_array_length ((MonoArray*)arg);
6581 *p++ = (len >> 8) & 0xff;
6582 *p++ = (len >> 16) & 0xff;
6583 *p++ = (len >> 24) & 0xff;
6585 *retbuffer = buffer;
6586 eclass = type->data.klass;
6587 arg_eclass = mono_object_class (arg)->element_class;
6588 if (eclass->valuetype && arg_eclass->valuetype) {
6589 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6590 int elsize = mono_class_array_element_size (eclass);
6591 for (i = 0; i < len; ++i) {
6592 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6596 for (i = 0; i < len; ++i) {
6597 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6602 /* it may be a boxed value or a Type */
6603 case MONO_TYPE_OBJECT: {
6604 MonoClass *klass = mono_object_class (arg);
6608 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6611 } else if (klass->enumtype) {
6613 } else if (klass == mono_defaults.string_class) {
6614 simple_type = MONO_TYPE_STRING;
6617 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6618 *p++ = simple_type = klass->byval_arg.type;
6621 g_error ("unhandled type in custom attr");
6623 str = type_get_qualified_name (klass->enum_basetype, NULL);
6624 slen = strlen (str);
6625 if ((p-buffer) + 10 + slen >= *buflen) {
6629 newbuf = g_realloc (buffer, *buflen);
6630 p = newbuf + (p-buffer);
6633 mono_metadata_encode_value (slen, p, &p);
6634 memcpy (p, str, slen);
6637 simple_type = klass->enum_basetype->type;
6641 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6644 *retbuffer = buffer;
6648 * mono_reflection_get_custom_attrs_blob:
6649 * @ctor: custom attribute constructor
6650 * @ctorArgs: arguments o the constructor
6656 * Creates the blob of data that needs to be saved in the metadata and that represents
6657 * the custom attributed described by @ctor, @ctorArgs etc.
6658 * Returns: a Byte array representing the blob of data.
6661 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6664 MonoMethodSignature *sig;
6669 MONO_ARCH_SAVE_REGS;
6671 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6672 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6674 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6676 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6678 p = buffer = g_malloc (buflen);
6679 /* write the prolog */
6682 for (i = 0; i < sig->param_count; ++i) {
6683 arg = mono_array_get (ctorArgs, MonoObject*, i);
6684 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
6688 i += mono_array_length (properties);
6690 i += mono_array_length (fields);
6692 *p++ = (i >> 8) & 0xff;
6695 for (i = 0; i < mono_array_length (properties); ++i) {
6700 prop = mono_array_get (properties, gpointer, i);
6701 get_prop_name_and_type (prop, &pname, &ptype);
6702 *p++ = 0x54; /* PROPERTY signature */
6704 /* Preallocate a large enough buffer */
6705 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6706 char *str = type_get_qualified_name (ptype, NULL);
6712 len += strlen (pname);
6714 if ((p-buffer) + 20 + len >= buflen) {
6718 newbuf = g_realloc (buffer, buflen);
6719 p = newbuf + (p-buffer);
6723 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6724 char *str = type_get_qualified_name (ptype, NULL);
6725 int slen = strlen (str);
6729 * This seems to be optional...
6732 mono_metadata_encode_value (slen, p, &p);
6733 memcpy (p, str, slen);
6737 mono_metadata_encode_value (ptype->type, p, &p);
6738 if (ptype->type == MONO_TYPE_SZARRAY)
6739 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6741 len = strlen (pname);
6742 mono_metadata_encode_value (len, p, &p);
6743 memcpy (p, pname, len);
6745 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
6752 for (i = 0; i < mono_array_length (fields); ++i) {
6757 field = mono_array_get (fields, gpointer, i);
6758 get_field_name_and_type (field, &fname, &ftype);
6759 *p++ = 0x53; /* FIELD signature */
6760 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6761 char *str = type_get_qualified_name (ftype, NULL);
6762 int slen = strlen (str);
6763 if ((p-buffer) + 10 + slen >= buflen) {
6767 newbuf = g_realloc (buffer, buflen);
6768 p = newbuf + (p-buffer);
6773 * This seems to be optional...
6776 mono_metadata_encode_value (slen, p, &p);
6777 memcpy (p, str, slen);
6781 mono_metadata_encode_value (ftype->type, p, &p);
6782 if (ftype->type == MONO_TYPE_SZARRAY)
6783 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
6785 len = strlen (fname);
6786 mono_metadata_encode_value (len, p, &p);
6787 memcpy (p, fname, len);
6789 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
6794 g_assert (p - buffer <= buflen);
6795 buflen = p - buffer;
6796 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6797 p = mono_array_addr (result, char, 0);
6798 memcpy (p, buffer, buflen);
6800 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6806 * mono_reflection_setup_internal_class:
6807 * @tb: a TypeBuilder object
6809 * Creates a MonoClass that represents the TypeBuilder.
6810 * This is a trick that lets us simplify a lot of reflection code
6811 * (and will allow us to support Build and Run assemblies easier).
6814 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6816 MonoClass *klass, *parent;
6818 MONO_ARCH_SAVE_REGS;
6821 /* check so we can compile corlib correctly */
6822 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6823 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6824 parent = tb->parent->type->data.klass;
6826 parent = my_mono_class_from_mono_type (tb->parent->type);
6830 /* the type has already being created: it means we just have to change the parent */
6831 if (tb->type.type) {
6832 klass = mono_class_from_mono_type (tb->type.type);
6833 klass->parent = NULL;
6834 /* fool mono_class_setup_parent */
6835 g_free (klass->supertypes);
6836 klass->supertypes = NULL;
6837 mono_class_setup_parent (klass, parent);
6841 klass = g_new0 (MonoClass, 1);
6843 klass->image = &tb->module->dynamic_image->image;
6845 klass->inited = 1; /* we lie to the runtime */
6846 klass->name = mono_string_to_utf8 (tb->name);
6847 klass->name_space = mono_string_to_utf8 (tb->nspace);
6848 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6849 klass->flags = tb->attrs;
6851 klass->element_class = klass;
6852 klass->reflection_info = tb; /* need to pin. */
6854 /* Put into cache so mono_class_get () will find it */
6855 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6858 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6859 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6863 mono_class_setup_parent (klass, parent);
6864 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6865 const char *old_n = klass->name;
6866 /* trick to get relative numbering right when compiling corlib */
6867 klass->name = "BuildingObject";
6868 mono_class_setup_parent (klass, mono_defaults.object_class);
6869 klass->name = old_n;
6871 mono_class_setup_mono_type (klass);
6873 mono_class_setup_supertypes (klass);
6876 * FIXME: handle interfaces.
6879 tb->type.type = &klass->byval_arg;
6881 if (tb->nesting_type) {
6882 g_assert (tb->nesting_type->type);
6883 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6886 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6890 * mono_reflection_setup_generic_class:
6891 * @tb: a TypeBuilder object
6893 * Setup the generic class after all generic parameters have been added.
6896 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6901 MONO_ARCH_SAVE_REGS;
6903 klass = my_mono_class_from_mono_type (tb->type.type);
6905 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6907 if (klass->gen_params || (count == 0))
6910 klass->num_gen_params = count;
6911 klass->gen_params = g_new0 (MonoGenericParam, count);
6913 for (i = 0; i < count; i++) {
6914 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6915 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6920 * mono_reflection_create_internal_class:
6921 * @tb: a TypeBuilder object
6923 * Actually create the MonoClass that is associated with the TypeBuilder.
6926 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6930 MONO_ARCH_SAVE_REGS;
6932 klass = my_mono_class_from_mono_type (tb->type.type);
6934 if (klass->enumtype && klass->enum_basetype == NULL) {
6935 MonoReflectionFieldBuilder *fb;
6937 g_assert (tb->fields != NULL);
6938 g_assert (mono_array_length (tb->fields) >= 1);
6940 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6942 klass->enum_basetype = fb->type->type;
6943 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6944 if (!klass->element_class)
6945 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6946 klass->instance_size = klass->element_class->instance_size;
6947 klass->size_inited = 1;
6949 * this is almost safe to do with enums and it's needed to be able
6950 * to create objects of the enum type (for use in SetConstant).
6952 /* FIXME: Does this mean enums can't have method overrides ? */
6953 mono_class_setup_vtable (klass, NULL, 0);
6957 static MonoMarshalSpec*
6958 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6959 MonoReflectionMarshal *minfo)
6961 MonoMarshalSpec *res;
6963 res = g_new0 (MonoMarshalSpec, 1);
6964 res->native = minfo->type;
6966 switch (minfo->type) {
6967 case MONO_NATIVE_LPARRAY:
6968 res->data.array_data.elem_type = minfo->eltype;
6969 res->data.array_data.param_num = 0; /* Not yet */
6970 res->data.array_data.num_elem = minfo->count;
6973 case MONO_NATIVE_BYVALTSTR:
6974 case MONO_NATIVE_BYVALARRAY:
6975 res->data.array_data.num_elem = minfo->count;
6978 case MONO_NATIVE_CUSTOM:
6979 if (minfo->marshaltyperef)
6980 res->data.custom_data.custom_name =
6981 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6983 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6994 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6995 ReflectionMethodBuilder *rmb,
6996 MonoMethodSignature *sig)
6999 MonoMethodNormal *pm;
7000 MonoMarshalSpec **specs;
7001 MonoReflectionMethodAux *method_aux;
7004 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7005 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7006 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7009 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7011 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7013 pm = (MonoMethodNormal*)m;
7016 m->flags = rmb->attrs;
7017 m->iflags = rmb->iattrs;
7018 m->name = mono_string_to_utf8 (rmb->name);
7022 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7024 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7025 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7028 m->signature->pinvoke = 1;
7029 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7031 m->signature->pinvoke = 1;
7033 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7035 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7036 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7038 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7040 if (klass->image->dynamic)
7041 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7044 } else if (!m->klass->dummy &&
7045 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7046 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7047 MonoMethodHeader *header;
7049 gint32 max_stack, i;
7050 gint32 num_locals = 0;
7051 gint32 num_clauses = 0;
7055 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7056 code_size = rmb->ilgen->code_len;
7057 max_stack = rmb->ilgen->max_stack;
7058 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7059 if (rmb->ilgen->ex_handlers)
7060 num_clauses = method_count_clauses (rmb->ilgen);
7063 code = mono_array_addr (rmb->code, guint8, 0);
7064 code_size = mono_array_length (rmb->code);
7065 /* we probably need to run a verifier on the code... */
7075 header = g_malloc0 (sizeof (MonoMethodHeader) +
7076 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7077 header->code_size = code_size;
7078 header->code = g_malloc (code_size);
7079 memcpy ((char*)header->code, code, code_size);
7080 header->max_stack = max_stack;
7081 header->init_locals = rmb->init_locals;
7082 header->num_locals = num_locals;
7084 for (i = 0; i < num_locals; ++i) {
7085 MonoReflectionLocalBuilder *lb =
7086 mono_array_get (rmb->ilgen->locals,
7087 MonoReflectionLocalBuilder*, i);
7089 header->locals [i] = g_new0 (MonoType, 1);
7090 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7093 header->num_clauses = num_clauses;
7095 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7100 if (rmb->generic_params) {
7101 int count = mono_array_length (rmb->generic_params);
7102 header->gen_params = g_new0 (MonoGenericParam, count);
7103 for (i = 0; i < count; i++) {
7104 MonoReflectionGenericParam *gp =
7105 mono_array_get (rmb->generic_params,
7106 MonoReflectionGenericParam*, i);
7108 header->gen_params [i] = *gp->type.type->data.generic_param;
7112 pm->header = header;
7116 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7119 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7121 for (i = 0; i < rmb->nrefs; ++i)
7122 mw->data = g_list_append (mw->data, rmb->refs [i]);
7127 /* Parameter names */
7130 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7131 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7132 for (i = 0; i <= m->signature->param_count; ++i) {
7133 MonoReflectionParamBuilder *pb;
7134 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7136 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7138 if (!method_aux->param_cattr)
7139 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7140 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7146 /* Parameter marshalling */
7149 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7150 MonoReflectionParamBuilder *pb;
7151 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7152 if (pb->marshal_info) {
7154 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7155 specs [pb->position] =
7156 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7160 if (specs != NULL) {
7162 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7163 method_aux->param_marshall = specs;
7166 if (klass->image->dynamic && method_aux)
7167 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7173 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7175 ReflectionMethodBuilder rmb;
7176 MonoMethodSignature *sig;
7178 sig = ctor_builder_to_signature (mb);
7180 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7182 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7183 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7185 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7186 /* ilgen is no longer needed */
7194 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7196 ReflectionMethodBuilder rmb;
7197 MonoMethodSignature *sig;
7199 sig = method_builder_to_signature (mb);
7201 reflection_methodbuilder_from_method_builder (&rmb, mb);
7203 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7204 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7206 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7207 /* ilgen is no longer needed */
7213 static MonoClassField*
7214 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7216 MonoClassField *field;
7223 field = g_new0 (MonoClassField, 1);
7225 field->name = mono_string_to_utf8 (fb->name);
7227 /* FIXME: handle type modifiers */
7228 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7229 field->type->attrs = fb->attrs;
7231 field->type = fb->type->type;
7233 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7234 field->data = mono_array_addr (fb->rva_data, char, 0);
7235 if (fb->offset != -1)
7236 field->offset = fb->offset;
7237 field->parent = klass;
7239 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7241 if (fb->def_value) {
7242 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7243 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7244 field->def_value = g_new0 (MonoConstant, 1);
7245 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7246 /* Copy the data from the blob since it might get realloc-ed */
7247 p = assembly->blob.data + idx;
7248 len = mono_metadata_decode_blob_size (p, &p2);
7250 field->def_value->value = g_malloc (len);
7251 memcpy (field->def_value->value, p, len);
7258 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7262 MonoReflectionTypeBuilder *tb = NULL;
7263 MonoGenericInst *ginst;
7268 klass = mono_class_from_mono_type (type->type);
7269 if (!klass->gen_params && !klass->generic_inst &&
7270 !(klass->nested_in && klass->nested_in->gen_params))
7273 mono_loader_lock ();
7275 domain = mono_object_domain (type);
7277 ginst = g_new0 (MonoGenericInst, 1);
7279 if (!klass->generic_inst) {
7280 ginst->type_argc = type_argc;
7281 ginst->type_argv = types;
7283 for (i = 0; i < ginst->type_argc; ++i) {
7284 if (!ginst->is_open)
7285 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7288 ginst->generic_type = &klass->byval_arg;
7290 MonoGenericInst *kginst = klass->generic_inst;
7292 ginst->type_argc = kginst->type_argc;
7293 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7295 for (i = 0; i < ginst->type_argc; i++) {
7296 MonoType *t = kginst->type_argv [i];
7298 if (t->type == MONO_TYPE_VAR)
7299 t = types [t->data.generic_param->num];
7301 if (!ginst->is_open)
7302 ginst->is_open = mono_class_is_open_constructed_type (t);
7304 ginst->type_argv [i] = t;
7307 ginst->generic_type = kginst->generic_type;
7310 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7313 mono_loader_unlock ();
7317 ginst->context = g_new0 (MonoGenericContext, 1);
7318 ginst->context->ginst = ginst;
7320 geninst = g_new0 (MonoType, 1);
7321 geninst->type = MONO_TYPE_GENERICINST;
7322 geninst->data.generic_inst = ginst;
7324 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7325 tb = (MonoReflectionTypeBuilder *) type;
7327 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7328 ginst->is_dynamic = TRUE;
7329 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7330 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7331 MonoReflectionType *rgt = rgi->generic_type;
7333 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7334 tb = (MonoReflectionTypeBuilder *) rgt;
7336 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7337 ginst->is_dynamic = TRUE;
7339 icount = klass->interface_count;
7341 ginst->ifaces = g_new0 (MonoType *, icount);
7342 ginst->count_ifaces = icount;
7344 for (i = 0; i < icount; i++) {
7345 MonoReflectionType *itype;
7348 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7350 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7351 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7352 if (!ginst->ifaces [i])
7353 ginst->ifaces [i] = itype->type;
7356 mono_class_create_generic (ginst);
7358 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7360 mono_loader_unlock ();
7366 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7368 MonoClass *klass, *pklass = NULL;
7369 MonoReflectionType *parent = NULL;
7371 MonoReflectionTypeBuilder *tb = NULL;
7372 MonoGenericInst *ginst;
7375 domain = mono_object_domain (type);
7376 klass = mono_class_from_mono_type (type->type);
7378 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7379 tb = (MonoReflectionTypeBuilder *) type;
7382 parent = tb->parent;
7383 pklass = mono_class_from_mono_type (parent->type);
7386 pklass = klass->parent;
7388 parent = mono_type_get_object (domain, &pklass->byval_arg);
7391 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7395 ginst = geninst->data.generic_inst;
7397 if (pklass && pklass->generic_inst)
7398 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7403 MonoReflectionMethod*
7404 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7406 MonoMethod *method, *inflated;
7407 MonoReflectionMethodBuilder *mb = NULL;
7408 MonoGenericMethod *gmethod;
7409 MonoGenericContext *context;
7412 MONO_ARCH_SAVE_REGS;
7413 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7414 MonoReflectionTypeBuilder *tb;
7417 mb = (MonoReflectionMethodBuilder *) rmethod;
7418 tb = (MonoReflectionTypeBuilder *) mb->type;
7419 klass = mono_class_from_mono_type (tb->type.type);
7421 method = methodbuilder_to_mono_method (klass, mb);
7423 method = rmethod->method;
7425 count = method->signature->generic_param_count;
7426 if (count != mono_array_length (types))
7429 gmethod = g_new0 (MonoGenericMethod, 1);
7430 gmethod->mtype_argc = count;
7431 gmethod->mtype_argv = g_new0 (MonoType *, count);
7432 for (i = 0; i < count; i++) {
7433 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7434 gmethod->mtype_argv [i] = garg->type;
7437 context = g_new0 (MonoGenericContext, 1);
7438 context->ginst = method->klass->generic_inst;
7439 context->gmethod = gmethod;
7441 inflated = mono_class_inflate_generic_method (method, context, NULL);
7443 return mono_method_get_object (
7444 mono_object_domain (rmethod), inflated, NULL);
7448 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7450 MonoGenericMethod *gmethod;
7451 MonoGenericInst *ginst;
7452 MonoGenericContext *context;
7455 ginst = type->type.type->data.generic_inst;
7457 gmethod = g_new0 (MonoGenericMethod, 1);
7458 gmethod->reflection_info = obj;
7460 gmethod->mtype_argc = method->signature->generic_param_count;
7461 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7463 for (i = 0; i < gmethod->mtype_argc; i++) {
7464 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7465 MonoGenericParam *gparam = &mn->header->gen_params [i];
7467 g_assert (gparam->pklass);
7468 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7471 context = g_new0 (MonoGenericContext, 1);
7472 context->ginst = ginst;
7473 context->gmethod = gmethod;
7475 return mono_class_inflate_generic_method (method, context, ginst->klass);
7479 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7484 klass = mono_class_from_mono_type (type->type.type);
7486 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7487 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7488 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7489 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7490 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7491 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7492 method = ((MonoReflectionMethod *) obj)->method;
7494 method = NULL; /* prevent compiler warning */
7495 g_assert_not_reached ();
7498 return inflate_mono_method (type, method, obj);
7502 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7503 MonoArray *methods, MonoArray *ctors,
7504 MonoArray *fields, MonoArray *properties,
7507 MonoGenericInst *ginst;
7508 MonoDynamicGenericInst *dginst;
7509 MonoClass *klass, *gklass, *pklass;
7512 MONO_ARCH_SAVE_REGS;
7514 klass = mono_class_from_mono_type (type->type.type);
7515 ginst = type->type.type->data.generic_inst;
7517 if (ginst->initialized)
7520 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7522 gklass = mono_class_from_mono_type (ginst->generic_type);
7523 mono_class_init (gklass);
7526 pklass = mono_class_from_mono_type (ginst->parent);
7528 pklass = gklass->parent;
7530 mono_class_setup_parent (klass, pklass);
7532 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7533 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7534 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7535 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7536 dginst->count_events = events ? mono_array_length (events) : 0;
7538 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7539 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7540 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7541 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7542 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7544 for (i = 0; i < dginst->count_methods; i++) {
7545 MonoObject *obj = mono_array_get (methods, gpointer, i);
7547 dginst->methods [i] = inflate_method (type, obj);
7550 for (i = 0; i < dginst->count_ctors; i++) {
7551 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7553 dginst->ctors [i] = inflate_method (type, obj);
7556 for (i = 0; i < dginst->count_fields; i++) {
7557 MonoObject *obj = mono_array_get (fields, gpointer, i);
7558 MonoClassField *field;
7559 MonoInflatedField *ifield;
7561 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7562 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7563 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7564 field = ((MonoReflectionField *) obj)->field;
7566 field = NULL; /* prevent compiler warning */
7567 g_assert_not_reached ();
7570 ifield = g_new0 (MonoInflatedField, 1);
7571 ifield->generic_type = field->type;
7572 ifield->reflection_info = obj;
7574 dginst->fields [i] = *field;
7575 dginst->fields [i].generic_info = ifield;
7576 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7579 for (i = 0; i < dginst->count_properties; i++) {
7580 MonoObject *obj = mono_array_get (properties, gpointer, i);
7581 MonoProperty *property = &dginst->properties [i];
7583 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7584 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7586 property->parent = klass;
7587 property->attrs = pb->attrs;
7588 property->name = mono_string_to_utf8 (pb->name);
7590 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7592 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7593 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7594 *property = *((MonoReflectionProperty *) obj)->property;
7597 property->get = inflate_mono_method (type, property->get, NULL);
7599 property->set = inflate_mono_method (type, property->set, NULL);
7601 g_assert_not_reached ();
7604 for (i = 0; i < dginst->count_events; i++) {
7605 MonoObject *obj = mono_array_get (events, gpointer, i);
7606 MonoEvent *event = &dginst->events [i];
7608 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7609 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7611 event->parent = klass;
7612 event->attrs = eb->attrs;
7613 event->name = mono_string_to_utf8 (eb->name);
7615 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7616 if (eb->remove_method)
7617 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7618 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7619 *event = *((MonoReflectionEvent *) obj)->event;
7622 event->add = inflate_mono_method (type, event->add, NULL);
7624 event->remove = inflate_mono_method (type, event->remove, NULL);
7626 g_assert_not_reached ();
7629 ginst->initialized = TRUE;
7633 ensure_runtime_vtable (MonoClass *klass)
7635 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7636 int i, num, j, onum;
7637 MonoMethod **overrides;
7639 if (!tb || klass->wastypebuilder)
7642 ensure_runtime_vtable (klass->parent);
7644 num = tb->ctors? mono_array_length (tb->ctors): 0;
7645 num += tb->num_methods;
7646 klass->method.count = num;
7647 klass->methods = g_new (MonoMethod*, num);
7648 num = tb->ctors? mono_array_length (tb->ctors): 0;
7649 for (i = 0; i < num; ++i)
7650 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7651 num = tb->num_methods;
7653 for (i = 0; i < num; ++i)
7654 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7656 klass->wastypebuilder = TRUE;
7657 if (tb->interfaces) {
7658 klass->interface_count = mono_array_length (tb->interfaces);
7659 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7660 for (i = 0; i < klass->interface_count; ++i) {
7661 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7662 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7666 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7667 for (i = 0; i < klass->method.count; ++i)
7668 klass->methods [i]->slot = i;
7673 for (i = 0; i < tb->num_methods; ++i) {
7674 MonoReflectionMethodBuilder *mb =
7675 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7676 if (mb->override_method)
7681 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7685 for (i = 0; i < tb->num_methods; ++i) {
7686 MonoReflectionMethodBuilder *mb =
7687 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7688 if (mb->override_method) {
7689 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7690 overrides [onum * 2] =
7691 mb->override_method->method;
7692 overrides [onum * 2 + 1] =
7695 g_assert (mb->mhandle);
7702 mono_class_setup_vtable (klass, overrides, onum);
7706 typebuilder_setup_fields (MonoClass *klass)
7708 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7709 MonoReflectionFieldBuilder *fb;
7710 MonoClassField *field;
7715 klass->field.count = tb->num_fields;
7716 klass->field.first = 0;
7717 klass->field.last = klass->field.count;
7719 if (!klass->field.count)
7722 klass->fields = g_new0 (MonoClassField, klass->field.count);
7724 for (i = 0; i < klass->field.count; ++i) {
7725 fb = mono_array_get (tb->fields, gpointer, i);
7726 field = &klass->fields [i];
7727 field->name = mono_string_to_utf8 (fb->name);
7729 /* FIXME: handle type modifiers */
7730 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7731 field->type->attrs = fb->attrs;
7733 field->type = fb->type->type;
7735 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7736 field->data = mono_array_addr (fb->rva_data, char, 0);
7737 if (fb->offset != -1)
7738 field->offset = fb->offset;
7739 field->parent = klass;
7741 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7743 if (fb->def_value) {
7744 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7745 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7746 field->def_value = g_new0 (MonoConstant, 1);
7747 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7748 /* Copy the data from the blob since it might get realloc-ed */
7749 p = assembly->blob.data + idx;
7750 len = mono_metadata_decode_blob_size (p, &p2);
7752 field->def_value->value = g_malloc (len);
7753 memcpy (field->def_value->value, p, len);
7756 mono_class_layout_fields (klass);
7760 typebuilder_setup_properties (MonoClass *klass)
7762 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7763 MonoReflectionPropertyBuilder *pb;
7766 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7767 klass->property.first = 0;
7768 klass->property.last = klass->property.count;
7770 klass->properties = g_new0 (MonoProperty, klass->property.count);
7771 for (i = 0; i < klass->property.count; ++i) {
7772 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7773 klass->properties [i].parent = klass;
7774 klass->properties [i].attrs = pb->attrs;
7775 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7777 klass->properties [i].get = pb->get_method->mhandle;
7779 klass->properties [i].set = pb->set_method->mhandle;
7783 MonoReflectionEvent *
7784 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7786 MonoEvent *event = g_new0 (MonoEvent, 1);
7790 klass = my_mono_class_from_mono_type (tb->type.type);
7792 event->parent = klass;
7793 event->attrs = eb->attrs;
7794 event->name = mono_string_to_utf8 (eb->name);
7796 event->add = eb->add_method->mhandle;
7797 if (eb->remove_method)
7798 event->remove = eb->remove_method->mhandle;
7799 if (eb->raise_method)
7800 event->raise = eb->raise_method->mhandle;
7802 if (eb->other_methods) {
7803 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7804 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7805 MonoReflectionMethodBuilder *mb =
7806 mono_array_get (eb->other_methods,
7807 MonoReflectionMethodBuilder*, j);
7808 event->other [j] = mb->mhandle;
7812 return mono_event_get_object (mono_object_domain (tb), klass, event);
7816 typebuilder_setup_events (MonoClass *klass)
7818 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7819 MonoReflectionEventBuilder *eb;
7822 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7823 klass->event.first = 0;
7824 klass->event.last = klass->event.count;
7826 klass->events = g_new0 (MonoEvent, klass->event.count);
7827 for (i = 0; i < klass->event.count; ++i) {
7828 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7829 klass->events [i].parent = klass;
7830 klass->events [i].attrs = eb->attrs;
7831 klass->events [i].name = mono_string_to_utf8 (eb->name);
7833 klass->events [i].add = eb->add_method->mhandle;
7834 if (eb->remove_method)
7835 klass->events [i].remove = eb->remove_method->mhandle;
7836 if (eb->raise_method)
7837 klass->events [i].raise = eb->raise_method->mhandle;
7839 if (eb->other_methods) {
7840 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7841 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7842 MonoReflectionMethodBuilder *mb =
7843 mono_array_get (eb->other_methods,
7844 MonoReflectionMethodBuilder*, j);
7845 klass->events [i].other [j] = mb->mhandle;
7852 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7855 MonoReflectionType* res;
7858 MONO_ARCH_SAVE_REGS;
7860 klass = my_mono_class_from_mono_type (tb->type.type);
7862 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7865 * Fields to set in klass:
7866 * the various flags: delegate/unicode/contextbound etc.
7868 klass->flags = tb->attrs;
7870 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7871 /* No need to fully construct the type */
7872 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7874 /* enums are done right away */
7875 if (!klass->enumtype)
7876 ensure_runtime_vtable (klass);
7879 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
7880 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
7881 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
7885 /* fields and object layout */
7886 if (klass->parent) {
7887 if (!klass->parent->size_inited)
7888 mono_class_init (klass->parent);
7889 klass->instance_size += klass->parent->instance_size;
7890 klass->class_size += klass->parent->class_size;
7891 klass->min_align = klass->parent->min_align;
7893 klass->instance_size = sizeof (MonoObject);
7894 klass->min_align = 1;
7897 /* FIXME: handle packing_size and instance_size */
7898 typebuilder_setup_fields (klass);
7900 typebuilder_setup_properties (klass);
7902 typebuilder_setup_events (klass);
7904 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7905 /* with enums res == tb: need to fix that. */
7906 if (!klass->enumtype)
7907 g_assert (res != (MonoReflectionType*)tb);
7912 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7914 MonoGenericParam *param;
7917 MONO_ARCH_SAVE_REGS;
7919 param = g_new0 (MonoGenericParam, 1);
7921 param->method = NULL;
7922 param->name = mono_string_to_utf8 (gparam->name);
7923 param->num = gparam->index;
7925 image = &gparam->tbuilder->module->dynamic_image->image;
7926 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7928 param->pklass->reflection_info = gparam;
7930 gparam->type.type = g_new0 (MonoType, 1);
7931 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7932 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7933 gparam->type.type->data.generic_param = param;
7937 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7939 MonoDynamicImage *assembly = sig->module->dynamic_image;
7940 guint32 na = mono_array_length (sig->arguments);
7945 MONO_ARCH_SAVE_REGS;
7947 p = buf = g_malloc (10 + na * 10);
7949 mono_metadata_encode_value (0x07, p, &p);
7950 mono_metadata_encode_value (na, p, &p);
7951 for (i = 0; i < na; ++i) {
7952 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7953 encode_reflection_type (assembly, type, p, &p);
7957 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7958 p = mono_array_addr (result, char, 0);
7959 memcpy (p, buf, buflen);
7966 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7968 MonoDynamicImage *assembly = sig->module->dynamic_image;
7969 guint32 na = mono_array_length (sig->arguments);
7974 MONO_ARCH_SAVE_REGS;
7976 p = buf = g_malloc (10 + na * 10);
7978 mono_metadata_encode_value (0x06, p, &p);
7979 for (i = 0; i < na; ++i) {
7980 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7981 encode_reflection_type (assembly, type, p, &p);
7985 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7986 p = mono_array_addr (result, char, 0);
7987 memcpy (p, buf, buflen);
7994 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7996 ReflectionMethodBuilder rmb;
7997 MonoMethodSignature *sig;
8000 sig = dynamic_method_to_signature (mb);
8002 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8005 * Resolve references.
8007 rmb.nrefs = mb->nrefs;
8008 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8009 for (i = 0; i < mb->nrefs; ++i) {
8010 gpointer ref = resolve_object (mb->module->image,
8011 mono_array_get (mb->refs, MonoObject*, i));
8014 mono_raise_exception (mono_get_exception_type_load (NULL));
8021 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8025 /* ilgen is no longer needed */
8030 * mono_reflection_lookup_dynamic_token:
8032 * Finish the Builder object pointed to by TOKEN and return the corresponding
8033 * runtime structure.
8036 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8038 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8041 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8044 return resolve_object (image, obj);
8048 resolve_object (MonoImage *image, MonoObject *obj)
8050 gpointer result = NULL;
8052 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8053 result = mono_string_intern ((MonoString*)obj);
8056 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8057 MonoReflectionType *tb = (MonoReflectionType*)obj;
8058 result = mono_class_from_mono_type (tb->type);
8061 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8062 result = ((MonoReflectionMethod*)obj)->method;
8065 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8066 result = ((MonoReflectionMethod*)obj)->method;
8069 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8070 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8071 result = mb->mhandle;
8073 /* Type is not yet created */
8074 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8076 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8079 * Hopefully this has been filled in by calling CreateType() on the
8083 * TODO: This won't work if the application finishes another
8084 * TypeBuilder instance instead of this one.
8086 result = mb->mhandle;
8089 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8090 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8092 result = cb->mhandle;
8094 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8096 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8097 result = cb->mhandle;
8100 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8101 result = ((MonoReflectionField*)obj)->field;
8104 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8105 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8106 result = fb->handle;
8109 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8111 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8112 result = fb->handle;
8115 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8116 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8119 klass = tb->type.type->data.klass;
8120 if (klass->wastypebuilder) {
8121 /* Already created */
8125 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8126 result = tb->type.type->data.klass;
8130 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8131 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8132 MonoMethodSignature *sig;
8135 if (helper->arguments)
8136 nargs = mono_array_length (helper->arguments);
8140 sig = mono_metadata_signature_alloc (image, nargs);
8141 sig->explicit_this = helper->call_conv & 64;
8142 sig->hasthis = helper->call_conv & 32;
8144 if (helper->call_conv == 0) /* unmanaged */
8145 sig->call_convention = helper->unmanaged_call_conv - 1;
8147 if (helper->call_conv & 0x02)
8148 sig->call_convention = MONO_CALL_VARARG;
8150 sig->call_convention = MONO_CALL_DEFAULT;
8152 sig->param_count = nargs;
8153 /* TODO: Copy type ? */
8154 sig->ret = helper->return_type->type;
8155 for (i = 0; i < nargs; ++i) {
8156 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8157 sig->params [i] = rt->type;
8163 g_print (obj->vtable->klass->name);
8164 g_assert_not_reached ();