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;
71 MonoReflectionGenericParam *gparam;
72 } GenericParamTableEntry;
74 const unsigned char table_sizes [64] = {
84 MONO_INTERFACEIMPL_SIZE,
85 MONO_MEMBERREF_SIZE, /* 0x0A */
87 MONO_CUSTOM_ATTR_SIZE,
88 MONO_FIELD_MARSHAL_SIZE,
89 MONO_DECL_SECURITY_SIZE,
90 MONO_CLASS_LAYOUT_SIZE,
91 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
92 MONO_STAND_ALONE_SIGNATURE_SIZE,
96 MONO_PROPERTY_MAP_SIZE,
99 MONO_METHOD_SEMA_SIZE,
100 MONO_METHODIMPL_SIZE,
101 MONO_MODULEREF_SIZE, /* 0x1A */
107 MONO_ASSEMBLY_SIZE, /* 0x20 */
108 MONO_ASSEMBLY_PROCESSOR_SIZE,
109 MONO_ASSEMBLYOS_SIZE,
110 MONO_ASSEMBLYREF_SIZE,
111 MONO_ASSEMBLYREFPROC_SIZE,
112 MONO_ASSEMBLYREFOS_SIZE,
116 MONO_NESTED_CLASS_SIZE,
118 MONO_GENERICPARAM_SIZE, /* 0x2A */
119 MONO_METHODSPEC_SIZE,
120 MONO_GENPARCONSTRAINT_SIZE,
126 * These macros can be used to allocate long living atomic data so it won't be
127 * tracked by the garbage collector. We use libgc because it's apparently faster
131 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
132 #define FREE_ATOMIC(ptr)
133 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
135 #define ALLOC_ATOMIC(size) g_malloc (size)
136 #define FREE_ATOMIC(ptr) g_free (ptr)
137 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
140 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
141 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
142 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
143 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
144 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
145 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
146 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
147 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
148 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
149 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
150 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
151 static void ensure_runtime_vtable (MonoClass *klass);
152 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
153 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
154 static guint32 type_get_signature_size (MonoType *type);
155 static void get_default_param_value_blobs (MonoMethod *method, char **blobs);
156 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
160 alloc_table (MonoDynamicTable *table, guint nrows)
163 g_assert (table->columns);
164 if (nrows + 1 >= table->alloc_rows) {
165 while (nrows + 1 >= table->alloc_rows)
166 if (table->alloc_rows == 0)
167 table->alloc_rows = 16;
169 table->alloc_rows *= 2;
172 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
174 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
179 make_room_in_stream (MonoDynamicStream *stream, int size)
181 while (stream->alloc_size <= size) {
182 if (stream->alloc_size < 4096)
183 stream->alloc_size = 4096;
185 stream->alloc_size *= 2;
188 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
190 stream->data = ALLOC_ATOMIC (stream->alloc_size);
194 string_heap_insert (MonoDynamicStream *sh, const char *str)
198 gpointer oldkey, oldval;
200 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
201 return GPOINTER_TO_UINT (oldval);
203 len = strlen (str) + 1;
205 if (idx + len > sh->alloc_size)
206 make_room_in_stream (sh, idx + len);
209 * We strdup the string even if we already copy them in sh->data
210 * so that the string pointers in the hash remain valid even if
211 * we need to realloc sh->data. We may want to avoid that later.
213 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
214 memcpy (sh->data + idx, str, len);
220 string_heap_init (MonoDynamicStream *sh)
223 sh->alloc_size = 4096;
224 sh->data = ALLOC_ATOMIC (4096);
225 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
226 string_heap_insert (sh, "");
229 #if 0 /* never used */
231 string_heap_free (MonoDynamicStream *sh)
233 FREE_ATOMIC (sh->data);
234 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
235 g_hash_table_destroy (sh->hash);
240 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
243 if (stream->alloc_size < stream->index + len)
244 make_room_in_stream (stream, stream->index + len);
245 memcpy (stream->data + stream->index, data, len);
247 stream->index += len;
249 * align index? Not without adding an additional param that controls it since
250 * we may store a blob value in pieces.
256 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
259 if (stream->alloc_size < stream->index + len)
260 make_room_in_stream (stream, stream->index + len);
261 memset (stream->data + stream->index, 0, len);
263 stream->index += len;
268 stream_data_align (MonoDynamicStream *stream)
271 guint32 count = stream->index % 4;
273 /* we assume the stream data will be aligned */
275 mono_image_add_stream_data (stream, buf, 4 - count);
279 mono_blob_entry_hash (const char* str)
283 len = mono_metadata_decode_blob_size (str, &str);
287 for (str += 1; str < end; str++)
288 h = (h << 5) - h + *str;
296 mono_blob_entry_equal (const char *str1, const char *str2) {
300 len = mono_metadata_decode_blob_size (str1, &end1);
301 len2 = mono_metadata_decode_blob_size (str2, &end2);
304 return memcmp (end1, end2, len) == 0;
308 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
312 gpointer oldkey, oldval;
314 copy = ALLOC_ATOMIC (s1+s2);
315 memcpy (copy, b1, s1);
316 memcpy (copy + s1, b2, s2);
317 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
319 idx = GPOINTER_TO_UINT (oldval);
321 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
322 mono_image_add_stream_data (&assembly->blob, b2, s2);
323 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
329 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
330 * dest may be misaligned.
333 swap_with_size (char *dest, const char* val, int len, int nelem) {
334 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
337 for (elem = 0; elem < nelem; ++elem) {
363 g_assert_not_reached ();
369 memcpy (dest, val, len * nelem);
374 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
378 guint32 idx = 0, len;
380 len = str->length * 2;
381 mono_metadata_encode_value (len, b, &b);
382 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
384 char *swapped = g_malloc (2 * mono_string_length (str));
385 const char *p = (const char*)mono_string_chars (str);
387 swap_with_size (swapped, p, 2, mono_string_length (str));
388 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
392 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
397 /* modified version needed to handle building corlib */
399 my_mono_class_from_mono_type (MonoType *type) {
400 switch (type->type) {
401 case MONO_TYPE_ARRAY:
403 case MONO_TYPE_SZARRAY:
404 case MONO_TYPE_GENERICINST:
405 return mono_class_from_mono_type (type);
408 g_assert (type->data.generic_param->pklass);
409 return type->data.generic_param->pklass;
411 /* should be always valid when we reach this case... */
412 return type->data.klass;
417 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
422 g_assert_not_reached ();
426 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
427 encode_type (assembly, ginst->generic_type, p, &p);
428 mono_metadata_encode_value (ginst->type_argc, p, &p);
429 for (i = 0; i < ginst->type_argc; ++i)
430 encode_type (assembly, ginst->type_argv [i], p, &p);
436 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
439 g_assert_not_reached ();
444 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
448 case MONO_TYPE_BOOLEAN:
462 case MONO_TYPE_STRING:
463 case MONO_TYPE_OBJECT:
464 case MONO_TYPE_TYPEDBYREF:
465 mono_metadata_encode_value (type->type, p, &p);
468 mono_metadata_encode_value (type->type, p, &p);
469 encode_type (assembly, type->data.type, p, &p);
471 case MONO_TYPE_SZARRAY:
472 mono_metadata_encode_value (type->type, p, &p);
473 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
476 case MONO_TYPE_VALUETYPE:
477 case MONO_TYPE_CLASS: {
478 MonoClass *k = mono_class_from_mono_type (type);
479 mono_metadata_encode_value (type->type, p, &p);
481 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
482 * otherwise two typerefs could point to the same type, leading to
483 * verification errors.
485 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
489 case MONO_TYPE_ARRAY:
490 mono_metadata_encode_value (type->type, p, &p);
491 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
492 mono_metadata_encode_value (type->data.array->rank, p, &p);
493 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
494 mono_metadata_encode_value (0, p, &p);
496 case MONO_TYPE_GENERICINST:
497 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
501 mono_metadata_encode_value (type->type, p, &p);
502 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
506 g_error ("need to encode type %x", type->type);
512 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
515 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
519 encode_type (assembly, type->type, p, endbuf);
523 g_assert_not_reached ();
528 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
533 for (i = 0; i < mono_array_length (modreq); ++i) {
534 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
535 *p = MONO_TYPE_CMOD_REQD;
537 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
541 for (i = 0; i < mono_array_length (modopt); ++i) {
542 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
543 *p = MONO_TYPE_CMOD_OPT;
545 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
552 generic_inst_get_signature_size (MonoGenericInst *ginst)
558 g_assert_not_reached ();
561 size += 1 + type_get_signature_size (ginst->generic_type);
563 for (i = 0; i < ginst->type_argc; ++i)
564 size += type_get_signature_size (ginst->type_argv [i]);
570 type_get_signature_size (MonoType *type)
575 g_assert_not_reached ();
583 case MONO_TYPE_BOOLEAN:
597 case MONO_TYPE_STRING:
598 case MONO_TYPE_OBJECT:
599 case MONO_TYPE_TYPEDBYREF:
602 return size + 1 + type_get_signature_size (type->data.type);
603 case MONO_TYPE_SZARRAY:
604 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
606 case MONO_TYPE_VALUETYPE:
607 case MONO_TYPE_CLASS:
610 case MONO_TYPE_ARRAY:
611 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
612 case MONO_TYPE_GENERICINST:
613 return size + generic_inst_get_signature_size (type->data.generic_inst);
619 g_error ("need to encode type %x", type->type);
625 method_get_signature_size (MonoMethodSignature *sig)
630 size = type_get_signature_size (sig->ret);
631 for (i = 0; i < sig->param_count; i++)
632 size += type_get_signature_size (sig->params [i]);
634 if (sig->generic_param_count)
636 if (sig->sentinelpos >= 0)
643 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
648 guint32 nparams = sig->param_count;
649 guint32 size = 11 + method_get_signature_size (sig);
657 p = buf = g_malloc (size);
659 * FIXME: vararg, explicit_this, differenc call_conv values...
661 *p = sig->call_convention;
663 *p |= 0x20; /* hasthis */
664 if (sig->generic_param_count)
665 *p |= 0x10; /* generic */
667 if (sig->generic_param_count)
668 mono_metadata_encode_value (sig->generic_param_count, p, &p);
669 mono_metadata_encode_value (nparams, p, &p);
670 encode_type (assembly, sig->ret, p, &p);
671 for (i = 0; i < nparams; ++i) {
672 if (i == sig->sentinelpos)
673 *p++ = MONO_TYPE_SENTINEL;
674 encode_type (assembly, sig->params [i], p, &p);
677 g_assert (p - buf < size);
678 mono_metadata_encode_value (p-buf, b, &b);
679 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
685 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
688 * FIXME: reuse code from method_encode_signature().
693 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
694 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
695 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
696 guint32 size = 21 + nparams * 20 + notypes * 20;
701 p = buf = g_malloc (size);
702 /* LAMESPEC: all the call conv spec is foobared */
703 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
704 if (mb->call_conv & 2)
705 *p |= 0x5; /* vararg */
706 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
707 *p |= 0x20; /* hasthis */
709 *p |= 0x10; /* generic */
712 mono_metadata_encode_value (ngparams, p, &p);
713 mono_metadata_encode_value (nparams + notypes, p, &p);
714 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
715 encode_reflection_type (assembly, mb->rtype, p, &p);
716 for (i = 0; i < nparams; ++i) {
717 MonoArray *modreq = NULL;
718 MonoArray *modopt = NULL;
719 MonoReflectionType *pt;
721 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
722 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
723 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
724 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
725 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
726 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
727 encode_reflection_type (assembly, pt, p, &p);
730 *p++ = MONO_TYPE_SENTINEL;
731 for (i = 0; i < notypes; ++i) {
732 MonoReflectionType *pt;
734 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
735 encode_reflection_type (assembly, pt, p, &p);
739 g_assert (p - buf < size);
740 mono_metadata_encode_value (p-buf, b, &b);
741 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
747 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
749 MonoDynamicTable *table;
752 guint32 idx, sig_idx, size;
753 guint nl = mono_array_length (ilgen->locals);
760 p = buf = g_malloc (size);
761 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
762 idx = table->next_idx ++;
764 alloc_table (table, table->rows);
765 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
767 mono_metadata_encode_value (0x07, p, &p);
768 mono_metadata_encode_value (nl, p, &p);
769 for (i = 0; i < nl; ++i) {
770 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
773 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
775 encode_reflection_type (assembly, lb->type, p, &p);
777 g_assert (p - buf < size);
778 mono_metadata_encode_value (p-buf, b, &b);
779 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
782 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
788 method_count_clauses (MonoReflectionILGen *ilgen)
790 guint32 num_clauses = 0;
793 MonoILExceptionInfo *ex_info;
794 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
795 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
796 if (ex_info->handlers)
797 num_clauses += mono_array_length (ex_info->handlers);
805 static MonoExceptionClause*
806 method_encode_clauses (MonoDynamicImage *assembly,
807 MonoReflectionILGen *ilgen, guint32 num_clauses)
809 MonoExceptionClause *clauses;
810 MonoExceptionClause *clause;
811 MonoILExceptionInfo *ex_info;
812 MonoILExceptionBlock *ex_block;
813 guint32 finally_start;
814 int i, j, clause_index;;
816 clauses = g_new0 (MonoExceptionClause, num_clauses);
819 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
820 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
821 finally_start = ex_info->start + ex_info->len;
822 g_assert (ex_info->handlers);
823 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
824 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
825 clause = &(clauses [clause_index]);
827 clause->flags = ex_block->type;
828 clause->try_offset = ex_info->start;
830 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
831 clause->try_len = finally_start - ex_info->start;
833 clause->try_len = ex_info->len;
834 clause->handler_offset = ex_block->start;
835 clause->handler_len = ex_block->len;
836 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
837 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
838 if (ex_block->extype) {
839 mono_g_hash_table_insert (assembly->tokens,
840 GUINT_TO_POINTER (clause->token_or_filter),
843 finally_start = ex_block->start + ex_block->len;
853 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
859 gint32 num_locals = 0;
860 gint32 num_exception = 0;
863 char fat_header [12];
866 guint32 local_sig = 0;
867 guint32 header_size = 12;
870 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
871 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
872 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
873 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
877 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
879 code = mb->ilgen->code;
880 code_size = mb->ilgen->code_len;
881 max_stack = mb->ilgen->max_stack;
882 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
883 if (mb->ilgen->ex_handlers)
884 num_exception = method_count_clauses (mb->ilgen);
888 char *name = mono_string_to_utf8 (mb->name);
889 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
890 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
893 mono_raise_exception (exception);
896 code_size = mono_array_length (code);
897 max_stack = 8; /* we probably need to run a verifier on the code... */
900 /* check for exceptions, maxstack, locals */
901 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
903 if (code_size < 64 && !(code_size & 1)) {
904 flags = (code_size << 2) | 0x2;
905 } else if (code_size < 32 && (code_size & 1)) {
906 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
910 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
911 /* add to the fixup todo list */
912 if (mb->ilgen && mb->ilgen->num_token_fixups)
913 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
914 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
915 return assembly->text_rva + idx;
919 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
921 * FIXME: need to set also the header size in fat_flags.
922 * (and more sects and init locals flags)
926 fat_flags |= METHOD_HEADER_MORE_SECTS;
928 fat_flags |= METHOD_HEADER_INIT_LOCALS;
929 fat_header [0] = fat_flags;
930 fat_header [1] = (header_size / 4 ) << 4;
931 shortp = (guint16*)(fat_header + 2);
932 *shortp = GUINT16_TO_LE (max_stack);
933 intp = (guint32*)(fat_header + 4);
934 *intp = GUINT32_TO_LE (code_size);
935 intp = (guint32*)(fat_header + 8);
936 *intp = GUINT32_TO_LE (local_sig);
937 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
938 /* add to the fixup todo list */
939 if (mb->ilgen && mb->ilgen->num_token_fixups)
940 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
942 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
944 unsigned char sheader [4];
945 MonoExceptionClause clause;
946 MonoILExceptionInfo * ex_info;
947 MonoILExceptionBlock * ex_block;
950 stream_data_align (&assembly->code);
951 /* always use fat format for now */
952 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
953 num_exception *= sizeof (MonoExceptionClause);
954 num_exception += 4; /* include the size of the header */
955 sheader [1] = num_exception & 0xff;
956 sheader [2] = (num_exception >> 8) & 0xff;
957 sheader [3] = (num_exception >> 16) & 0xff;
958 mono_image_add_stream_data (&assembly->code, sheader, 4);
959 /* fat header, so we are already aligned */
961 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
962 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
963 if (ex_info->handlers) {
964 int finally_start = ex_info->start + ex_info->len;
965 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
966 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
967 clause.flags = GUINT32_TO_LE (ex_block->type);
968 clause.try_offset = GUINT32_TO_LE (ex_info->start);
969 /* need fault, too, probably */
970 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
971 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
973 clause.try_len = GUINT32_TO_LE (ex_info->len);
974 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
975 clause.handler_len = GUINT32_TO_LE (ex_block->len);
976 finally_start = ex_block->start + ex_block->len;
977 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
978 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
979 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
980 /*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",
981 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);*/
982 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
985 g_error ("No clauses for ex info block %d", i);
989 return assembly->text_rva + idx;
993 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
996 MonoDynamicTable *table;
999 table = &assembly->tables [table_idx];
1001 g_assert (col < table->columns);
1003 values = table->values + table->columns;
1004 for (i = 1; i <= table->rows; ++i) {
1005 if (values [col] == token)
1007 values += table->columns;
1012 static GHashTable *dynamic_custom_attrs = NULL;
1014 static MonoCustomAttrInfo*
1015 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1018 MonoCustomAttrInfo *ainfo;
1019 MonoReflectionCustomAttr *cattr;
1023 /* FIXME: check in assembly the Run flag is set */
1025 count = mono_array_length (cattrs);
1027 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1029 ainfo->image = image;
1030 ainfo->num_attrs = count;
1031 for (i = 0; i < count; ++i) {
1032 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1033 ainfo->attrs [i].ctor = cattr->ctor->method;
1034 /* FIXME: might want to memdup the data here */
1035 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1036 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1043 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1045 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1050 if (!dynamic_custom_attrs)
1051 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1053 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1054 ainfo->cached = TRUE;
1058 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1060 /* they are cached, so we don't free them */
1061 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1067 * idx is the table index of the object
1068 * type is one of MONO_CUSTOM_ATTR_*
1071 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1073 MonoDynamicTable *table;
1074 MonoReflectionCustomAttr *cattr;
1076 guint32 count, i, token;
1078 char *p = blob_size;
1080 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1083 count = mono_array_length (cattrs);
1084 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1085 table->rows += count;
1086 alloc_table (table, table->rows);
1087 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1088 idx <<= MONO_CUSTOM_ATTR_BITS;
1090 for (i = 0; i < count; ++i) {
1091 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1092 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1093 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1094 type = mono_metadata_token_index (token);
1095 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1096 switch (mono_metadata_token_table (token)) {
1097 case MONO_TABLE_METHOD:
1098 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1100 case MONO_TABLE_MEMBERREF:
1101 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1104 g_warning ("got wrong token in custom attr");
1107 values [MONO_CUSTOM_ATTR_TYPE] = type;
1109 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1110 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1111 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1112 values += MONO_CUSTOM_ATTR_SIZE;
1118 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
1119 MonoArray *permissions)
1121 MonoDynamicTable *table;
1123 guint32 count, i, idx;
1124 MonoReflectionPermissionSet *perm;
1129 count = mono_array_length (permissions);
1130 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1131 table->rows += count;
1132 alloc_table (table, table->rows);
1134 for (i = 0; i < mono_array_length (permissions); ++i) {
1135 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1137 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1139 idx = mono_metadata_token_index (parent_token);
1140 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1141 switch (mono_metadata_token_table (parent_token)) {
1142 case MONO_TABLE_TYPEDEF:
1143 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1145 case MONO_TABLE_METHOD:
1146 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1148 case MONO_TABLE_ASSEMBLY:
1149 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1152 g_assert_not_reached ();
1155 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1156 values [MONO_DECL_SECURITY_PARENT] = idx;
1157 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1164 * Fill in the MethodDef and ParamDef tables for a method.
1165 * This is used for both normal methods and constructors.
1168 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1170 MonoDynamicTable *table;
1175 /* room in this table is already allocated */
1176 table = &assembly->tables [MONO_TABLE_METHOD];
1177 *mb->table_idx = table->next_idx ++;
1178 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1179 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1180 name = mono_string_to_utf8 (mb->name);
1181 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1183 values [MONO_METHOD_FLAGS] = mb->attrs;
1184 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1185 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1186 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1188 table = &assembly->tables [MONO_TABLE_PARAM];
1189 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1191 mono_image_add_decl_security (assembly,
1192 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1196 MonoDynamicTable *mtable;
1199 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1200 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1203 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1204 if (mono_array_get (mb->pinfo, gpointer, i))
1207 table->rows += count;
1208 alloc_table (table, table->rows);
1209 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1210 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1211 MonoReflectionParamBuilder *pb;
1212 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1213 values [MONO_PARAM_FLAGS] = pb->attrs;
1214 values [MONO_PARAM_SEQUENCE] = i;
1215 if (pb->name != NULL) {
1216 name = mono_string_to_utf8 (pb->name);
1217 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1220 values [MONO_PARAM_NAME] = 0;
1222 values += MONO_PARAM_SIZE;
1223 if (pb->marshal_info) {
1225 alloc_table (mtable, mtable->rows);
1226 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1227 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1228 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1230 pb->table_idx = table->next_idx++;
1231 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1232 guint32 field_type = 0;
1233 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1235 alloc_table (mtable, mtable->rows);
1236 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1237 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1238 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1239 mvalues [MONO_CONSTANT_TYPE] = field_type;
1240 mvalues [MONO_CONSTANT_PADDING] = 0;
1248 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1249 MonoReflectionMethodBuilder *mb)
1251 rmb->ilgen = mb->ilgen;
1252 rmb->rtype = mb->rtype;
1253 rmb->parameters = mb->parameters;
1254 rmb->generic_params = mb->generic_params;
1255 rmb->opt_types = NULL;
1256 rmb->pinfo = mb->pinfo;
1257 rmb->attrs = mb->attrs;
1258 rmb->iattrs = mb->iattrs;
1259 rmb->call_conv = mb->call_conv;
1260 rmb->code = mb->code;
1261 rmb->type = mb->type;
1262 rmb->name = mb->name;
1263 rmb->table_idx = &mb->table_idx;
1264 rmb->init_locals = mb->init_locals;
1265 rmb->return_modreq = mb->return_modreq;
1266 rmb->return_modopt = mb->return_modopt;
1267 rmb->param_modreq = mb->param_modreq;
1268 rmb->param_modopt = mb->param_modopt;
1269 rmb->permissions = mb->permissions;
1270 rmb->mhandle = mb->mhandle;
1275 rmb->charset = rmb->charset & 0xf;
1276 rmb->lasterr = rmb->charset & 0x40;
1277 rmb->native_cc = rmb->native_cc;
1278 rmb->dllentry = mb->dllentry;
1284 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1285 MonoReflectionCtorBuilder *mb)
1287 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1289 rmb->ilgen = mb->ilgen;
1290 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1291 rmb->parameters = mb->parameters;
1292 rmb->generic_params = NULL;
1293 rmb->opt_types = NULL;
1294 rmb->pinfo = mb->pinfo;
1295 rmb->attrs = mb->attrs;
1296 rmb->iattrs = mb->iattrs;
1297 rmb->call_conv = mb->call_conv;
1299 rmb->type = mb->type;
1300 rmb->name = mono_string_new (mono_domain_get (), name);
1301 rmb->table_idx = &mb->table_idx;
1302 rmb->init_locals = mb->init_locals;
1303 rmb->return_modreq = NULL;
1304 rmb->return_modopt = NULL;
1305 rmb->param_modreq = mb->param_modreq;
1306 rmb->param_modopt = mb->param_modopt;
1307 rmb->permissions = mb->permissions;
1308 rmb->mhandle = mb->mhandle;
1314 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1315 MonoReflectionDynamicMethod *mb)
1317 rmb->ilgen = mb->ilgen;
1318 rmb->rtype = mb->rtype;
1319 rmb->parameters = mb->parameters;
1320 rmb->generic_params = NULL;
1321 rmb->opt_types = NULL;
1323 rmb->attrs = mb->attrs;
1325 rmb->call_conv = mb->call_conv;
1328 rmb->name = mb->name;
1329 rmb->table_idx = NULL;
1330 rmb->init_locals = mb->init_locals;
1331 rmb->return_modreq = NULL;
1332 rmb->return_modopt = NULL;
1333 rmb->param_modreq = NULL;
1334 rmb->param_modopt = NULL;
1335 rmb->permissions = NULL;
1336 rmb->mhandle = mb->mhandle;
1342 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1344 MonoDynamicTable *table;
1347 ReflectionMethodBuilder rmb;
1350 reflection_methodbuilder_from_method_builder (&rmb, mb);
1352 mono_image_basic_method (&rmb, assembly);
1354 if (mb->dll) { /* It's a P/Invoke method */
1356 int charset = mb->charset & 0xf;
1357 int lasterr = mb->charset & 0x40;
1358 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1360 alloc_table (table, table->rows);
1361 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1362 /* map CharSet values to on-disk values */
1364 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1365 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1366 name = mono_string_to_utf8 (mb->dllentry);
1367 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1369 name = mono_string_to_utf8 (mb->dll);
1370 moduleref = string_heap_insert (&assembly->sheap, name);
1372 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1373 table = &assembly->tables [MONO_TABLE_MODULEREF];
1375 alloc_table (table, table->rows);
1376 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1377 values [MONO_IMPLMAP_SCOPE] = table->rows;
1381 if (mb->override_method) {
1382 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1384 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1386 alloc_table (table, table->rows);
1387 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1388 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1389 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1391 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1392 switch (mono_metadata_token_table (tok)) {
1393 case MONO_TABLE_MEMBERREF:
1394 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1396 case MONO_TABLE_METHOD:
1397 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1400 g_assert_not_reached ();
1402 values [MONO_METHODIMPL_DECLARATION] = tok;
1405 if (mb->generic_params) {
1406 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1407 table->rows += mono_array_length (mb->generic_params);
1408 alloc_table (table, table->rows);
1409 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1410 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1412 mono_image_get_generic_param_info (
1413 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1420 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1422 ReflectionMethodBuilder rmb;
1424 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1426 mono_image_basic_method (&rmb, assembly);
1430 type_get_fully_qualified_name (MonoType *type) {
1431 char *name, *result;
1435 name = mono_type_get_name (type);
1436 klass = my_mono_class_from_mono_type (type);
1437 ta = klass->image->assembly;
1439 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1440 name, ta->aname.name,
1441 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1442 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1443 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1449 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1453 klass = my_mono_class_from_mono_type (type);
1455 return mono_type_get_name (type);
1456 ta = klass->image->assembly;
1457 if (ta == ass || klass->image == mono_defaults.corlib)
1458 return mono_type_get_name (type);
1460 return type_get_fully_qualified_name (type);
1464 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1466 char blob_size [64];
1467 char *b = blob_size;
1472 if (!assembly->save)
1475 p = buf = g_malloc (64);
1477 mono_metadata_encode_value (0x06, p, &p);
1478 /* encode custom attributes before the type */
1479 encode_type (assembly, type, p, &p);
1480 g_assert (p-buf < 64);
1481 mono_metadata_encode_value (p-buf, b, &b);
1482 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1488 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1490 char blob_size [64];
1491 char *b = blob_size;
1496 p = buf = g_malloc (64);
1498 mono_metadata_encode_value (0x06, p, &p);
1499 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1500 /* encode custom attributes before the type */
1501 encode_reflection_type (assembly, fb->type, p, &p);
1502 g_assert (p-buf < 64);
1503 mono_metadata_encode_value (p-buf, b, &b);
1504 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1510 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1511 char blob_size [64];
1512 char *b = blob_size;
1515 guint32 idx = 0, len = 0, dummy = 0;
1517 p = buf = g_malloc (64);
1519 *ret_type = MONO_TYPE_CLASS;
1521 box_val = (char*)&dummy;
1523 box_val = ((char*)val) + sizeof (MonoObject);
1524 *ret_type = val->vtable->klass->byval_arg.type;
1527 switch (*ret_type) {
1528 case MONO_TYPE_BOOLEAN:
1533 case MONO_TYPE_CHAR:
1548 case MONO_TYPE_VALUETYPE:
1549 if (val->vtable->klass->enumtype) {
1550 *ret_type = val->vtable->klass->enum_basetype->type;
1553 g_error ("we can't encode valuetypes");
1554 case MONO_TYPE_CLASS:
1556 case MONO_TYPE_STRING: {
1557 MonoString *str = (MonoString*)val;
1558 /* there is no signature */
1559 len = str->length * 2;
1560 mono_metadata_encode_value (len, b, &b);
1561 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1563 char *swapped = g_malloc (2 * mono_string_length (str));
1564 const char *p = (const char*)mono_string_chars (str);
1566 swap_with_size (swapped, p, 2, mono_string_length (str));
1567 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1571 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1578 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1581 /* there is no signature */
1582 mono_metadata_encode_value (len, b, &b);
1583 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1584 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1585 swap_with_size (blob_size, box_val, len, 1);
1586 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1588 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1596 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1597 char blob_size [64];
1598 char *b = blob_size;
1599 char *p, *buf, *str;
1600 guint32 idx, len, bufsize = 256;
1602 p = buf = g_malloc (bufsize);
1604 switch (minfo->type) {
1605 case MONO_NATIVE_BYVALTSTR:
1606 case MONO_NATIVE_BYVALARRAY:
1607 mono_metadata_encode_value (minfo->type, p, &p);
1608 mono_metadata_encode_value (minfo->count, p, &p);
1610 case MONO_NATIVE_LPARRAY:
1611 mono_metadata_encode_value (minfo->type, p, &p);
1612 if (minfo->eltype || (minfo->count > 0)) {
1613 mono_metadata_encode_value (minfo->eltype, p, &p);
1614 if (minfo->count > 0) {
1615 mono_metadata_encode_value (0, p, &p);
1616 mono_metadata_encode_value (minfo->count, p, &p);
1620 case MONO_NATIVE_CUSTOM:
1621 mono_metadata_encode_value (minfo->type, p, &p);
1623 str = mono_string_to_utf8 (minfo->guid);
1625 mono_metadata_encode_value (len, p, &p);
1626 memcpy (p, str, len);
1630 mono_metadata_encode_value (0, p, &p);
1632 if (minfo->marshaltype) {
1633 str = mono_string_to_utf8 (minfo->marshaltype);
1635 mono_metadata_encode_value (len, p, &p);
1636 if (p + len >= buf + bufsize) {
1639 buf = g_realloc (buf, bufsize);
1642 memcpy (p, str, len);
1646 mono_metadata_encode_value (0, p, &p);
1648 if (minfo->marshaltyperef) {
1649 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1651 mono_metadata_encode_value (len, p, &p);
1652 if (p + len >= buf + bufsize) {
1655 buf = g_realloc (buf, bufsize);
1658 memcpy (p, str, len);
1662 mono_metadata_encode_value (0, p, &p);
1664 if (minfo->mcookie) {
1665 str = mono_string_to_utf8 (minfo->mcookie);
1667 mono_metadata_encode_value (len, p, &p);
1668 if (p + len >= buf + bufsize) {
1671 buf = g_realloc (buf, bufsize);
1674 memcpy (p, str, len);
1678 mono_metadata_encode_value (0, p, &p);
1682 mono_metadata_encode_value (minfo->type, p, &p);
1686 mono_metadata_encode_value (len, b, &b);
1687 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1693 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1695 MonoDynamicTable *table;
1699 /* maybe this fixup should be done in the C# code */
1700 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1701 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1702 table = &assembly->tables [MONO_TABLE_FIELD];
1703 fb->table_idx = table->next_idx ++;
1704 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1705 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1706 name = mono_string_to_utf8 (fb->name);
1707 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1709 values [MONO_FIELD_FLAGS] = fb->attrs;
1710 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1712 if (fb->offset != -1) {
1713 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1715 alloc_table (table, table->rows);
1716 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1717 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1718 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1720 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1721 guint32 field_type = 0;
1722 table = &assembly->tables [MONO_TABLE_CONSTANT];
1724 alloc_table (table, table->rows);
1725 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1726 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1727 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1728 values [MONO_CONSTANT_TYPE] = field_type;
1729 values [MONO_CONSTANT_PADDING] = 0;
1731 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1733 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1735 alloc_table (table, table->rows);
1736 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1737 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1739 * We store it in the code section because it's simpler for now.
1742 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1744 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1745 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1747 if (fb->marshal_info) {
1748 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1750 alloc_table (table, table->rows);
1751 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1752 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1753 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1758 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1762 char *b = blob_size;
1763 guint32 nparams = 0;
1764 MonoReflectionMethodBuilder *mb = fb->get_method;
1765 MonoReflectionMethodBuilder *smb = fb->set_method;
1766 guint32 idx, i, size;
1768 if (mb && mb->parameters)
1769 nparams = mono_array_length (mb->parameters);
1770 if (!mb && smb && smb->parameters)
1771 nparams = mono_array_length (smb->parameters) - 1;
1772 size = 24 + nparams * 10;
1773 buf = p = g_malloc (size);
1776 mono_metadata_encode_value (nparams, p, &p);
1778 encode_reflection_type (assembly, mb->rtype, p, &p);
1779 for (i = 0; i < nparams; ++i) {
1780 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1781 encode_reflection_type (assembly, pt, p, &p);
1784 /* the property type is the last param */
1785 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1786 for (i = 0; i < nparams; ++i) {
1787 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1788 encode_reflection_type (assembly, pt, p, &p);
1792 g_assert (p - buf < size);
1793 mono_metadata_encode_value (p-buf, b, &b);
1794 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1800 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1802 MonoDynamicTable *table;
1805 guint num_methods = 0;
1809 * we need to set things in the following tables:
1810 * PROPERTYMAP (info already filled in _get_type_info ())
1811 * PROPERTY (rows already preallocated in _get_type_info ())
1812 * METHOD (method info already done with the generic method code)
1815 table = &assembly->tables [MONO_TABLE_PROPERTY];
1816 pb->table_idx = table->next_idx ++;
1817 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1818 name = mono_string_to_utf8 (pb->name);
1819 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1821 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1822 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1824 /* FIXME: we still don't handle 'other' methods */
1825 if (pb->get_method) num_methods ++;
1826 if (pb->set_method) num_methods ++;
1828 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1829 table->rows += num_methods;
1830 alloc_table (table, table->rows);
1832 if (pb->get_method) {
1833 semaidx = table->next_idx ++;
1834 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1835 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1836 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1837 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1839 if (pb->set_method) {
1840 semaidx = table->next_idx ++;
1841 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1842 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1843 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1844 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1849 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1851 MonoDynamicTable *table;
1854 guint num_methods = 0;
1858 * we need to set things in the following tables:
1859 * EVENTMAP (info already filled in _get_type_info ())
1860 * EVENT (rows already preallocated in _get_type_info ())
1861 * METHOD (method info already done with the generic method code)
1864 table = &assembly->tables [MONO_TABLE_EVENT];
1865 eb->table_idx = table->next_idx ++;
1866 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1867 name = mono_string_to_utf8 (eb->name);
1868 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1870 values [MONO_EVENT_FLAGS] = eb->attrs;
1871 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1874 * FIXME: we still don't handle 'other' methods
1876 if (eb->add_method) num_methods ++;
1877 if (eb->remove_method) num_methods ++;
1878 if (eb->raise_method) num_methods ++;
1880 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1881 table->rows += num_methods;
1882 alloc_table (table, table->rows);
1884 if (eb->add_method) {
1885 semaidx = table->next_idx ++;
1886 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1887 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1888 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1889 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1891 if (eb->remove_method) {
1892 semaidx = table->next_idx ++;
1893 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1894 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1895 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1896 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1898 if (eb->raise_method) {
1899 semaidx = table->next_idx ++;
1900 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1901 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1902 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1903 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1908 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1910 static MonoClass *NewConstraintAttr;
1911 static MonoMethod *NewConstraintAttr_ctor;
1912 MonoDynamicTable *table;
1914 guint32 token, type;
1915 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1918 if (!NewConstraintAttr)
1919 NewConstraintAttr = mono_class_from_name (
1920 mono_defaults.corlib, "System.Runtime.CompilerServices",
1921 "NewConstraintAttribute");
1922 g_assert (NewConstraintAttr);
1924 if (!NewConstraintAttr_ctor) {
1927 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1928 MonoMethod *m = NewConstraintAttr->methods [i];
1930 if (strcmp (m->name, ".ctor"))
1933 NewConstraintAttr_ctor = m;
1937 g_assert (NewConstraintAttr_ctor);
1940 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1942 alloc_table (table, table->rows);
1944 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1945 owner <<= MONO_CUSTOM_ATTR_BITS;
1946 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1947 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1949 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1951 type = mono_metadata_token_index (token);
1952 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1953 switch (mono_metadata_token_table (token)) {
1954 case MONO_TABLE_METHOD:
1955 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1957 case MONO_TABLE_MEMBERREF:
1958 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1961 g_warning ("got wrong token in custom attr");
1964 values [MONO_CUSTOM_ATTR_TYPE] = type;
1966 buf = p = g_malloc (1);
1967 mono_metadata_encode_value (4, p, &p);
1968 g_assert (p-buf == 1);
1970 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1972 values += MONO_CUSTOM_ATTR_SIZE;
1977 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1979 MonoDynamicTable *table;
1980 guint32 num_constraints, i;
1984 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1985 num_constraints = gparam->iface_constraints ?
1986 mono_array_length (gparam->iface_constraints) : 0;
1987 table->rows += num_constraints;
1988 if (gparam->base_type)
1990 alloc_table (table, table->rows);
1992 if (gparam->base_type) {
1993 table_idx = table->next_idx ++;
1994 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1996 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1997 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1998 assembly, gparam->base_type->type);
2001 for (i = 0; i < num_constraints; i++) {
2002 MonoReflectionType *constraint = mono_array_get (
2003 gparam->iface_constraints, gpointer, i);
2005 table_idx = table->next_idx ++;
2006 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2008 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2009 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2010 assembly, constraint->type);
2013 if (gparam->has_ctor_constraint)
2014 encode_new_constraint (assembly, owner);
2018 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2020 GenericParamTableEntry *entry;
2023 * The GenericParam table must be sorted according to the `owner' field.
2024 * We need to do this sorting prior to writing the GenericParamConstraint
2025 * table, since we have to use the final GenericParam table indices there
2026 * and they must also be sorted.
2029 entry = g_new0 (GenericParamTableEntry, 1);
2030 entry->owner = owner;
2031 entry->gparam = gparam;
2033 g_ptr_array_add (assembly->gen_params, entry);
2037 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2039 MonoDynamicTable *table;
2040 MonoGenericParam *param;
2044 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2045 table_idx = table->next_idx ++;
2046 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2048 param = entry->gparam->type.type->data.generic_param;
2050 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2051 if (entry->gparam->has_value_type)
2052 values [MONO_GENERICPARAM_FLAGS] = 0x18;
2053 else if (entry->gparam->has_reference_type)
2054 values [MONO_GENERICPARAM_FLAGS] = 0x04;
2056 values [MONO_GENERICPARAM_FLAGS] = 0x00;
2057 values [MONO_GENERICPARAM_NUMBER] = param->num;
2058 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2059 values [MONO_GENERICPARAM_KIND] = 0;
2061 encode_constraints (entry->gparam, table_idx, assembly);
2065 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2067 MonoDynamicTable *table;
2070 guint32 cols [MONO_ASSEMBLY_SIZE];
2074 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2077 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2078 table = &assembly->tables [MONO_TABLE_MODULEREF];
2079 token = table->next_idx ++;
2081 alloc_table (table, table->rows);
2082 values = table->values + token * MONO_MODULEREF_SIZE;
2083 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2085 token <<= MONO_RESOLTION_SCOPE_BITS;
2086 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2087 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2092 if (image->assembly->dynamic)
2094 memset (cols, 0, sizeof (cols));
2096 /* image->assembly->image is the manifest module */
2097 image = image->assembly->image;
2098 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2101 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2102 token = table->next_idx ++;
2104 alloc_table (table, table->rows);
2105 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2106 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2107 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2108 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2109 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2110 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2111 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2112 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2113 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2115 if (strcmp ("", image->assembly->aname.culture)) {
2116 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2117 image->assembly->aname.culture);
2120 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2121 guchar pubtoken [9];
2123 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2124 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2126 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2128 token <<= MONO_RESOLTION_SCOPE_BITS;
2129 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2130 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2135 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2137 MonoDynamicTable *table;
2143 char *b = blob_size;
2145 switch (type->type) {
2146 case MONO_TYPE_FNPTR:
2148 case MONO_TYPE_SZARRAY:
2149 case MONO_TYPE_ARRAY:
2151 case MONO_TYPE_MVAR:
2152 case MONO_TYPE_GENERICINST:
2153 encode_type (assembly, type, p, &p);
2155 case MONO_TYPE_CLASS:
2156 case MONO_TYPE_VALUETYPE: {
2157 MonoClass *k = mono_class_from_mono_type (type);
2158 if (!k || !k->generic_inst)
2160 encode_generic_inst (assembly, k->generic_inst, p, &p);
2167 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2168 if (assembly->save) {
2169 g_assert (p-sig < 128);
2170 mono_metadata_encode_value (p-sig, b, &b);
2171 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2172 alloc_table (table, table->rows + 1);
2173 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2174 values [MONO_TYPESPEC_SIGNATURE] = token;
2177 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2178 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2184 * Despite the name, we handle also TypeSpec (with the above helper).
2187 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2189 MonoDynamicTable *table;
2191 guint32 token, scope, enclosing;
2194 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2197 token = create_typespec (assembly, type);
2200 klass = my_mono_class_from_mono_type (type);
2202 klass = mono_class_from_mono_type (type);
2205 * If it's in the same module and not a generic type parameter:
2207 if ((klass->image == &assembly->image) &&
2208 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2209 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2210 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2211 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2215 if (klass->nested_in) {
2216 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2217 /* get the typeref idx of the enclosing type */
2218 enclosing >>= MONO_TYPEDEFORREF_BITS;
2219 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2221 scope = resolution_scope_from_image (assembly, klass->image);
2223 table = &assembly->tables [MONO_TABLE_TYPEREF];
2224 if (assembly->save) {
2225 alloc_table (table, table->rows + 1);
2226 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2227 values [MONO_TYPEREF_SCOPE] = scope;
2228 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2229 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2231 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2232 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2234 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2239 * Insert a memberef row into the metadata: the token that point to the memberref
2240 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2241 * mono_image_get_fieldref_token()).
2242 * The sig param is an index to an already built signature.
2245 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2247 MonoDynamicTable *table;
2249 guint32 token, pclass;
2252 parent = mono_image_typedef_or_ref (assembly, type);
2253 switch (parent & MONO_TYPEDEFORREF_MASK) {
2254 case MONO_TYPEDEFORREF_TYPEREF:
2255 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2257 case MONO_TYPEDEFORREF_TYPESPEC:
2258 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2260 case MONO_TYPEDEFORREF_TYPEDEF:
2261 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2264 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2267 /* extract the index */
2268 parent >>= MONO_TYPEDEFORREF_BITS;
2270 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2272 if (assembly->save) {
2273 alloc_table (table, table->rows + 1);
2274 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2275 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2276 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2277 values [MONO_MEMBERREF_SIGNATURE] = sig;
2280 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2287 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2290 MonoMethodSignature *sig;
2292 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2297 * A methodref signature can't contain an unmanaged calling convention.
2299 sig = mono_metadata_signature_dup (method->signature);
2300 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2301 sig->call_convention = MONO_CALL_DEFAULT;
2302 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2303 method->name, method_encode_signature (assembly, sig));
2305 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2310 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2311 const gchar *name, guint32 sig)
2313 MonoDynamicTable *table;
2317 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2319 if (assembly->save) {
2320 alloc_table (table, table->rows + 1);
2321 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2322 values [MONO_MEMBERREF_CLASS] = original;
2323 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2324 values [MONO_MEMBERREF_SIGNATURE] = sig;
2327 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2334 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2337 ReflectionMethodBuilder rmb;
2339 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2343 reflection_methodbuilder_from_method_builder (&rmb, mb);
2345 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2346 mono_string_to_utf8 (rmb.name),
2347 method_builder_encode_signature (assembly, &rmb));
2348 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2353 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2356 ReflectionMethodBuilder rmb;
2358 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2362 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2364 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2365 mono_string_to_utf8 (rmb.name),
2366 method_builder_encode_signature (assembly, &rmb));
2367 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2372 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2377 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2380 g_assert (f->field->parent);
2381 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2382 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2383 f->field->name, fieldref_encode_signature (assembly, type));
2384 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2389 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2394 guint32 nparams = gmethod->mtype_argc;
2395 guint32 size = 10 + nparams * 10;
2398 char *b = blob_size;
2400 if (!assembly->save)
2403 p = buf = g_malloc (size);
2405 * FIXME: vararg, explicit_this, differenc call_conv values...
2407 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2408 mono_metadata_encode_value (nparams, p, &p);
2410 for (i = 0; i < nparams; i++)
2411 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2414 g_assert (p - buf < size);
2415 mono_metadata_encode_value (p-buf, b, &b);
2416 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2422 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2424 MonoDynamicTable *table;
2426 guint32 token, mtoken = 0, sig;
2427 MonoMethodInflated *imethod;
2428 MonoMethod *declaring;
2430 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2432 g_assert (method->signature->is_inflated);
2433 imethod = (MonoMethodInflated *) method;
2434 declaring = imethod->declaring;
2436 sig = method_encode_signature (assembly, declaring->signature);
2437 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2438 declaring->name, sig);
2440 if (!declaring->signature->generic_param_count)
2443 switch (mono_metadata_token_table (mtoken)) {
2444 case MONO_TABLE_MEMBERREF:
2445 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2447 case MONO_TABLE_METHOD:
2448 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2451 g_assert_not_reached ();
2454 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2456 if (assembly->save) {
2457 alloc_table (table, table->rows + 1);
2458 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2459 values [MONO_METHODSPEC_METHOD] = mtoken;
2460 values [MONO_METHODSPEC_SIGNATURE] = sig;
2463 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2470 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2472 MonoMethodInflated *imethod;
2475 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2479 g_assert (m->signature->is_inflated);
2480 imethod = (MonoMethodInflated *) m;
2482 if (imethod->declaring->signature->generic_param_count)
2483 token = method_encode_methodspec (assembly, m);
2485 guint32 sig = method_encode_signature (
2486 assembly, imethod->declaring->signature);
2487 token = mono_image_get_memberref_token (
2488 assembly, &m->klass->byval_arg, m->name, sig);
2491 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2496 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2498 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2501 sig = method_encode_signature (assembly, imethod->declaring->signature);
2502 token = mono_image_get_memberref_token (
2503 assembly, &m->klass->byval_arg, m->name, sig);
2509 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2511 MonoDynamicTable *table;
2518 char *b = blob_size;
2522 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2523 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2524 * Because of this, we must not insert it into the `typeref' hash table.
2527 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2531 g_assert (tb->generic_params);
2532 klass = mono_class_from_mono_type (tb->type.type);
2534 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2535 encode_type (assembly, &klass->byval_arg, p, &p);
2537 count = mono_array_length (tb->generic_params);
2538 mono_metadata_encode_value (count, p, &p);
2539 for (i = 0; i < count; i++) {
2540 MonoReflectionGenericParam *gparam;
2542 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2544 encode_type (assembly, gparam->type.type, p, &p);
2547 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2548 if (assembly->save) {
2549 g_assert (p-sig < 128);
2550 mono_metadata_encode_value (p-sig, b, &b);
2551 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2552 alloc_table (table, table->rows + 1);
2553 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2554 values [MONO_TYPESPEC_SIGNATURE] = token;
2557 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2558 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2564 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2566 MonoDynamicTable *table;
2569 guint32 token, pclass, parent, sig;
2572 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2576 klass = mono_class_from_mono_type (fb->typeb->type);
2577 name = mono_string_to_utf8 (fb->name);
2579 sig = fieldref_encode_signature (assembly, fb->type->type);
2581 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2582 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2584 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2585 parent >>= MONO_TYPEDEFORREF_BITS;
2587 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2589 if (assembly->save) {
2590 alloc_table (table, table->rows + 1);
2591 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2592 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2593 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2594 values [MONO_MEMBERREF_SIGNATURE] = sig;
2597 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2599 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2604 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2612 char *b = blob_size;
2614 if (!assembly->save)
2618 g_assert (helper->type == 2);
2620 if (helper->arguments)
2621 nargs = mono_array_length (helper->arguments);
2625 size = 10 + (nargs * 10);
2627 p = buf = g_malloc (size);
2629 /* Encode calling convention */
2630 /* Change Any to Standard */
2631 if ((helper->call_conv & 0x03) == 0x03)
2632 helper->call_conv = 0x01;
2633 /* explicit_this implies has_this */
2634 if (helper->call_conv & 0x40)
2635 helper->call_conv &= 0x20;
2637 if (helper->call_conv == 0) /* Unmanaged */
2638 *p = helper->unmanaged_call_conv - 1;
2641 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2642 if (helper->call_conv & 0x02) /* varargs */
2647 mono_metadata_encode_value (nargs, p, &p);
2648 encode_reflection_type (assembly, helper->return_type, p, &p);
2649 for (i = 0; i < nargs; ++i) {
2650 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2651 encode_reflection_type (assembly, pt, p, &p);
2654 g_assert (p - buf < size);
2655 mono_metadata_encode_value (p-buf, b, &b);
2656 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2663 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2666 MonoDynamicTable *table;
2669 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2670 idx = table->next_idx ++;
2672 alloc_table (table, table->rows);
2673 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2675 values [MONO_STAND_ALONE_SIGNATURE] =
2676 mono_reflection_encode_sighelper (assembly, helper);
2682 reflection_cc_to_file (int call_conv) {
2683 switch (call_conv & 0x3) {
2685 case 1: return MONO_CALL_DEFAULT;
2686 case 2: return MONO_CALL_VARARG;
2688 g_assert_not_reached ();
2695 MonoMethodSignature *sig;
2701 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2706 MonoMethodSignature *sig;
2709 name = mono_string_to_utf8 (m->name);
2710 nparams = mono_array_length (m->parameters);
2711 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2713 sig->sentinelpos = -1;
2714 sig->call_convention = reflection_cc_to_file (m->call_conv);
2715 sig->param_count = nparams;
2716 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2717 for (i = 0; i < nparams; ++i) {
2718 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2719 sig->params [i] = t->type;
2722 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2724 if (strcmp (name, am->name) == 0 &&
2725 mono_metadata_type_equal (am->parent, m->parent->type) &&
2726 mono_metadata_signature_equal (am->sig, sig)) {
2729 m->table_idx = am->token & 0xffffff;
2733 am = g_new0 (ArrayMethod, 1);
2736 am->parent = m->parent->type;
2737 am->token = mono_image_get_memberref_token (assembly, am->parent,
2738 name, method_encode_signature (assembly, sig));
2739 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2740 m->table_idx = am->token & 0xffffff;
2745 * Insert into the metadata tables all the info about the TypeBuilder tb.
2746 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2749 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2751 MonoDynamicTable *table;
2753 int i, is_object = 0, is_system = 0;
2756 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2757 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2758 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2759 n = mono_string_to_utf8 (tb->name);
2760 if (strcmp (n, "Object") == 0)
2762 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2764 n = mono_string_to_utf8 (tb->nspace);
2765 if (strcmp (n, "System") == 0)
2767 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2769 if (tb->parent && !(is_system && is_object) &&
2770 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2771 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2773 values [MONO_TYPEDEF_EXTENDS] = 0;
2774 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2775 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2778 * if we have explicitlayout or sequentiallayouts, output data in the
2779 * ClassLayout table.
2781 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2782 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2783 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2785 alloc_table (table, table->rows);
2786 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2787 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2788 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2789 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2792 /* handle interfaces */
2793 if (tb->interfaces) {
2794 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2796 table->rows += mono_array_length (tb->interfaces);
2797 alloc_table (table, table->rows);
2798 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2799 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2800 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2801 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2802 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2803 values += MONO_INTERFACEIMPL_SIZE;
2809 table = &assembly->tables [MONO_TABLE_FIELD];
2810 table->rows += tb->num_fields;
2811 alloc_table (table, table->rows);
2812 for (i = 0; i < tb->num_fields; ++i)
2813 mono_image_get_field_info (
2814 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2817 /* handle constructors */
2819 table = &assembly->tables [MONO_TABLE_METHOD];
2820 table->rows += mono_array_length (tb->ctors);
2821 alloc_table (table, table->rows);
2822 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2823 mono_image_get_ctor_info (domain,
2824 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2827 /* handle methods */
2829 table = &assembly->tables [MONO_TABLE_METHOD];
2830 table->rows += tb->num_methods;
2831 alloc_table (table, table->rows);
2832 for (i = 0; i < tb->num_methods; ++i)
2833 mono_image_get_method_info (
2834 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2837 /* Do the same with properties etc.. */
2838 if (tb->events && mono_array_length (tb->events)) {
2839 table = &assembly->tables [MONO_TABLE_EVENT];
2840 table->rows += mono_array_length (tb->events);
2841 alloc_table (table, table->rows);
2842 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2844 alloc_table (table, table->rows);
2845 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2846 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2847 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2848 for (i = 0; i < mono_array_length (tb->events); ++i)
2849 mono_image_get_event_info (
2850 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2852 if (tb->properties && mono_array_length (tb->properties)) {
2853 table = &assembly->tables [MONO_TABLE_PROPERTY];
2854 table->rows += mono_array_length (tb->properties);
2855 alloc_table (table, table->rows);
2856 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2858 alloc_table (table, table->rows);
2859 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2860 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2861 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2862 for (i = 0; i < mono_array_length (tb->properties); ++i)
2863 mono_image_get_property_info (
2864 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2867 /* handle generic parameters */
2868 if (tb->generic_params) {
2869 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2870 table->rows += mono_array_length (tb->generic_params);
2871 alloc_table (table, table->rows);
2872 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2873 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2875 mono_image_get_generic_param_info (
2876 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2880 mono_image_add_decl_security (assembly,
2881 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2885 MonoDynamicTable *ntable;
2887 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2888 ntable->rows += mono_array_length (tb->subtypes);
2889 alloc_table (ntable, ntable->rows);
2890 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2892 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2893 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2895 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2896 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2897 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2898 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2899 mono_string_to_utf8 (tb->name), tb->table_idx,
2900 ntable->next_idx, ntable->rows);*/
2901 values += MONO_NESTED_CLASS_SIZE;
2908 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2912 g_ptr_array_add (types, type);
2914 if (!type->subtypes)
2917 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2918 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2919 collect_types (types, subtype);
2924 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2925 MonoReflectionTypeBuilder **type2)
2927 if ((*type1)->table_idx < (*type2)->table_idx)
2930 if ((*type1)->table_idx > (*type2)->table_idx)
2937 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2942 for (i = 0; i < mono_array_length (pinfo); ++i) {
2943 MonoReflectionParamBuilder *pb;
2944 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2947 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2952 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2955 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2957 for (i = 0; i < tb->num_fields; ++i) {
2958 MonoReflectionFieldBuilder* fb;
2959 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2960 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2964 for (i = 0; i < mono_array_length (tb->events); ++i) {
2965 MonoReflectionEventBuilder* eb;
2966 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2967 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2970 if (tb->properties) {
2971 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2972 MonoReflectionPropertyBuilder* pb;
2973 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2974 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2978 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2979 MonoReflectionCtorBuilder* cb;
2980 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2981 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2982 params_add_cattrs (assembly, cb->pinfo);
2987 for (i = 0; i < tb->num_methods; ++i) {
2988 MonoReflectionMethodBuilder* mb;
2989 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2990 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2991 params_add_cattrs (assembly, mb->pinfo);
2996 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2997 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3002 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3005 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3007 /* no types in the module */
3011 for (i = 0; i < mb->num_types; ++i)
3012 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3016 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
3017 MonoDynamicImage *assembly)
3019 MonoDynamicTable *table;
3023 char *b = blob_size;
3026 table = &assembly->tables [MONO_TABLE_FILE];
3028 alloc_table (table, table->rows);
3029 values = table->values + table->next_idx * MONO_FILE_SIZE;
3030 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3031 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3032 if (module->image->dynamic) {
3033 /* This depends on the fact that the main module is emitted last */
3034 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3035 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3039 path = g_strdup (module->image->name);
3041 mono_sha1_get_digest_from_file (path, hash);
3044 mono_metadata_encode_value (20, b, &b);
3045 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3046 mono_image_add_stream_data (&assembly->blob, hash, 20);
3051 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3053 MonoDynamicTable *table;
3057 table = &assembly->tables [MONO_TABLE_MODULE];
3058 mb->table_idx = table->next_idx ++;
3059 name = mono_string_to_utf8 (mb->module.name);
3060 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3062 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3065 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3066 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3067 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3071 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3072 guint32 module_index, guint32 parent_index,
3073 MonoDynamicImage *assembly)
3075 MonoDynamicTable *table;
3079 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3080 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3083 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3085 alloc_table (table, table->rows);
3086 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3088 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3089 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3090 if (klass->nested_in)
3091 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3093 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3094 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3095 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3097 res = table->next_idx;
3101 /* Emit nested types */
3102 if (klass->nested_classes) {
3105 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3106 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3113 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3114 guint32 module_index, guint32 parent_index,
3115 MonoDynamicImage *assembly)
3120 klass = mono_class_from_mono_type (tb->type.type);
3122 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3124 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3125 parent_index, assembly);
3129 * We need to do this ourselves since klass->nested_classes is not set up.
3132 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3133 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3138 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3139 guint32 module_index,
3140 MonoDynamicImage *assembly)
3142 MonoImage *image = module->image;
3146 t = &image->tables [MONO_TABLE_TYPEDEF];
3148 for (i = 0; i < t->rows; ++i) {
3149 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3151 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3152 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3156 #define align_pointer(base,p)\
3158 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3160 (p) += 4 - (__diff & 3);\
3164 compare_semantics (const void *a, const void *b)
3166 const guint32 *a_values = a;
3167 const guint32 *b_values = b;
3168 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3171 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3175 compare_custom_attrs (const void *a, const void *b)
3177 const guint32 *a_values = a;
3178 const guint32 *b_values = b;
3180 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3184 compare_field_marshal (const void *a, const void *b)
3186 const guint32 *a_values = a;
3187 const guint32 *b_values = b;
3189 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3193 compare_nested (const void *a, const void *b)
3195 const guint32 *a_values = a;
3196 const guint32 *b_values = b;
3198 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3202 compare_genericparam (const void *a, const void *b)
3204 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3205 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3207 return (*a_entry)->owner - (*b_entry)->owner;
3211 compare_declsecurity_attrs (const void *a, const void *b)
3213 const guint32 *a_values = a;
3214 const guint32 *b_values = b;
3216 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3220 pad_heap (MonoDynamicStream *sh)
3222 if (sh->index & 3) {
3223 int sz = 4 - (sh->index & 3);
3224 memset (sh->data + sh->index, 0, sz);
3231 MonoDynamicStream *stream;
3235 * build_compressed_metadata() fills in the blob of data that represents the
3236 * raw metadata as it will be saved in the PE file. The five streams are output
3237 * and the metadata tables are comnpressed from the guint32 array representation,
3238 * to the compressed on-disk format.
3241 build_compressed_metadata (MonoDynamicImage *assembly)
3243 MonoDynamicTable *table;
3245 guint64 valid_mask = 0;
3246 guint64 sorted_mask;
3247 guint32 heapt_size = 0;
3248 guint32 meta_size = 256; /* allow for header and other stuff */
3249 guint32 table_offset;
3250 guint32 ntables = 0;
3256 struct StreamDesc stream_desc [5];
3258 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3259 for (i = 0; i < assembly->gen_params->len; i++){
3260 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3261 write_generic_param_entry (assembly, entry);
3264 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3265 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3266 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3267 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3268 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3270 /* tables that are sorted */
3271 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3272 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3273 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3274 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3275 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3276 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3278 /* Compute table sizes */
3279 /* the MonoImage has already been created in mono_image_basic_init() */
3280 meta = &assembly->image;
3282 /* sizes should be multiple of 4 */
3283 pad_heap (&assembly->blob);
3284 pad_heap (&assembly->guid);
3285 pad_heap (&assembly->sheap);
3286 pad_heap (&assembly->us);
3288 /* Setup the info used by compute_sizes () */
3289 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3290 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3291 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3293 meta_size += assembly->blob.index;
3294 meta_size += assembly->guid.index;
3295 meta_size += assembly->sheap.index;
3296 meta_size += assembly->us.index;
3298 for (i=0; i < 64; ++i)
3299 meta->tables [i].rows = assembly->tables [i].rows;
3301 for (i = 0; i < 64; i++){
3302 if (meta->tables [i].rows == 0)
3304 valid_mask |= (guint64)1 << i;
3306 meta->tables [i].row_size = mono_metadata_compute_size (
3307 meta, i, &meta->tables [i].size_bitfield);
3308 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3310 heapt_size += 24; /* #~ header size */
3311 heapt_size += ntables * 4;
3312 /* make multiple of 4 */
3315 meta_size += heapt_size;
3316 meta->raw_metadata = g_malloc0 (meta_size);
3317 p = meta->raw_metadata;
3318 /* the metadata signature */
3319 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3320 /* version numbers and 4 bytes reserved */
3321 int16val = (guint16*)p;
3322 *int16val++ = GUINT16_TO_LE (1);
3323 *int16val = GUINT16_TO_LE (1);
3325 /* version string */
3326 int32val = (guint32*)p;
3327 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3329 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3330 p += GUINT32_FROM_LE (*int32val);
3331 align_pointer (meta->raw_metadata, p);
3332 int16val = (guint16*)p;
3333 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3334 *int16val = GUINT16_TO_LE (5); /* number of streams */
3338 * write the stream info.
3340 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3341 table_offset += 3; table_offset &= ~3;
3343 assembly->tstream.index = heapt_size;
3344 for (i = 0; i < 5; ++i) {
3345 int32val = (guint32*)p;
3346 stream_desc [i].stream->offset = table_offset;
3347 *int32val++ = GUINT32_TO_LE (table_offset);
3348 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3349 table_offset += GUINT32_FROM_LE (*int32val);
3350 table_offset += 3; table_offset &= ~3;
3352 strcpy (p, stream_desc [i].name);
3353 p += strlen (stream_desc [i].name) + 1;
3354 align_pointer (meta->raw_metadata, p);
3357 * now copy the data, the table stream header and contents goes first.
3359 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3360 p = meta->raw_metadata + assembly->tstream.offset;
3361 int32val = (guint32*)p;
3362 *int32val = GUINT32_TO_LE (0); /* reserved */
3365 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3366 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3367 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3368 *p++ = 1; /* version */
3371 *p++ = 1; /* version */
3375 if (meta->idx_string_wide)
3377 if (meta->idx_guid_wide)
3379 if (meta->idx_blob_wide)
3382 *p++ = 0; /* reserved */
3383 int64val = (guint64*)p;
3384 *int64val++ = GUINT64_TO_LE (valid_mask);
3385 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3387 int32val = (guint32*)p;
3388 for (i = 0; i < 64; i++){
3389 if (meta->tables [i].rows == 0)
3391 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3393 p = (unsigned char*)int32val;
3395 /* sort the tables that still need sorting */
3396 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3398 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3399 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3401 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3402 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3404 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3405 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3407 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3408 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3409 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3411 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3413 /* compress the tables */
3414 for (i = 0; i < 64; i++){
3417 guint32 bitfield = meta->tables [i].size_bitfield;
3418 if (!meta->tables [i].rows)
3420 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3421 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3422 meta->tables [i].base = p;
3423 for (row = 1; row <= meta->tables [i].rows; ++row) {
3424 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3425 for (col = 0; col < assembly->tables [i].columns; ++col) {
3426 switch (mono_metadata_table_size (bitfield, col)) {
3428 *p++ = values [col];
3431 *p++ = values [col] & 0xff;
3432 *p++ = (values [col] >> 8) & 0xff;
3435 *p++ = values [col] & 0xff;
3436 *p++ = (values [col] >> 8) & 0xff;
3437 *p++ = (values [col] >> 16) & 0xff;
3438 *p++ = (values [col] >> 24) & 0xff;
3441 g_assert_not_reached ();
3445 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3448 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3449 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3450 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3451 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3452 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3454 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3458 * Some tables in metadata need to be sorted according to some criteria, but
3459 * when methods and fields are first created with reflection, they may be assigned a token
3460 * that doesn't correspond to the final token they will get assigned after the sorting.
3461 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3462 * with the reflection objects that represent them. Once all the tables are set up, the
3463 * reflection objects will contains the correct table index. fixup_method() will fixup the
3464 * tokens for the method with ILGenerator @ilgen.
3467 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3468 guint32 code_idx = GPOINTER_TO_UINT (value);
3469 MonoReflectionILTokenInfo *iltoken;
3470 MonoReflectionFieldBuilder *field;
3471 MonoReflectionCtorBuilder *ctor;
3472 MonoReflectionMethodBuilder *method;
3473 MonoReflectionTypeBuilder *tb;
3474 MonoReflectionArrayMethod *am;
3476 unsigned char *target;
3478 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3479 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3480 target = assembly->code.data + code_idx + iltoken->code_pos;
3481 switch (target [3]) {
3482 case MONO_TABLE_FIELD:
3483 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3484 field = (MonoReflectionFieldBuilder *)iltoken->member;
3485 idx = field->table_idx;
3486 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3487 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3488 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3490 g_assert_not_reached ();
3493 case MONO_TABLE_METHOD:
3494 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3495 method = (MonoReflectionMethodBuilder *)iltoken->member;
3496 idx = method->table_idx;
3497 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3498 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3499 idx = ctor->table_idx;
3500 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3501 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3502 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3503 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3505 g_assert_not_reached ();
3508 case MONO_TABLE_TYPEDEF:
3509 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3510 g_assert_not_reached ();
3511 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3512 idx = tb->table_idx;
3514 case MONO_TABLE_MEMBERREF:
3515 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3516 am = (MonoReflectionArrayMethod*)iltoken->member;
3517 idx = am->table_idx;
3518 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3519 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3520 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3521 g_assert (m->klass->generic_inst);
3523 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3525 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3526 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3527 g_assert (f->generic_info);
3529 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3532 g_assert_not_reached ();
3535 case MONO_TABLE_METHODSPEC:
3536 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3537 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3538 g_assert (m->signature->generic_param_count);
3541 g_assert_not_reached ();
3545 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3547 target [0] = idx & 0xff;
3548 target [1] = (idx >> 8) & 0xff;
3549 target [2] = (idx >> 16) & 0xff;
3556 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3557 * value is not known when the table is emitted.
3560 fixup_cattrs (MonoDynamicImage *assembly)
3562 MonoDynamicTable *table;
3564 guint32 type, i, idx, token;
3567 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3569 for (i = 0; i < table->rows; ++i) {
3570 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3572 type = values [MONO_CUSTOM_ATTR_TYPE];
3573 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3574 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3575 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3576 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3579 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3580 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3581 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3582 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3589 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3591 MonoDynamicTable *table;
3595 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3597 alloc_table (table, table->rows);
3598 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3599 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3600 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3601 name = mono_string_to_utf8 (rsrc->name);
3602 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3604 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3609 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3611 MonoDynamicTable *table;
3615 char *b = blob_size;
3617 guint32 idx, offset;
3619 if (rsrc->filename) {
3620 name = mono_string_to_utf8 (rsrc->filename);
3621 sname = g_path_get_basename (name);
3623 table = &assembly->tables [MONO_TABLE_FILE];
3625 alloc_table (table, table->rows);
3626 values = table->values + table->next_idx * MONO_FILE_SIZE;
3627 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3628 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3631 mono_sha1_get_digest_from_file (name, hash);
3632 mono_metadata_encode_value (20, b, &b);
3633 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3634 mono_image_add_stream_data (&assembly->blob, hash, 20);
3636 idx = table->next_idx++;
3638 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3641 offset = mono_array_length (rsrc->data);
3642 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3643 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3644 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3645 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3649 * The entry should be emitted into the MANIFESTRESOURCE table of
3650 * the main module, but that needs to reference the FILE table
3651 * which isn't emitted yet.
3658 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3662 set_version_from_string (MonoString *version, guint32 *values)
3664 gchar *ver, *p, *str;
3667 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3668 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3669 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3670 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3673 ver = str = mono_string_to_utf8 (version);
3674 for (i = 0; i < 4; ++i) {
3675 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3681 /* handle Revision and Build */
3691 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3695 char *b = blob_size;
3700 len = mono_array_length (pkey);
3701 mono_metadata_encode_value (len, b, &b);
3702 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3703 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3705 /* need to get the actual value from the key type... */
3706 assembly->strong_name_size = 128;
3707 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3713 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3715 MonoDynamicTable *table;
3716 MonoDynamicImage *assembly;
3717 MonoReflectionAssemblyBuilder *assemblyb;
3722 guint32 module_index;
3724 assemblyb = moduleb->assemblyb;
3725 assembly = moduleb->dynamic_image;
3726 domain = mono_object_domain (assemblyb);
3728 /* Emit ASSEMBLY table */
3729 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3730 alloc_table (table, 1);
3731 values = table->values + MONO_ASSEMBLY_SIZE;
3732 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3733 name = mono_string_to_utf8 (assemblyb->name);
3734 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3736 if (assemblyb->culture) {
3737 name = mono_string_to_utf8 (assemblyb->culture);
3738 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3741 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3743 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3744 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3745 set_version_from_string (assemblyb->version, values);
3747 /* Emit FILE + EXPORTED_TYPE table */
3749 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3751 MonoReflectionModuleBuilder *file_module =
3752 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3753 if (file_module != moduleb) {
3754 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3756 if (file_module->types) {
3757 for (j = 0; j < file_module->num_types; ++j) {
3758 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3759 mono_image_fill_export_table (domain, tb, module_index, 0,
3765 if (assemblyb->loaded_modules) {
3766 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3767 MonoReflectionModule *file_module =
3768 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3769 mono_image_fill_file_table (domain, file_module, assembly);
3771 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3775 /* Emit MANIFESTRESOURCE table */
3777 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3779 MonoReflectionModuleBuilder *file_module =
3780 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3781 /* The table for the main module is emitted later */
3782 if (file_module != moduleb) {
3784 if (file_module->resources) {
3785 int len = mono_array_length (file_module->resources);
3786 for (j = 0; j < len; ++j) {
3787 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3788 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3796 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3797 * for the modulebuilder @moduleb.
3798 * At the end of the process, method and field tokens are fixed up and the
3799 * on-disk compressed metadata representation is created.
3802 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3804 MonoDynamicTable *table;
3805 MonoDynamicImage *assembly;
3806 MonoReflectionAssemblyBuilder *assemblyb;
3811 assemblyb = moduleb->assemblyb;
3812 assembly = moduleb->dynamic_image;
3813 domain = mono_object_domain (assemblyb);
3815 if (assembly->text_rva)
3818 assembly->text_rva = START_TEXT_RVA;
3820 if (moduleb->is_main) {
3821 mono_image_emit_manifest (moduleb);
3824 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3825 table->rows = 1; /* .<Module> */
3827 alloc_table (table, table->rows);
3829 * Set the first entry.
3831 values = table->values + table->columns;
3832 values [MONO_TYPEDEF_FLAGS] = 0;
3833 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3834 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3835 values [MONO_TYPEDEF_EXTENDS] = 0;
3836 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3837 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3840 * handle global methods
3841 * FIXME: test what to do when global methods are defined in multiple modules.
3843 if (moduleb->global_methods) {
3844 table = &assembly->tables [MONO_TABLE_METHOD];
3845 table->rows += mono_array_length (moduleb->global_methods);
3846 alloc_table (table, table->rows);
3847 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3848 mono_image_get_method_info (
3849 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3851 if (moduleb->global_fields) {
3852 table = &assembly->tables [MONO_TABLE_FIELD];
3853 table->rows += mono_array_length (moduleb->global_fields);
3854 alloc_table (table, table->rows);
3855 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3856 mono_image_get_field_info (
3857 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3860 table = &assembly->tables [MONO_TABLE_MODULE];
3861 alloc_table (table, 1);
3862 mono_image_fill_module_table (domain, moduleb, assembly);
3866 /* Collect all types into a list sorted by their table_idx */
3867 GPtrArray *types = g_ptr_array_new ();
3870 for (i = 0; i < moduleb->num_types; ++i) {
3871 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3872 collect_types (types, type);
3875 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3876 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3877 table->rows += types->len;
3878 alloc_table (table, table->rows);
3880 for (i = 0; i < types->len; ++i) {
3881 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3882 mono_image_get_type_info (domain, type, assembly);
3884 g_ptr_array_free (types, TRUE);
3888 * table->rows is already set above and in mono_image_fill_module_table.
3890 /* add all the custom attributes at the end, once all the indexes are stable */
3891 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3893 /* CAS assembly permissions */
3894 if (assemblyb->permissions_minimum)
3895 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3896 if (assemblyb->permissions_optional)
3897 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3898 if (assemblyb->permissions_refused)
3899 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3901 module_add_cattrs (assembly, moduleb);
3904 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3905 fixup_cattrs (assembly);
3909 * mono_image_insert_string:
3910 * @module: module builder object
3913 * Insert @str into the user string stream of @module.
3916 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3918 MonoDynamicImage *assembly;
3923 MONO_ARCH_SAVE_REGS;
3925 if (!module->dynamic_image)
3926 mono_image_module_basic_init (module);
3928 assembly = module->dynamic_image;
3930 if (assembly->save) {
3931 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3932 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3933 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3935 char *swapped = g_malloc (2 * mono_string_length (str));
3936 const char *p = (const char*)mono_string_chars (str);
3938 swap_with_size (swapped, p, 2, mono_string_length (str));
3939 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3943 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3945 mono_image_add_stream_data (&assembly->us, "", 1);
3948 idx = assembly->us.index ++;
3950 mono_g_hash_table_insert (assembly->tokens,
3951 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3953 return MONO_TOKEN_STRING | idx;
3957 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj,
3958 MonoArray *opt_param_types)
3963 klass = obj->vtable->klass;
3964 if (strcmp (klass->name, "MonoMethod") == 0) {
3965 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3966 MonoMethodSignature *sig, *old;
3967 guint32 sig_token, parent;
3970 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3972 nargs = mono_array_length (opt_param_types);
3973 old = method->signature;
3974 sig = mono_metadata_signature_alloc (
3975 &assembly->image, old->param_count + nargs);
3977 sig->hasthis = old->hasthis;
3978 sig->explicit_this = old->explicit_this;
3979 sig->call_convention = old->call_convention;
3980 sig->generic_param_count = old->generic_param_count;
3981 sig->param_count = old->param_count + nargs;
3982 sig->sentinelpos = old->param_count;
3983 sig->ret = old->ret;
3985 for (i = 0; i < old->param_count; i++)
3986 sig->params [i] = old->params [i];
3988 for (i = 0; i < nargs; i++) {
3989 MonoReflectionType *rt = mono_array_get (
3990 opt_param_types, MonoReflectionType *, i);
3991 sig->params [old->param_count + i] = rt->type;
3994 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
3995 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
3996 parent >>= MONO_TYPEDEFORREF_BITS;
3998 parent <<= MONO_MEMBERREF_PARENT_BITS;
3999 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4001 sig_token = method_encode_signature (assembly, sig);
4002 token = mono_image_get_varargs_method_token (
4003 assembly, parent, method->name, sig_token);
4004 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4005 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4006 ReflectionMethodBuilder rmb;
4007 guint32 parent, sig;
4009 reflection_methodbuilder_from_method_builder (&rmb, mb);
4010 rmb.opt_types = opt_param_types;
4012 sig = method_builder_encode_signature (assembly, &rmb);
4014 parent = mono_image_create_token (assembly, obj, TRUE);
4015 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4017 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4018 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4020 token = mono_image_get_varargs_method_token (
4021 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4023 g_error ("requested method token for %s\n", klass->name);
4029 * mono_image_create_token:
4030 * @assembly: a dynamic assembly
4033 * Get a token to insert in the IL code stream for the given MemberInfo.
4034 * @obj can be one of:
4035 * ConstructorBuilder
4045 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4046 gboolean create_methodspec)
4051 klass = obj->vtable->klass;
4052 if (strcmp (klass->name, "MethodBuilder") == 0) {
4053 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4055 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4056 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4058 token = mono_image_get_methodbuilder_token (assembly, mb);
4059 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4061 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4062 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4064 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4065 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4067 token = mono_image_get_ctorbuilder_token (assembly, mb);
4068 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4070 else if (strcmp (klass->name, "FieldBuilder") == 0) {
4071 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4072 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4073 if (tb->generic_params) {
4074 token = mono_image_get_generic_field_token (assembly, fb);
4076 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4079 else if (strcmp (klass->name, "TypeBuilder") == 0) {
4080 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4081 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4083 else if (strcmp (klass->name, "MonoType") == 0 ||
4084 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4085 MonoReflectionType *tb = (MonoReflectionType *)obj;
4086 token = mono_metadata_token_from_dor (
4087 mono_image_typedef_or_ref (assembly, tb->type));
4089 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
4090 MonoReflectionType *tb = (MonoReflectionType *)obj;
4091 token = mono_metadata_token_from_dor (
4092 mono_image_typedef_or_ref (assembly, tb->type));
4094 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4095 strcmp (klass->name, "MonoMethod") == 0) {
4096 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4097 if (m->method->signature->is_inflated) {
4098 if (create_methodspec)
4099 token = mono_image_get_methodspec_token (
4100 assembly, m->method);
4102 token = mono_image_get_inflated_method_token (
4103 assembly, m->method);
4104 } else if (m->method->signature->generic_param_count) {
4105 g_assert_not_reached ();
4106 } else if ((m->method->klass->image == &assembly->image) &&
4107 !m->method->klass->generic_inst) {
4108 static guint32 method_table_idx = 0xffffff;
4109 if (m->method->klass->wastypebuilder) {
4110 /* we use the same token as the one that was assigned
4111 * to the Methodbuilder.
4112 * FIXME: do the equivalent for Fields.
4114 token = m->method->token;
4117 * Each token should have a unique index, but the indexes are
4118 * assigned by managed code, so we don't know about them. An
4119 * easy solution is to count backwards...
4121 method_table_idx --;
4122 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4125 token = mono_image_get_methodref_token (assembly, m->method);
4126 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4128 else if (strcmp (klass->name, "MonoField") == 0) {
4129 MonoReflectionField *f = (MonoReflectionField *)obj;
4130 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4131 static guint32 field_table_idx = 0xffffff;
4133 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4135 token = mono_image_get_fieldref_token (assembly, f);
4136 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4138 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4139 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4140 token = mono_image_get_array_token (assembly, m);
4142 else if (strcmp (klass->name, "SignatureHelper") == 0) {
4143 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4144 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4147 g_error ("requested token for %s\n", klass->name);
4149 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
4156 guint32 import_lookup_table;
4160 guint32 import_address_table_rva;
4168 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4170 static MonoDynamicImage*
4171 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
4172 char *assembly_name, char *module_name)
4174 static const guchar entrycode [16] = {0xff, 0x25, 0};
4175 MonoDynamicImage *image;
4178 const char *version = mono_get_runtime_version ();
4181 image = GC_MALLOC (sizeof (MonoDynamicImage));
4183 image = g_new0 (MonoDynamicImage, 1);
4186 /* keep in sync with image.c */
4187 image->image.name = assembly_name;
4188 image->image.assembly_name = image->image.name; /* they may be different */
4189 image->image.module_name = module_name;
4190 image->image.version = g_strdup (version);
4191 image->image.dynamic = TRUE;
4193 image->image.references = g_new0 (MonoAssembly*, 1);
4194 image->image.references [0] = NULL;
4196 mono_image_init (&image->image);
4198 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4199 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4200 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4201 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4202 image->handleref = g_hash_table_new (NULL, NULL);
4203 image->tokens = mono_g_hash_table_new (NULL, NULL);
4204 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4205 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4206 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4207 image->gen_params = g_ptr_array_new ();
4209 string_heap_init (&image->sheap);
4210 mono_image_add_stream_data (&image->us, "", 1);
4211 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4212 /* import tables... */
4213 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4214 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4215 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4216 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4217 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4218 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4219 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4220 stream_data_align (&image->code);
4222 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4224 for (i=0; i < 64; ++i) {
4225 image->tables [i].next_idx = 1;
4226 image->tables [i].columns = table_sizes [i];
4229 image->image.assembly = (MonoAssembly*)assembly;
4230 image->run = assembly->run;
4231 image->save = assembly->save;
4237 * mono_image_basic_init:
4238 * @assembly: an assembly builder object
4240 * Create the MonoImage that represents the assembly builder and setup some
4241 * of the helper hash table and the basic metadata streams.
4244 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4246 MonoDynamicAssembly *assembly;
4247 MonoDynamicImage *image;
4249 MONO_ARCH_SAVE_REGS;
4251 if (assemblyb->dynamic_assembly)
4255 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4257 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4260 assembly->assembly.dynamic = TRUE;
4261 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4262 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4263 if (assemblyb->culture)
4264 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4266 assembly->assembly.aname.culture = g_strdup ("");
4268 assembly->run = assemblyb->access != 2;
4269 assembly->save = assemblyb->access != 1;
4271 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4272 assembly->assembly.aname.name = image->image.name;
4273 assembly->assembly.image = &image->image;
4275 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4276 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4280 calc_section_size (MonoDynamicImage *assembly)
4284 /* alignment constraints */
4285 assembly->code.index += 3;
4286 assembly->code.index &= ~3;
4287 assembly->meta_size += 3;
4288 assembly->meta_size &= ~3;
4289 assembly->resources.index += 3;
4290 assembly->resources.index &= ~3;
4292 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4293 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4296 if (assembly->win32_res) {
4297 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4299 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4300 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4304 assembly->sections [MONO_SECTION_RELOC].size = 12;
4305 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4315 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4319 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4321 ResTreeNode *t1 = (ResTreeNode*)a;
4322 ResTreeNode *t2 = (ResTreeNode*)b;
4324 return t1->id - t2->id;
4328 * resource_tree_create:
4330 * Organize the resources into a resource tree.
4332 static ResTreeNode *
4333 resource_tree_create (MonoArray *win32_resources)
4335 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4339 tree = g_new0 (ResTreeNode, 1);
4341 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4342 MonoReflectionWin32Resource *win32_res =
4343 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4347 lang_node = g_new0 (ResTreeNode, 1);
4348 lang_node->id = win32_res->lang_id;
4349 lang_node->win32_res = win32_res;
4351 /* Create type node if neccesary */
4353 for (l = tree->children; l; l = l->next)
4354 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4355 type_node = (ResTreeNode*)l->data;
4360 type_node = g_new0 (ResTreeNode, 1);
4361 type_node->id = win32_res->res_type;
4364 * The resource types have to be sorted otherwise
4365 * Windows Explorer can't display the version information.
4367 tree->children = g_slist_insert_sorted (tree->children, type_node,
4368 resource_tree_compare_by_id);
4371 /* Create res node if neccesary */
4373 for (l = type_node->children; l; l = l->next)
4374 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4375 res_node = (ResTreeNode*)l->data;
4380 res_node = g_new0 (ResTreeNode, 1);
4381 res_node->id = win32_res->res_id;
4382 type_node->children = g_slist_append (type_node->children, res_node);
4385 res_node->children = g_slist_append (res_node->children, lang_node);
4392 * resource_tree_encode:
4394 * Encode the resource tree into the format used in the PE file.
4397 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4400 MonoPEResourceDir dir;
4401 MonoPEResourceDirEntry dir_entry;
4402 MonoPEResourceDataEntry data_entry;
4406 * For the format of the resource directory, see the article
4407 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4411 memset (&dir, 0, sizeof (dir));
4412 memset (&dir_entry, 0, sizeof (dir_entry));
4413 memset (&data_entry, 0, sizeof (data_entry));
4415 g_assert (sizeof (dir) == 16);
4416 g_assert (sizeof (dir_entry) == 8);
4417 g_assert (sizeof (data_entry) == 16);
4419 node->offset = p - begin;
4421 /* IMAGE_RESOURCE_DIRECTORY */
4422 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4424 memcpy (p, &dir, sizeof (dir));
4427 /* Reserve space for entries */
4429 p += sizeof (dir_entry) * dir.res_id_entries;
4431 /* Write children */
4432 for (l = node->children; l; l = l->next) {
4433 ResTreeNode *child = (ResTreeNode*)l->data;
4435 if (child->win32_res) {
4437 child->offset = p - begin;
4439 /* IMAGE_RESOURCE_DATA_ENTRY */
4440 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4441 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4443 memcpy (p, &data_entry, sizeof (data_entry));
4444 p += sizeof (data_entry);
4446 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4447 p += data_entry.rde_size;
4450 resource_tree_encode (child, begin, p, &p);
4453 /* IMAGE_RESOURCE_ENTRY */
4454 for (l = node->children; l; l = l->next) {
4455 ResTreeNode *child = (ResTreeNode*)l->data;
4456 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4458 dir_entry.is_dir = child->win32_res ? 0 : 1;
4459 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4461 memcpy (entries, &dir_entry, sizeof (dir_entry));
4462 entries += sizeof (dir_entry);
4469 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4474 MonoReflectionWin32Resource *win32_res;
4477 if (!assemblyb->win32_resources)
4481 * Resources are stored in a three level tree inside the PE file.
4482 * - level one contains a node for each type of resource
4483 * - level two contains a node for each resource
4484 * - level three contains a node for each instance of a resource for a
4485 * specific language.
4488 tree = resource_tree_create (assemblyb->win32_resources);
4490 /* Estimate the size of the encoded tree */
4492 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4493 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4494 size += mono_array_length (win32_res->res_data);
4496 /* Directory structure */
4497 size += mono_array_length (assemblyb->win32_resources) * 256;
4498 p = buf = g_malloc (size);
4500 resource_tree_encode (tree, p, p, &p);
4502 g_assert (p - buf < size);
4504 assembly->win32_res = g_malloc (p - buf);
4505 assembly->win32_res_size = p - buf;
4506 memcpy (assembly->win32_res, buf, p - buf);
4512 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4514 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4517 p += sizeof (MonoPEResourceDir);
4518 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4519 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4520 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4521 if (dir_entry->is_dir)
4522 fixup_resource_directory (res_section, child, rva);
4524 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4525 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4528 p += sizeof (MonoPEResourceDirEntry);
4533 * mono_image_create_pefile:
4534 * @mb: a module builder object
4536 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4537 * assembly->pefile where it can be easily retrieved later in chunks.
4540 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4541 MonoMSDOSHeader *msdos;
4542 MonoDotNetHeader *header;
4543 MonoSectionTable *section;
4544 MonoCLIHeader *cli_header;
4545 guint32 size, image_size, virtual_base, text_offset;
4546 guint32 header_start, section_start, file_offset, virtual_offset;
4547 MonoDynamicImage *assembly;
4548 MonoReflectionAssemblyBuilder *assemblyb;
4549 MonoDynamicStream *pefile;
4551 guint32 *rva, value;
4554 static const unsigned char msheader[] = {
4555 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4556 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4559 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4560 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4561 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4562 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4565 assemblyb = mb->assemblyb;
4567 mono_image_basic_init (assemblyb);
4568 assembly = mb->dynamic_image;
4570 /* already created */
4571 if (assembly->pefile.index)
4574 mono_image_build_metadata (mb);
4576 if (mb->is_main && assemblyb->resources) {
4577 int len = mono_array_length (assemblyb->resources);
4578 for (i = 0; i < len; ++i)
4579 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4582 if (mb->resources) {
4583 int len = mono_array_length (mb->resources);
4584 for (i = 0; i < len; ++i)
4585 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4588 build_compressed_metadata (assembly);
4591 assembly_add_win32_resources (assembly, assemblyb);
4593 nsections = calc_section_size (assembly);
4595 pefile = &assembly->pefile;
4597 /* The DOS header and stub */
4598 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4599 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4601 /* the dotnet header */
4602 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4604 /* the section tables */
4605 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4607 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4608 virtual_offset = VIRT_ALIGN;
4611 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4612 if (!assembly->sections [i].size)
4615 file_offset += FILE_ALIGN - 1;
4616 file_offset &= ~(FILE_ALIGN - 1);
4617 virtual_offset += VIRT_ALIGN - 1;
4618 virtual_offset &= ~(VIRT_ALIGN - 1);
4620 assembly->sections [i].offset = file_offset;
4621 assembly->sections [i].rva = virtual_offset;
4623 file_offset += assembly->sections [i].size;
4624 virtual_offset += assembly->sections [i].size;
4625 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4628 file_offset += FILE_ALIGN - 1;
4629 file_offset &= ~(FILE_ALIGN - 1);
4630 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4632 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4634 /* back-patch info */
4635 msdos = (MonoMSDOSHeader*)pefile->data;
4636 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4637 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4638 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4640 header = (MonoDotNetHeader*)(pefile->data + header_start);
4641 header->pesig [0] = 'P';
4642 header->pesig [1] = 'E';
4644 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4645 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4646 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4647 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4648 if (assemblyb->pekind == 1) {
4650 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4653 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4656 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4658 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4659 header->pe.pe_major = 6;
4660 header->pe.pe_minor = 0;
4661 size = assembly->sections [MONO_SECTION_TEXT].size;
4662 size += FILE_ALIGN - 1;
4663 size &= ~(FILE_ALIGN - 1);
4664 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4665 size = assembly->sections [MONO_SECTION_RSRC].size;
4666 size += FILE_ALIGN - 1;
4667 size &= ~(FILE_ALIGN - 1);
4668 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4669 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4670 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4671 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4672 /* pe_rva_entry_point always at the beginning of the text section */
4673 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4675 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4676 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4677 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4678 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4679 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4680 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4681 size = section_start;
4682 size += FILE_ALIGN - 1;
4683 size &= ~(FILE_ALIGN - 1);
4684 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4686 size += VIRT_ALIGN - 1;
4687 size &= ~(VIRT_ALIGN - 1);
4688 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4691 // Translate the PEFileKind value to the value expected by the Windows loader
4697 // PEFileKinds.Dll == 1
4698 // PEFileKinds.ConsoleApplication == 2
4699 // PEFileKinds.WindowApplication == 3
4702 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4703 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4705 if (assemblyb->pekind == 3)
4710 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4712 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4713 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4714 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4715 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4716 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4717 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4719 /* fill data directory entries */
4721 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4722 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4724 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4725 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4727 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4728 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4729 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4730 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4731 /* patch imported function RVA name */
4732 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4733 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4735 /* the import table */
4736 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4737 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4738 /* patch imported dll RVA name and other entries in the dir */
4739 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4740 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4741 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4742 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4743 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4744 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4746 p = (assembly->code.data + assembly->ilt_offset);
4747 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4748 *p++ = (value) & 0xff;
4749 *p++ = (value >> 8) & (0xff);
4750 *p++ = (value >> 16) & (0xff);
4751 *p++ = (value >> 24) & (0xff);
4753 /* the CLI header info */
4754 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4755 cli_header->ch_size = GUINT32_FROM_LE (72);
4756 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4757 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4758 if (assemblyb->entry_point) {
4759 guint32 table_idx = 0;
4760 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4761 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4762 table_idx = methodb->table_idx;
4765 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4766 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4769 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4770 /* The embedded managed resources */
4771 text_offset = assembly->text_rva + assembly->code.index;
4772 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4773 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4774 text_offset += assembly->resources.index;
4775 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4776 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4777 text_offset += assembly->meta_size;
4778 if (assembly->strong_name_size) {
4779 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4780 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4781 text_offset += assembly->strong_name_size;
4784 /* write the section tables and section content */
4785 section = (MonoSectionTable*)(pefile->data + section_start);
4786 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4787 static const char *section_names [] = {
4788 ".text", ".rsrc", ".reloc"
4790 if (!assembly->sections [i].size)
4792 strcpy (section->st_name, section_names [i]);
4793 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4794 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4795 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4796 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4797 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4798 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4799 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4801 case MONO_SECTION_TEXT:
4802 /* patch entry point */
4803 p = (assembly->code.data + 2);
4804 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4805 *p++ = (value) & 0xff;
4806 *p++ = (value >> 8) & 0xff;
4807 *p++ = (value >> 16) & 0xff;
4808 *p++ = (value >> 24) & 0xff;
4810 text_offset = assembly->sections [i].offset;
4811 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4812 text_offset += assembly->code.index;
4813 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4814 text_offset += assembly->resources.index;
4815 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4816 text_offset += assembly->meta_size;
4817 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4819 g_free (assembly->image.raw_metadata);
4821 case MONO_SECTION_RELOC:
4822 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4823 *rva = GUINT32_FROM_LE (assembly->text_rva);
4825 *rva = GUINT32_FROM_LE (12);
4827 data16 = (guint16*)rva;
4829 * the entrypoint is always at the start of the text section
4830 * 3 is IMAGE_REL_BASED_HIGHLOW
4831 * 2 is patch_size_rva - text_rva
4833 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4835 *data16 = 0; /* terminate */
4837 case MONO_SECTION_RSRC:
4838 if (assembly->win32_res) {
4839 text_offset = assembly->sections [i].offset;
4841 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4842 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4844 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4848 g_assert_not_reached ();
4853 /* check that the file is properly padded */
4856 FILE *f = fopen ("mypetest.exe", "w");
4857 fwrite (pefile->data, pefile->index, 1, f);
4863 MonoReflectionModule *
4864 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4868 MonoImageOpenStatus status;
4869 MonoDynamicAssembly *assembly;
4871 name = mono_string_to_utf8 (fileName);
4873 image = mono_image_open (name, &status);
4876 if (status == MONO_IMAGE_ERROR_ERRNO)
4877 exc = mono_get_exception_file_not_found (fileName);
4879 exc = mono_get_exception_bad_image_format (name);
4881 mono_raise_exception (exc);
4886 assembly = ab->dynamic_assembly;
4887 image->assembly = (MonoAssembly*)assembly;
4889 mono_assembly_load_references (image, &status);
4891 mono_image_close (image);
4892 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4895 return mono_module_get_object (mono_domain_get (), image);
4899 * We need to return always the same object for MethodInfo, FieldInfo etc..
4900 * but we need to consider the reflected type.
4901 * type uses a different hash, since it uses custom hash/equal functions.
4906 MonoClass *refclass;
4910 reflected_equal (gconstpointer a, gconstpointer b) {
4911 const ReflectedEntry *ea = a;
4912 const ReflectedEntry *eb = b;
4914 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4918 reflected_hash (gconstpointer a) {
4919 const ReflectedEntry *ea = a;
4920 return GPOINTER_TO_UINT (ea->item);
4923 #define CHECK_OBJECT(t,p,k) \
4929 mono_domain_lock (domain); \
4930 if (!domain->refobject_hash) \
4931 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4932 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4933 mono_domain_unlock (domain); \
4939 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4941 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4944 #define CACHE_OBJECT(p,o,k) \
4946 ReflectedEntry *e = ALLOC_REFENTRY; \
4948 e->refclass = (k); \
4949 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4950 mono_domain_unlock (domain); \
4954 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4956 /* this is done only once */
4957 mono_domain_lock (domain);
4958 CACHE_OBJECT (assembly, res, NULL);
4962 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4964 /* this is done only once */
4965 mono_domain_lock (domain);
4966 CACHE_OBJECT (module, res, NULL);
4970 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4972 MonoDynamicImage *image = moduleb->dynamic_image;
4973 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4976 * FIXME: we already created an image in mono_image_basic_init (), but
4977 * we don't know which module it belongs to, since that is only
4978 * determined at assembly save time.
4980 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
4981 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4983 moduleb->module.image = &image->image;
4984 moduleb->dynamic_image = image;
4985 register_module (mono_object_domain (moduleb), moduleb, image);
4990 * mono_assembly_get_object:
4991 * @domain: an app domain
4992 * @assembly: an assembly
4994 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4996 MonoReflectionAssembly*
4997 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4999 static MonoClass *System_Reflection_Assembly;
5000 MonoReflectionAssembly *res;
5002 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5003 if (!System_Reflection_Assembly)
5004 System_Reflection_Assembly = mono_class_from_name (
5005 mono_defaults.corlib, "System.Reflection", "Assembly");
5006 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5007 res->assembly = assembly;
5008 CACHE_OBJECT (assembly, res, NULL);
5014 MonoReflectionModule*
5015 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5017 static MonoClass *System_Reflection_Module;
5018 MonoReflectionModule *res;
5020 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5021 if (!System_Reflection_Module)
5022 System_Reflection_Module = mono_class_from_name (
5023 mono_defaults.corlib, "System.Reflection", "Module");
5024 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5027 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5029 res->fqname = mono_string_new (domain, image->name);
5030 res->name = mono_string_new (domain, g_path_get_basename (image->name));
5031 res->scopename = mono_string_new (domain, image->module_name);
5033 if (image->assembly->image == image)
5034 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5037 g_assert (image->assembly->image->modules);
5039 while (image->assembly->image->modules [i])
5040 if (image->assembly->image->modules [i] == image)
5041 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5042 g_assert (res->token);
5045 mono_image_addref (image);
5047 CACHE_OBJECT (image, res, NULL);
5051 MonoReflectionModule*
5052 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5054 static MonoClass *System_Reflection_Module;
5055 MonoReflectionModule *res;
5056 MonoTableInfo *table;
5057 guint32 cols [MONO_FILE_SIZE];
5059 guint32 i, name_idx;
5062 if (!System_Reflection_Module)
5063 System_Reflection_Module = mono_class_from_name (
5064 mono_defaults.corlib, "System.Reflection", "Module");
5065 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5067 table = &image->tables [MONO_TABLE_FILE];
5068 g_assert (table_index < table->rows);
5069 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5072 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5073 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5075 /* Check whenever the row has a corresponding row in the moduleref table */
5076 table = &image->tables [MONO_TABLE_MODULEREF];
5077 for (i = 0; i < table->rows; ++i) {
5078 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5079 val = mono_metadata_string_heap (image, name_idx);
5080 if (strcmp (val, name) == 0)
5081 res->image = image->modules [i];
5084 res->fqname = mono_string_new (domain, name);
5085 res->name = mono_string_new (domain, name);
5086 res->scopename = mono_string_new (domain, name);
5087 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5088 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5094 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5096 if ((t1->type != t2->type) ||
5097 (t1->byref != t2->byref))
5101 case MONO_TYPE_VOID:
5102 case MONO_TYPE_BOOLEAN:
5103 case MONO_TYPE_CHAR:
5114 case MONO_TYPE_STRING:
5117 case MONO_TYPE_OBJECT:
5118 case MONO_TYPE_TYPEDBYREF:
5120 case MONO_TYPE_VALUETYPE:
5121 case MONO_TYPE_CLASS:
5122 case MONO_TYPE_SZARRAY:
5123 return t1->data.klass == t2->data.klass;
5125 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5126 case MONO_TYPE_ARRAY:
5127 if (t1->data.array->rank != t2->data.array->rank)
5129 return t1->data.array->eklass == t2->data.array->eklass;
5130 case MONO_TYPE_GENERICINST: {
5132 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5134 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5136 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5137 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5143 case MONO_TYPE_MVAR:
5144 return t1->data.generic_param == t2->data.generic_param;
5146 g_error ("implement type compare for %0x!", t1->type);
5154 mymono_metadata_type_hash (MonoType *t1)
5160 hash |= t1->byref << 6; /* do not collide with t1->type values */
5162 case MONO_TYPE_VALUETYPE:
5163 case MONO_TYPE_CLASS:
5164 case MONO_TYPE_SZARRAY:
5165 /* check if the distribution is good enough */
5166 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5168 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5173 static MonoReflectionGenericInst*
5174 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5176 static MonoClass *System_Reflection_MonoGenericInst;
5177 MonoReflectionGenericInst *res;
5178 MonoGenericInst *ginst;
5181 if (!System_Reflection_MonoGenericInst) {
5182 System_Reflection_MonoGenericInst = mono_class_from_name (
5183 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5184 g_assert (System_Reflection_MonoGenericInst);
5187 ginst = geninst->data.generic_inst;
5188 gklass = mono_class_from_mono_type (ginst->generic_type);
5190 mono_class_init (ginst->klass);
5192 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5194 res->type.type = geninst;
5195 if (gklass->wastypebuilder && gklass->reflection_info)
5196 res->generic_type = gklass->reflection_info;
5198 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5204 * mono_type_get_object:
5205 * @domain: an app domain
5208 * Return an System.MonoType object representing the type @type.
5211 mono_type_get_object (MonoDomain *domain, MonoType *type)
5213 MonoReflectionType *res;
5214 MonoClass *klass = mono_class_from_mono_type (type);
5216 mono_domain_lock (domain);
5217 if (!domain->type_hash)
5218 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5219 (GCompareFunc)mymono_metadata_type_equal);
5220 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5221 mono_domain_unlock (domain);
5224 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5225 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5226 mono_g_hash_table_insert (domain->type_hash, type, res);
5227 mono_domain_unlock (domain);
5230 if (klass->reflection_info && !klass->wastypebuilder) {
5231 /* g_assert_not_reached (); */
5232 /* should this be considered an error condition? */
5234 mono_domain_unlock (domain);
5235 return klass->reflection_info;
5238 mono_class_init (klass);
5239 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5241 mono_g_hash_table_insert (domain->type_hash, type, res);
5242 mono_domain_unlock (domain);
5247 * mono_method_get_object:
5248 * @domain: an app domain
5250 * @refclass: the reflected type (can be NULL)
5252 * Return an System.Reflection.MonoMethod object representing the method @method.
5254 MonoReflectionMethod*
5255 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5258 * We use the same C representation for methods and constructors, but the type
5259 * name in C# is different.
5263 MonoReflectionMethod *ret;
5266 refclass = method->klass;
5268 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5269 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5270 cname = "MonoCMethod";
5272 cname = "MonoMethod";
5273 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5275 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5276 ret->method = method;
5277 ret->name = mono_string_new (domain, method->name);
5278 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5279 CACHE_OBJECT (method, ret, refclass);
5284 * mono_field_get_object:
5285 * @domain: an app domain
5289 * Return an System.Reflection.MonoField object representing the field @field
5292 MonoReflectionField*
5293 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5295 MonoReflectionField *res;
5298 CHECK_OBJECT (MonoReflectionField *, field, klass);
5299 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5300 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5303 res->name = mono_string_new (domain, field->name);
5304 if (field->generic_info)
5305 res->attrs = field->generic_info->generic_type->attrs;
5307 res->attrs = field->type->attrs;
5308 res->type = mono_type_get_object (domain, field->type);
5309 CACHE_OBJECT (field, res, klass);
5314 * mono_property_get_object:
5315 * @domain: an app domain
5317 * @property: a property
5319 * Return an System.Reflection.MonoProperty object representing the property @property
5322 MonoReflectionProperty*
5323 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5325 MonoReflectionProperty *res;
5328 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5329 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5330 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5332 res->property = property;
5333 CACHE_OBJECT (property, res, klass);
5338 * mono_event_get_object:
5339 * @domain: an app domain
5343 * Return an System.Reflection.MonoEvent object representing the event @event
5346 MonoReflectionEvent*
5347 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5349 MonoReflectionEvent *res;
5352 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5353 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5354 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5357 CACHE_OBJECT (event, res, klass);
5362 * mono_param_get_objects:
5363 * @domain: an app domain
5366 * Return an System.Reflection.ParameterInfo array object representing the parameters
5367 * in the method @method.
5370 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5372 static MonoClass *System_Reflection_ParameterInfo;
5374 MonoArray *res = NULL;
5375 MonoReflectionMethod *member = NULL;
5376 MonoReflectionParameter *param = NULL;
5377 char **names, **blobs = NULL;
5378 MonoObject *dbnull = mono_get_dbnull_object (domain);
5381 if (!System_Reflection_ParameterInfo)
5382 System_Reflection_ParameterInfo = mono_class_from_name (
5383 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5385 if (!method->signature->param_count)
5386 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5388 /* Note: the cache is based on the address of the signature into the method
5389 * since we already cache MethodInfos with the method as keys.
5391 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5393 member = mono_method_get_object (domain, method, NULL);
5394 names = g_new (char *, method->signature->param_count);
5395 mono_method_get_param_names (method, (const char **) names);
5397 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5398 for (i = 0; i < method->signature->param_count; ++i) {
5399 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5400 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5401 param->MemberImpl = (MonoObject*)member;
5402 param->NameImpl = mono_string_new (domain, names [i]);
5403 param->PositionImpl = i;
5404 param->AttrsImpl = method->signature->params [i]->attrs;
5406 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5407 param->DefaultValueImpl = dbnull;
5409 MonoType *type = param->ClassImpl->type;
5412 blobs = g_new0 (char *, method->signature->param_count);
5413 get_default_param_value_blobs (method, blobs);
5416 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5418 if (!param->DefaultValueImpl) {
5419 param->DefaultValueImpl = dbnull;
5423 mono_array_set (res, gpointer, i, param);
5428 CACHE_OBJECT (&(method->signature), res, NULL);
5433 mono_get_dbnull_object (MonoDomain *domain)
5437 static MonoClassField *dbnull_value_field = NULL;
5439 if (!dbnull_value_field) {
5440 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5441 mono_class_init (klass);
5442 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5443 g_assert (dbnull_value_field);
5445 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5452 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5454 guint32 param_index, i, lastp, crow = 0;
5455 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5458 MonoClass *klass = method->klass;
5459 MonoImage *image = klass->image;
5460 MonoDomain *domain = mono_domain_get ();
5461 MonoMethodSignature *methodsig = method->signature;
5463 MonoTableInfo *constt;
5464 MonoTableInfo *methodt;
5465 MonoTableInfo *paramt;
5467 if (!methodsig->param_count)
5470 if (klass->generic_inst) {
5471 return; /* FIXME - ??? */
5474 mono_class_init (klass);
5476 if (klass->image->dynamic) {
5480 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5481 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5482 constt = &image->tables [MONO_TABLE_CONSTANT];
5484 for (i = 0; i < klass->method.count; ++i) {
5485 if (method == klass->methods [i]) {
5486 idx = klass->method.first + i;
5491 g_assert (idx != -1);
5493 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5494 if (idx + 1 < methodt->rows)
5495 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5497 lastp = paramt->rows + 1;
5499 for (i = param_index; i < lastp; ++i) {
5502 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5503 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5505 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5508 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5513 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5514 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5521 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5530 klass = mono_class_from_mono_type (type);
5531 if (klass->valuetype) {
5532 object = mono_object_new (domain, klass);
5533 retval = ((gchar *) object + sizeof (MonoObject));
5538 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5545 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5549 memset (assembly, 0, sizeof (MonoAssemblyName));
5551 assembly->culture = "";
5552 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5554 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5557 while (*p == ' ' || *p == ',') {
5566 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5568 assembly->major = strtoul (p, &s, 10);
5569 if (s == p || *s != '.')
5572 assembly->minor = strtoul (p, &s, 10);
5573 if (s == p || *s != '.')
5576 assembly->build = strtoul (p, &s, 10);
5577 if (s == p || *s != '.')
5580 assembly->revision = strtoul (p, &s, 10);
5584 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5586 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5587 assembly->culture = "";
5590 assembly->culture = p;
5591 while (*p && *p != ',') {
5595 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5597 if (strncmp (p, "null", 4) == 0) {
5602 while (*p && *p != ',') {
5605 len = (p - start + 1);
5606 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5607 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5608 g_strlcpy (assembly->public_key_token, start, len);
5611 while (*p && *p != ',')
5615 while (*p == ' ' || *p == ',') {
5629 * mono_reflection_parse_type:
5632 * Parse a type name as accepted by the GetType () method and output the info
5633 * extracted in the info structure.
5634 * the name param will be mangled, so, make a copy before passing it to this function.
5635 * The fields in info will be valid until the memory pointed to by name is valid.
5636 * Returns 0 on parse error.
5637 * See also mono_type_get_name () below.
5640 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5642 char *start, *p, *w, *last_point, *startn;
5643 int in_modifiers = 0;
5644 int isbyref = 0, rank;
5646 start = p = w = name;
5648 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5649 info->name = info->name_space = NULL;
5650 info->nested = NULL;
5651 info->modifiers = NULL;
5653 /* last_point separates the namespace from the name */
5659 *p = 0; /* NULL terminate the name */
5661 info->nested = g_list_append (info->nested, startn);
5662 /* we have parsed the nesting namespace + name */
5666 info->name_space = start;
5668 info->name = last_point + 1;
5670 info->name_space = (char *)"";
5696 info->name_space = start;
5698 info->name = last_point + 1;
5700 info->name_space = (char *)"";
5707 if (isbyref) /* only one level allowed by the spec */
5710 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5714 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5725 else if (*p != '*') /* '*' means unknown lower bound */
5731 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5743 return 0; /* missing assembly name */
5744 if (!assembly_name_to_aname (&info->assembly, p))
5751 if (info->assembly.name)
5754 *w = 0; /* terminate class name */
5755 if (!info->name || !*info->name)
5757 /* add other consistency checks */
5762 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5769 image = mono_defaults.corlib;
5772 klass = mono_class_from_name_case (image, info->name_space, info->name);
5774 klass = mono_class_from_name (image, info->name_space, info->name);
5777 for (mod = info->nested; mod; mod = mod->next) {
5780 mono_class_init (klass);
5781 nested = klass->nested_classes;
5784 klass = nested->data;
5786 if (g_strcasecmp (klass->name, mod->data) == 0)
5789 if (strcmp (klass->name, mod->data) == 0)
5793 nested = nested->next;
5800 mono_class_init (klass);
5801 for (mod = info->modifiers; mod; mod = mod->next) {
5802 modval = GPOINTER_TO_UINT (mod->data);
5803 if (!modval) { /* byref: must be last modifier */
5804 return &klass->this_arg;
5805 } else if (modval == -1) {
5806 klass = mono_ptr_class_get (&klass->byval_arg);
5807 } else { /* array rank */
5808 klass = mono_array_class_get (klass, modval);
5810 mono_class_init (klass);
5813 return &klass->byval_arg;
5817 * mono_reflection_get_type:
5818 * @image: a metadata context
5819 * @info: type description structure
5820 * @ignorecase: flag for case-insensitive string compares
5821 * @type_resolve: whenever type resolve was already tried
5823 * Build a MonoType from the type description in @info.
5828 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5831 MonoReflectionAssembly *assembly;
5835 type = mono_reflection_get_type_internal (image, info, ignorecase);
5838 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5841 /* FIXME: Enabling this causes regressions (#65577) */
5847 *type_resolve = TRUE;
5851 /* Reconstruct the type name */
5852 fullName = g_string_new ("");
5853 if (info->name_space && (info->name_space [0] != '\0'))
5854 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5856 g_string_printf (fullName, info->name);
5857 for (mod = info->nested; mod; mod = mod->next)
5858 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5861 mono_domain_try_type_resolve (
5862 mono_domain_get (), fullName->str, NULL);
5863 if (assembly && (!image || (assembly->assembly->image == image))) {
5865 if (assembly->assembly->dynamic) {
5866 /* Enumerate all modules */
5867 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5871 if (abuilder->modules) {
5872 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5873 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5874 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5880 if (!type && abuilder->loaded_modules) {
5881 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5882 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5883 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5890 type = mono_reflection_get_type_internal (assembly->assembly->image,
5893 g_string_free (fullName, TRUE);
5898 * mono_reflection_type_from_name:
5900 * @image: a metadata context (can be NULL).
5902 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5903 * it defaults to get the type from @image or, if @image is NULL or loading
5904 * from it fails, uses corlib.
5908 mono_reflection_type_from_name (char *name, MonoImage *image)
5911 MonoTypeNameParse info;
5912 MonoAssembly *assembly;
5914 gboolean type_resolve = FALSE;
5916 /* Make a copy since parse_type modifies its argument */
5917 tmp = g_strdup (name);
5919 /*g_print ("requested type %s\n", str);*/
5920 if (!mono_reflection_parse_type (tmp, &info)) {
5922 g_list_free (info.modifiers);
5923 g_list_free (info.nested);
5927 if (info.assembly.name) {
5928 assembly = mono_assembly_loaded (&info.assembly);
5930 /* then we must load the assembly ourselve - see #60439 */
5931 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5934 g_list_free (info.modifiers);
5935 g_list_free (info.nested);
5939 image = assembly->image;
5940 } else if (image == NULL) {
5941 image = mono_defaults.corlib;
5944 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5945 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5946 image = mono_defaults.corlib;
5947 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5951 g_list_free (info.modifiers);
5952 g_list_free (info.nested);
5957 * mono_reflection_get_token:
5959 * Return the metadata token of OBJ which should be an object
5960 * representing a metadata element.
5963 mono_reflection_get_token (MonoObject *obj)
5968 klass = obj->vtable->klass;
5970 if (strcmp (klass->name, "MethodBuilder") == 0) {
5971 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5973 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5975 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5976 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5978 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5980 else if (strcmp (klass->name, "FieldBuilder") == 0) {
5981 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5982 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5983 if (tb->generic_params) {
5984 g_assert_not_reached ();
5986 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5989 else if (strcmp (klass->name, "TypeBuilder") == 0) {
5990 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5991 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5993 else if (strcmp (klass->name, "MonoType") == 0) {
5994 MonoReflectionType *tb = (MonoReflectionType *)obj;
5995 token = mono_class_from_mono_type (tb->type)->type_token;
5997 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5998 strcmp (klass->name, "MonoMethod") == 0) {
5999 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6000 if (m->method->signature->is_inflated) {
6001 g_assert_not_reached ();
6002 } else if (m->method->signature->generic_param_count) {
6003 g_assert_not_reached ();
6004 } else if (m->method->klass->generic_inst) {
6005 g_assert_not_reached ();
6007 token = m->method->token;
6010 else if (strcmp (klass->name, "MonoField") == 0) {
6011 MonoReflectionField *f = (MonoReflectionField*)obj;
6013 token = mono_class_get_field_token (f->field);
6015 else if (strcmp (klass->name, "MonoProperty") == 0) {
6016 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6018 token = mono_class_get_property_token (p->property);
6020 else if (strcmp (klass->name, "MonoEvent") == 0) {
6021 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6023 token = mono_class_get_event_token (p->event);
6025 else if (strcmp (klass->name, "ParameterInfo") == 0) {
6026 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6028 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6030 else if (strcmp (klass->name, "Module") == 0) {
6031 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6035 else if (strcmp (klass->name, "Assembly") == 0) {
6036 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6039 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6040 MonoException *ex = mono_get_exception_not_implemented (msg);
6042 mono_raise_exception (ex);
6049 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6051 int slen, type = t->type;
6056 case MONO_TYPE_BOOLEAN: {
6057 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6062 case MONO_TYPE_CHAR:
6064 case MONO_TYPE_I2: {
6065 guint16 *val = g_malloc (sizeof (guint16));
6070 #if SIZEOF_VOID_P == 4
6076 case MONO_TYPE_I4: {
6077 guint32 *val = g_malloc (sizeof (guint32));
6082 #if SIZEOF_VOID_P == 8
6083 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6088 case MONO_TYPE_I8: {
6089 guint64 *val = g_malloc (sizeof (guint64));
6094 case MONO_TYPE_VALUETYPE:
6095 if (t->data.klass->enumtype) {
6096 type = t->data.klass->enum_basetype->type;
6099 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6102 case MONO_TYPE_STRING:
6103 if (*p == (char)0xFF) {
6107 slen = mono_metadata_decode_value (p, &p);
6109 return mono_string_new_len (mono_domain_get (), p, slen);
6110 case MONO_TYPE_CLASS: {
6113 if (*p == (char)0xFF) {
6118 slen = mono_metadata_decode_value (p, &p);
6119 n = g_memdup (p, slen + 1);
6121 t = mono_reflection_type_from_name (n, image);
6123 g_warning ("Cannot load type '%s'", n);
6127 return mono_type_get_object (mono_domain_get (), t);
6131 case MONO_TYPE_OBJECT: {
6134 MonoClass *subc = NULL;
6139 } else if (subt == 0x0E) {
6140 type = MONO_TYPE_STRING;
6142 } else if (subt == 0x55) {
6145 slen = mono_metadata_decode_value (p, &p);
6146 n = g_memdup (p, slen + 1);
6148 t = mono_reflection_type_from_name (n, image);
6150 g_warning ("Cannot load type '%s'", n);
6153 subc = mono_class_from_mono_type (t);
6154 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6155 MonoType simple_type = {{0}};
6156 simple_type.type = subt;
6157 subc = mono_class_from_mono_type (&simple_type);
6159 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6161 val = load_cattr_value (image, &subc->byval_arg, p, end);
6162 obj = mono_object_new (mono_domain_get (), subc);
6163 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6167 case MONO_TYPE_SZARRAY:
6170 guint32 i, alen, basetype;
6173 if (alen == 0xffffffff) {
6177 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6178 basetype = t->data.klass->byval_arg.type;
6183 case MONO_TYPE_BOOLEAN:
6184 for (i=0;i<alen;i++)
6186 MonoBoolean val=*p++;
6187 mono_array_set(arr,MonoBoolean,i,val);
6190 case MONO_TYPE_CHAR:
6193 for (i=0;i<alen;i++)
6195 guint16 val=read16(p);
6196 mono_array_set(arr,guint16,i,val);
6203 for (i=0;i<alen;i++)
6205 guint32 val=read32(p);
6206 mono_array_set(arr,guint32,i,val);
6213 for (i=0;i<alen;i++)
6215 guint64 val=read64(p);
6216 mono_array_set(arr,guint64,i,val);
6220 case MONO_TYPE_CLASS:
6221 case MONO_TYPE_OBJECT:
6222 case MONO_TYPE_STRING:
6223 for (i = 0; i < alen; i++) {
6224 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6225 mono_array_set (arr, gpointer, i, item);
6229 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6235 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6241 type_is_reference (MonoType *type)
6243 switch (type->type) {
6244 case MONO_TYPE_BOOLEAN:
6245 case MONO_TYPE_CHAR:
6258 case MONO_TYPE_VALUETYPE:
6266 free_param_data (MonoMethodSignature *sig, void **params) {
6268 for (i = 0; i < sig->param_count; ++i) {
6269 if (!type_is_reference (sig->params [i]))
6270 g_free (params [i]);
6275 * Find the method index in the metadata methodDef table.
6276 * Later put these three helper methods in metadata and export them.
6279 find_method_index (MonoMethod *method) {
6280 MonoClass *klass = method->klass;
6283 for (i = 0; i < klass->method.count; ++i) {
6284 if (method == klass->methods [i])
6285 return klass->method.first + 1 + i;
6291 * Find the field index in the metadata FieldDef table.
6294 find_field_index (MonoClass *klass, MonoClassField *field) {
6297 for (i = 0; i < klass->field.count; ++i) {
6298 if (field == &klass->fields [i])
6299 return klass->field.first + 1 + i;
6305 * Find the property index in the metadata Property table.
6308 find_property_index (MonoClass *klass, MonoProperty *property) {
6311 for (i = 0; i < klass->property.count; ++i) {
6312 if (property == &klass->properties [i])
6313 return klass->property.first + 1 + i;
6319 * Find the event index in the metadata Event table.
6322 find_event_index (MonoClass *klass, MonoEvent *event) {
6325 for (i = 0; i < klass->event.count; ++i) {
6326 if (event == &klass->events [i])
6327 return klass->event.first + 1 + i;
6333 create_custom_attr (MonoImage *image, MonoMethod *method,
6334 const char *data, guint32 len)
6336 const char *p = data;
6338 guint32 i, j, num_named;
6342 mono_class_init (method->klass);
6345 attr = mono_object_new (mono_domain_get (), method->klass);
6346 mono_runtime_invoke (method, attr, NULL, NULL);
6350 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6353 /*g_print ("got attr %s\n", method->klass->name);*/
6355 params = g_new (void*, method->signature->param_count);
6359 for (i = 0; i < method->signature->param_count; ++i) {
6360 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6364 attr = mono_object_new (mono_domain_get (), method->klass);
6365 mono_runtime_invoke (method, attr, params, NULL);
6366 free_param_data (method->signature, params);
6368 num_named = read16 (named);
6370 for (j = 0; j < num_named; j++) {
6372 char *name, named_type, data_type;
6373 named_type = *named++;
6374 data_type = *named++; /* type of data */
6375 if (data_type == 0x55) {
6378 type_len = mono_metadata_decode_blob_size (named, &named);
6379 type_name = g_malloc (type_len + 1);
6380 memcpy (type_name, named, type_len);
6381 type_name [type_len] = 0;
6383 /* FIXME: lookup the type and check type consistency */
6384 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6385 /* this seems to be the type of the element of the array */
6386 /* g_print ("skipping 0x%02x after prop\n", *named); */
6389 name_len = mono_metadata_decode_blob_size (named, &named);
6390 name = g_malloc (name_len + 1);
6391 memcpy (name, named, name_len);
6392 name [name_len] = 0;
6394 if (named_type == 0x53) {
6395 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6396 void *val = load_cattr_value (image, field->type, named, &named);
6397 mono_field_set_value (attr, field, val);
6398 if (!type_is_reference (field->type))
6400 } else if (named_type == 0x54) {
6403 MonoType *prop_type;
6405 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6406 /* can we have more that 1 arg in a custom attr named property? */
6407 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6408 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6409 mono_property_set_value (prop, attr, pparams, NULL);
6410 if (!type_is_reference (prop_type))
6411 g_free (pparams [0]);
6420 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6427 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6428 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6429 for (i = 0; i < cinfo->num_attrs; ++i) {
6430 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6431 mono_array_set (result, gpointer, i, attr);
6437 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6439 guint32 mtoken, i, len;
6440 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6442 MonoCustomAttrInfo *ainfo;
6443 GList *tmp, *list = NULL;
6446 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6448 i = mono_metadata_custom_attrs_from_index (image, idx);
6452 while (i < ca->rows) {
6453 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6455 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6458 len = g_list_length (list);
6461 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6462 ainfo->num_attrs = len;
6463 ainfo->image = image;
6464 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6465 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6466 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6467 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6468 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6469 mtoken |= MONO_TOKEN_METHOD_DEF;
6471 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6472 mtoken |= MONO_TOKEN_MEMBER_REF;
6475 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6478 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6479 if (!ainfo->attrs [i].ctor)
6480 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6481 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6482 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6483 ainfo->attrs [i].data = data;
6491 mono_custom_attrs_from_method (MonoMethod *method)
6493 MonoCustomAttrInfo *cinfo;
6496 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6498 idx = find_method_index (method);
6499 idx <<= MONO_CUSTOM_ATTR_BITS;
6500 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6501 return mono_custom_attrs_from_index (method->klass->image, idx);
6505 mono_custom_attrs_from_class (MonoClass *klass)
6507 MonoCustomAttrInfo *cinfo;
6510 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6512 idx = mono_metadata_token_index (klass->type_token);
6513 idx <<= MONO_CUSTOM_ATTR_BITS;
6514 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6515 return mono_custom_attrs_from_index (klass->image, idx);
6519 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6521 MonoCustomAttrInfo *cinfo;
6524 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6526 idx = 1; /* there is only one assembly */
6527 idx <<= MONO_CUSTOM_ATTR_BITS;
6528 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6529 return mono_custom_attrs_from_index (assembly->image, idx);
6532 static MonoCustomAttrInfo*
6533 mono_custom_attrs_from_module (MonoImage *image)
6535 MonoCustomAttrInfo *cinfo;
6538 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6540 idx = 1; /* there is only one module */
6541 idx <<= MONO_CUSTOM_ATTR_BITS;
6542 idx |= MONO_CUSTOM_ATTR_MODULE;
6543 return mono_custom_attrs_from_index (image, idx);
6547 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6549 MonoCustomAttrInfo *cinfo;
6552 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6554 idx = find_property_index (klass, property);
6555 idx <<= MONO_CUSTOM_ATTR_BITS;
6556 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6557 return mono_custom_attrs_from_index (klass->image, idx);
6561 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6563 MonoCustomAttrInfo *cinfo;
6566 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6568 idx = find_event_index (klass, event);
6569 idx <<= MONO_CUSTOM_ATTR_BITS;
6570 idx |= MONO_CUSTOM_ATTR_EVENT;
6571 return mono_custom_attrs_from_index (klass->image, idx);
6575 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6577 MonoCustomAttrInfo *cinfo;
6580 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6582 idx = find_field_index (klass, field);
6583 idx <<= MONO_CUSTOM_ATTR_BITS;
6584 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6585 return mono_custom_attrs_from_index (klass->image, idx);
6589 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6592 guint32 i, idx, method_index;
6593 guint32 param_list, param_last, param_pos, found;
6595 MonoReflectionMethodAux *aux;
6597 if (method->klass->image->dynamic) {
6598 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6599 if (!aux || !aux->param_cattr)
6601 return aux->param_cattr [param];
6604 image = method->klass->image;
6605 method_index = find_method_index (method);
6606 ca = &image->tables [MONO_TABLE_METHOD];
6608 if (method->klass->generic_inst || method->klass->gen_params ||
6609 method->signature->generic_param_count) {
6610 /* FIXME FIXME FIXME */
6614 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6615 if (method_index == ca->rows) {
6616 ca = &image->tables [MONO_TABLE_PARAM];
6617 param_last = ca->rows + 1;
6619 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6620 ca = &image->tables [MONO_TABLE_PARAM];
6623 for (i = param_list; i < param_last; ++i) {
6624 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6625 if (param_pos == param) {
6633 idx <<= MONO_CUSTOM_ATTR_BITS;
6634 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6635 return mono_custom_attrs_from_index (image, idx);
6639 * mono_reflection_get_custom_attrs:
6640 * @obj: a reflection object handle
6642 * Return an array with all the custom attributes defined of the
6643 * reflection handle @obj. The objects are fully build.
6646 mono_reflection_get_custom_attrs (MonoObject *obj)
6650 MonoCustomAttrInfo *cinfo = NULL;
6652 MONO_ARCH_SAVE_REGS;
6654 klass = obj->vtable->klass;
6655 /* FIXME: need to handle: Module */
6656 if (klass == mono_defaults.monotype_class) {
6657 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6658 klass = mono_class_from_mono_type (rtype->type);
6659 cinfo = mono_custom_attrs_from_class (klass);
6660 } else if (strcmp ("Assembly", klass->name) == 0) {
6661 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6662 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6663 } else if (strcmp ("Module", klass->name) == 0) {
6664 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6665 cinfo = mono_custom_attrs_from_module (module->image);
6666 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6667 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6668 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6669 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6670 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6671 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6672 } else if (strcmp ("MonoField", klass->name) == 0) {
6673 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6674 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6675 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6676 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6677 cinfo = mono_custom_attrs_from_method (rmethod->method);
6678 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6679 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6680 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6681 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6682 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6683 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6684 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6685 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6686 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6687 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6688 } else { /* handle other types here... */
6689 g_error ("get custom attrs not yet supported for %s", klass->name);
6693 result = mono_custom_attrs_construct (cinfo);
6695 mono_custom_attrs_free (cinfo);
6697 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6698 result = mono_array_new (mono_domain_get (), klass, 0);
6704 static MonoMethodSignature*
6705 parameters_to_signature (MonoArray *parameters) {
6706 MonoMethodSignature *sig;
6709 count = parameters? mono_array_length (parameters): 0;
6711 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6712 sig->param_count = count;
6713 sig->sentinelpos = -1; /* FIXME */
6714 for (i = 0; i < count; ++i) {
6715 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6716 sig->params [i] = pt->type;
6721 static MonoMethodSignature*
6722 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6723 MonoMethodSignature *sig;
6725 sig = parameters_to_signature (ctor->parameters);
6726 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6727 sig->ret = &mono_defaults.void_class->byval_arg;
6731 static MonoMethodSignature*
6732 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6733 MonoMethodSignature *sig;
6735 sig = parameters_to_signature (method->parameters);
6736 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6737 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6738 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6742 static MonoMethodSignature*
6743 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6744 MonoMethodSignature *sig;
6746 sig = parameters_to_signature (method->parameters);
6747 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6748 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6749 sig->generic_param_count = 0;
6754 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6756 MonoClass *klass = mono_object_class (prop);
6757 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6758 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6759 *name = mono_string_to_utf8 (pb->name);
6760 *type = pb->type->type;
6762 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6763 *name = g_strdup (p->property->name);
6764 if (p->property->get)
6765 *type = p->property->get->signature->ret;
6767 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6772 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6774 MonoClass *klass = mono_object_class (field);
6775 if (strcmp (klass->name, "FieldBuilder") == 0) {
6776 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6777 *name = mono_string_to_utf8 (fb->name);
6778 *type = fb->type->type;
6780 MonoReflectionField *f = (MonoReflectionField *)field;
6781 *name = g_strdup (f->field->name);
6782 *type = f->field->type;
6787 * Encode a value in a custom attribute stream of bytes.
6788 * The value to encode is either supplied as an object in argument val
6789 * (valuetypes are boxed), or as a pointer to the data in the
6791 * @type represents the type of the value
6792 * @buffer is the start of the buffer
6793 * @p the current position in the buffer
6794 * @buflen contains the size of the buffer and is used to return the new buffer size
6795 * if this needs to be realloced.
6796 * @retbuffer and @retp return the start and the position of the buffer
6799 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6801 MonoTypeEnum simple_type;
6803 if ((p-buffer) + 10 >= *buflen) {
6806 newbuf = g_realloc (buffer, *buflen);
6807 p = newbuf + (p-buffer);
6811 argval = ((char*)arg + sizeof (MonoObject));
6812 simple_type = type->type;
6814 switch (simple_type) {
6815 case MONO_TYPE_BOOLEAN:
6820 case MONO_TYPE_CHAR:
6823 swap_with_size (p, argval, 2, 1);
6829 swap_with_size (p, argval, 4, 1);
6835 swap_with_size (p, argval, 8, 1);
6838 case MONO_TYPE_VALUETYPE:
6839 if (type->data.klass->enumtype) {
6840 simple_type = type->data.klass->enum_basetype->type;
6843 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6846 case MONO_TYPE_STRING: {
6853 str = mono_string_to_utf8 ((MonoString*)arg);
6854 slen = strlen (str);
6855 if ((p-buffer) + 10 + slen >= *buflen) {
6859 newbuf = g_realloc (buffer, *buflen);
6860 p = newbuf + (p-buffer);
6863 mono_metadata_encode_value (slen, p, &p);
6864 memcpy (p, str, slen);
6869 case MONO_TYPE_CLASS: {
6877 k = mono_object_class (arg);
6878 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6879 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6880 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6882 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6883 slen = strlen (str);
6884 if ((p-buffer) + 10 + slen >= *buflen) {
6888 newbuf = g_realloc (buffer, *buflen);
6889 p = newbuf + (p-buffer);
6892 mono_metadata_encode_value (slen, p, &p);
6893 memcpy (p, str, slen);
6898 case MONO_TYPE_SZARRAY: {
6900 MonoClass *eclass, *arg_eclass;
6903 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6906 len = mono_array_length ((MonoArray*)arg);
6908 *p++ = (len >> 8) & 0xff;
6909 *p++ = (len >> 16) & 0xff;
6910 *p++ = (len >> 24) & 0xff;
6912 *retbuffer = buffer;
6913 eclass = type->data.klass;
6914 arg_eclass = mono_object_class (arg)->element_class;
6915 if (eclass->valuetype && arg_eclass->valuetype) {
6916 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6917 int elsize = mono_class_array_element_size (eclass);
6918 for (i = 0; i < len; ++i) {
6919 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6923 for (i = 0; i < len; ++i) {
6924 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6929 /* it may be a boxed value or a Type */
6930 case MONO_TYPE_OBJECT: {
6931 MonoClass *klass = mono_object_class (arg);
6935 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6938 } else if (klass->enumtype) {
6940 } else if (klass == mono_defaults.string_class) {
6941 simple_type = MONO_TYPE_STRING;
6944 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6945 *p++ = simple_type = klass->byval_arg.type;
6948 g_error ("unhandled type in custom attr");
6950 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
6951 slen = strlen (str);
6952 if ((p-buffer) + 10 + slen >= *buflen) {
6956 newbuf = g_realloc (buffer, *buflen);
6957 p = newbuf + (p-buffer);
6960 mono_metadata_encode_value (slen, p, &p);
6961 memcpy (p, str, slen);
6964 simple_type = klass->enum_basetype->type;
6968 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6971 *retbuffer = buffer;
6975 * mono_reflection_get_custom_attrs_blob:
6976 * @ctor: custom attribute constructor
6977 * @ctorArgs: arguments o the constructor
6983 * Creates the blob of data that needs to be saved in the metadata and that represents
6984 * the custom attributed described by @ctor, @ctorArgs etc.
6985 * Returns: a Byte array representing the blob of data.
6988 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6991 MonoMethodSignature *sig;
6996 MONO_ARCH_SAVE_REGS;
6998 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6999 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7001 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7003 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7005 p = buffer = g_malloc (buflen);
7006 /* write the prolog */
7009 for (i = 0; i < sig->param_count; ++i) {
7010 arg = mono_array_get (ctorArgs, MonoObject*, i);
7011 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7015 i += mono_array_length (properties);
7017 i += mono_array_length (fields);
7019 *p++ = (i >> 8) & 0xff;
7022 for (i = 0; i < mono_array_length (properties); ++i) {
7027 prop = mono_array_get (properties, gpointer, i);
7028 get_prop_name_and_type (prop, &pname, &ptype);
7029 *p++ = 0x54; /* PROPERTY signature */
7031 /* Preallocate a large enough buffer */
7032 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7033 char *str = type_get_qualified_name (ptype, NULL);
7039 len += strlen (pname);
7041 if ((p-buffer) + 20 + len >= buflen) {
7045 newbuf = g_realloc (buffer, buflen);
7046 p = newbuf + (p-buffer);
7050 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7051 char *str = type_get_qualified_name (ptype, NULL);
7052 int slen = strlen (str);
7056 * This seems to be optional...
7059 mono_metadata_encode_value (slen, p, &p);
7060 memcpy (p, str, slen);
7064 mono_metadata_encode_value (ptype->type, p, &p);
7065 if (ptype->type == MONO_TYPE_SZARRAY)
7066 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7068 len = strlen (pname);
7069 mono_metadata_encode_value (len, p, &p);
7070 memcpy (p, pname, len);
7072 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7079 for (i = 0; i < mono_array_length (fields); ++i) {
7084 field = mono_array_get (fields, gpointer, i);
7085 get_field_name_and_type (field, &fname, &ftype);
7086 *p++ = 0x53; /* FIELD signature */
7087 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7088 char *str = type_get_qualified_name (ftype, NULL);
7089 int slen = strlen (str);
7090 if ((p-buffer) + 10 + slen >= buflen) {
7094 newbuf = g_realloc (buffer, buflen);
7095 p = newbuf + (p-buffer);
7100 * This seems to be optional...
7103 mono_metadata_encode_value (slen, p, &p);
7104 memcpy (p, str, slen);
7108 mono_metadata_encode_value (ftype->type, p, &p);
7109 if (ftype->type == MONO_TYPE_SZARRAY)
7110 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7112 len = strlen (fname);
7113 mono_metadata_encode_value (len, p, &p);
7114 memcpy (p, fname, len);
7116 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7121 g_assert (p - buffer <= buflen);
7122 buflen = p - buffer;
7123 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7124 p = mono_array_addr (result, char, 0);
7125 memcpy (p, buffer, buflen);
7127 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7133 * mono_reflection_setup_internal_class:
7134 * @tb: a TypeBuilder object
7136 * Creates a MonoClass that represents the TypeBuilder.
7137 * This is a trick that lets us simplify a lot of reflection code
7138 * (and will allow us to support Build and Run assemblies easier).
7141 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7143 MonoClass *klass, *parent;
7145 MONO_ARCH_SAVE_REGS;
7148 /* check so we can compile corlib correctly */
7149 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7150 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7151 parent = tb->parent->type->data.klass;
7153 parent = my_mono_class_from_mono_type (tb->parent->type);
7157 /* the type has already being created: it means we just have to change the parent */
7158 if (tb->type.type) {
7159 klass = mono_class_from_mono_type (tb->type.type);
7160 klass->parent = NULL;
7161 /* fool mono_class_setup_parent */
7162 g_free (klass->supertypes);
7163 klass->supertypes = NULL;
7164 mono_class_setup_parent (klass, parent);
7165 mono_class_setup_mono_type (klass);
7169 klass = g_new0 (MonoClass, 1);
7171 klass->image = &tb->module->dynamic_image->image;
7173 klass->inited = 1; /* we lie to the runtime */
7174 klass->name = mono_string_to_utf8 (tb->name);
7175 klass->name_space = mono_string_to_utf8 (tb->nspace);
7176 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7177 klass->flags = tb->attrs;
7179 klass->element_class = klass;
7180 klass->reflection_info = tb; /* need to pin. */
7182 /* Put into cache so mono_class_get () will find it */
7183 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
7186 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7187 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
7191 mono_class_setup_parent (klass, parent);
7192 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7193 const char *old_n = klass->name;
7194 /* trick to get relative numbering right when compiling corlib */
7195 klass->name = "BuildingObject";
7196 mono_class_setup_parent (klass, mono_defaults.object_class);
7197 klass->name = old_n;
7199 mono_class_setup_mono_type (klass);
7201 mono_class_setup_supertypes (klass);
7204 * FIXME: handle interfaces.
7207 tb->type.type = &klass->byval_arg;
7209 if (tb->nesting_type) {
7210 g_assert (tb->nesting_type->type);
7211 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7214 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7218 * mono_reflection_setup_generic_class:
7219 * @tb: a TypeBuilder object
7221 * Setup the generic class after all generic parameters have been added.
7224 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7229 MONO_ARCH_SAVE_REGS;
7231 klass = my_mono_class_from_mono_type (tb->type.type);
7233 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7235 if (klass->gen_params || (count == 0))
7238 klass->num_gen_params = count;
7239 klass->gen_params = g_new0 (MonoGenericParam, count);
7241 for (i = 0; i < count; i++) {
7242 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7243 klass->gen_params [i] = *gparam->type.type->data.generic_param;
7248 * mono_reflection_create_internal_class:
7249 * @tb: a TypeBuilder object
7251 * Actually create the MonoClass that is associated with the TypeBuilder.
7254 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7258 MONO_ARCH_SAVE_REGS;
7260 klass = my_mono_class_from_mono_type (tb->type.type);
7262 if (klass->enumtype && klass->enum_basetype == NULL) {
7263 MonoReflectionFieldBuilder *fb;
7265 g_assert (tb->fields != NULL);
7266 g_assert (mono_array_length (tb->fields) >= 1);
7268 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7270 klass->enum_basetype = fb->type->type;
7271 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7272 if (!klass->element_class)
7273 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7274 klass->instance_size = klass->element_class->instance_size;
7275 klass->size_inited = 1;
7277 * this is almost safe to do with enums and it's needed to be able
7278 * to create objects of the enum type (for use in SetConstant).
7280 /* FIXME: Does this mean enums can't have method overrides ? */
7281 mono_class_setup_vtable (klass, NULL, 0);
7285 static MonoMarshalSpec*
7286 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7287 MonoReflectionMarshal *minfo)
7289 MonoMarshalSpec *res;
7291 res = g_new0 (MonoMarshalSpec, 1);
7292 res->native = minfo->type;
7294 switch (minfo->type) {
7295 case MONO_NATIVE_LPARRAY:
7296 res->data.array_data.elem_type = minfo->eltype;
7297 res->data.array_data.param_num = 0; /* Not yet */
7298 res->data.array_data.num_elem = minfo->count;
7301 case MONO_NATIVE_BYVALTSTR:
7302 case MONO_NATIVE_BYVALARRAY:
7303 res->data.array_data.num_elem = minfo->count;
7306 case MONO_NATIVE_CUSTOM:
7307 if (minfo->marshaltyperef)
7308 res->data.custom_data.custom_name =
7309 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7311 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7322 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7323 ReflectionMethodBuilder *rmb,
7324 MonoMethodSignature *sig)
7327 MonoMethodNormal *pm;
7328 MonoMarshalSpec **specs;
7329 MonoReflectionMethodAux *method_aux;
7332 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7333 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7334 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7337 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7339 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7341 pm = (MonoMethodNormal*)m;
7344 m->flags = rmb->attrs;
7345 m->iflags = rmb->iattrs;
7346 m->name = mono_string_to_utf8 (rmb->name);
7350 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7352 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7353 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7356 m->signature->pinvoke = 1;
7357 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7358 m->signature->pinvoke = 1;
7360 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7362 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7363 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7365 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7367 if (klass->image->dynamic)
7368 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7371 } else if (!m->klass->dummy &&
7372 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7373 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7374 MonoMethodHeader *header;
7376 gint32 max_stack, i;
7377 gint32 num_locals = 0;
7378 gint32 num_clauses = 0;
7382 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7383 code_size = rmb->ilgen->code_len;
7384 max_stack = rmb->ilgen->max_stack;
7385 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7386 if (rmb->ilgen->ex_handlers)
7387 num_clauses = method_count_clauses (rmb->ilgen);
7390 code = mono_array_addr (rmb->code, guint8, 0);
7391 code_size = mono_array_length (rmb->code);
7392 /* we probably need to run a verifier on the code... */
7402 header = g_malloc0 (sizeof (MonoMethodHeader) +
7403 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7404 header->code_size = code_size;
7405 header->code = g_malloc (code_size);
7406 memcpy ((char*)header->code, code, code_size);
7407 header->max_stack = max_stack;
7408 header->init_locals = rmb->init_locals;
7409 header->num_locals = num_locals;
7411 for (i = 0; i < num_locals; ++i) {
7412 MonoReflectionLocalBuilder *lb =
7413 mono_array_get (rmb->ilgen->locals,
7414 MonoReflectionLocalBuilder*, i);
7416 header->locals [i] = g_new0 (MonoType, 1);
7417 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7420 header->num_clauses = num_clauses;
7422 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7427 pm->header = header;
7430 if (rmb->generic_params) {
7431 int count = mono_array_length (rmb->generic_params);
7432 pm->gen_params = g_new0 (MonoGenericParam, count);
7433 for (i = 0; i < count; i++) {
7434 MonoReflectionGenericParam *gp =
7435 mono_array_get (rmb->generic_params,
7436 MonoReflectionGenericParam*, i);
7438 pm->gen_params [i] = *gp->type.type->data.generic_param;
7443 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7446 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7448 for (i = 0; i < rmb->nrefs; ++i)
7449 mw->data = g_list_append (mw->data, rmb->refs [i]);
7454 /* Parameter names */
7457 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7458 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7459 for (i = 0; i <= m->signature->param_count; ++i) {
7460 MonoReflectionParamBuilder *pb;
7461 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7463 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7465 if (!method_aux->param_cattr)
7466 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7467 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7473 /* Parameter marshalling */
7476 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7477 MonoReflectionParamBuilder *pb;
7478 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7479 if (pb->marshal_info) {
7481 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7482 specs [pb->position] =
7483 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7487 if (specs != NULL) {
7489 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7490 method_aux->param_marshall = specs;
7493 if (klass->image->dynamic && method_aux)
7494 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7500 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7502 ReflectionMethodBuilder rmb;
7503 MonoMethodSignature *sig;
7505 sig = ctor_builder_to_signature (mb);
7507 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7509 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7510 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7512 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7513 /* ilgen is no longer needed */
7521 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7523 ReflectionMethodBuilder rmb;
7524 MonoMethodSignature *sig;
7526 sig = method_builder_to_signature (mb);
7528 reflection_methodbuilder_from_method_builder (&rmb, mb);
7530 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7531 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7533 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7534 /* ilgen is no longer needed */
7540 static MonoClassField*
7541 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7543 MonoClassField *field;
7550 field = g_new0 (MonoClassField, 1);
7552 field->name = mono_string_to_utf8 (fb->name);
7554 /* FIXME: handle type modifiers */
7555 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7556 field->type->attrs = fb->attrs;
7558 field->type = fb->type->type;
7560 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7561 field->data = mono_array_addr (fb->rva_data, char, 0);
7562 if (fb->offset != -1)
7563 field->offset = fb->offset;
7564 field->parent = klass;
7566 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7568 if (fb->def_value) {
7569 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7570 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7571 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7572 /* Copy the data from the blob since it might get realloc-ed */
7573 p = assembly->blob.data + idx;
7574 len = mono_metadata_decode_blob_size (p, &p2);
7576 field->data = g_malloc (len);
7577 memcpy ((gpointer)field->data, p, len);
7584 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7588 MonoReflectionTypeBuilder *tb = NULL;
7589 MonoGenericInst *ginst, *cached;
7594 klass = mono_class_from_mono_type (type->type);
7595 if (!klass->gen_params && !klass->generic_inst &&
7596 !(klass->nested_in && klass->nested_in->gen_params))
7599 mono_loader_lock ();
7601 domain = mono_object_domain (type);
7603 ginst = g_new0 (MonoGenericInst, 1);
7605 if (!klass->generic_inst) {
7606 ginst->type_argc = type_argc;
7607 ginst->type_argv = types;
7609 for (i = 0; i < ginst->type_argc; ++i) {
7610 if (!ginst->is_open)
7611 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7614 ginst->generic_type = &klass->byval_arg;
7616 MonoGenericInst *kginst = klass->generic_inst;
7618 ginst->type_argc = kginst->type_argc;
7619 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7621 for (i = 0; i < ginst->type_argc; i++) {
7622 MonoType *t = kginst->type_argv [i];
7624 if (t->type == MONO_TYPE_VAR)
7625 t = types [t->data.generic_param->num];
7627 if (!ginst->is_open)
7628 ginst->is_open = mono_class_is_open_constructed_type (t);
7630 ginst->type_argv [i] = t;
7633 ginst->generic_type = kginst->generic_type;
7636 geninst = g_new0 (MonoType, 1);
7637 geninst->type = MONO_TYPE_GENERICINST;
7639 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7642 mono_loader_unlock ();
7643 geninst->data.generic_inst = cached;
7647 geninst->data.generic_inst = ginst;
7649 ginst->context = g_new0 (MonoGenericContext, 1);
7650 ginst->context->ginst = ginst;
7652 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7653 tb = (MonoReflectionTypeBuilder *) type;
7655 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7656 ginst->is_dynamic = TRUE;
7657 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7658 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7659 MonoReflectionType *rgt = rgi->generic_type;
7661 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7662 tb = (MonoReflectionTypeBuilder *) rgt;
7664 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7665 ginst->is_dynamic = TRUE;
7667 icount = klass->interface_count;
7669 ginst->ifaces = g_new0 (MonoType *, icount);
7670 ginst->count_ifaces = icount;
7672 for (i = 0; i < icount; i++) {
7673 MonoReflectionType *itype;
7676 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7678 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7679 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7680 if (!ginst->ifaces [i])
7681 ginst->ifaces [i] = itype->type;
7684 mono_class_create_generic (ginst);
7686 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7688 mono_loader_unlock ();
7694 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7696 MonoClass *klass, *pklass = NULL;
7697 MonoReflectionType *parent = NULL;
7699 MonoReflectionTypeBuilder *tb = NULL;
7700 MonoGenericInst *ginst;
7703 domain = mono_object_domain (type);
7704 klass = mono_class_from_mono_type (type->type);
7706 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7707 tb = (MonoReflectionTypeBuilder *) type;
7710 parent = tb->parent;
7711 pklass = mono_class_from_mono_type (parent->type);
7714 pklass = klass->parent;
7716 parent = mono_type_get_object (domain, &pklass->byval_arg);
7719 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7723 ginst = geninst->data.generic_inst;
7725 if (pklass && pklass->generic_inst)
7726 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7731 MonoReflectionMethod*
7732 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7734 MonoMethod *method, *inflated;
7735 MonoReflectionMethodBuilder *mb = NULL;
7736 MonoGenericMethod *gmethod;
7737 MonoGenericContext *context;
7740 MONO_ARCH_SAVE_REGS;
7741 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7742 MonoReflectionTypeBuilder *tb;
7745 mb = (MonoReflectionMethodBuilder *) rmethod;
7746 tb = (MonoReflectionTypeBuilder *) mb->type;
7747 klass = mono_class_from_mono_type (tb->type.type);
7749 method = methodbuilder_to_mono_method (klass, mb);
7751 method = rmethod->method;
7753 count = method->signature->generic_param_count;
7754 if (count != mono_array_length (types))
7757 gmethod = g_new0 (MonoGenericMethod, 1);
7758 gmethod->mtype_argc = count;
7759 gmethod->mtype_argv = g_new0 (MonoType *, count);
7760 for (i = 0; i < count; i++) {
7761 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7762 gmethod->mtype_argv [i] = garg->type;
7765 gmethod->reflection_info = rmethod;
7767 context = g_new0 (MonoGenericContext, 1);
7768 context->ginst = method->klass->generic_inst;
7769 context->gmethod = gmethod;
7771 inflated = mono_class_inflate_generic_method (method, context, NULL);
7773 return mono_method_get_object (
7774 mono_object_domain (rmethod), inflated, NULL);
7778 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7780 MonoGenericMethod *gmethod;
7781 MonoGenericInst *ginst;
7782 MonoGenericContext *context;
7785 ginst = type->type.type->data.generic_inst;
7787 gmethod = g_new0 (MonoGenericMethod, 1);
7788 gmethod->reflection_info = obj;
7790 gmethod->mtype_argc = method->signature->generic_param_count;
7791 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7793 for (i = 0; i < gmethod->mtype_argc; i++) {
7794 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7795 MonoGenericParam *gparam = &mn->gen_params [i];
7797 g_assert (gparam->pklass);
7798 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7801 context = g_new0 (MonoGenericContext, 1);
7802 context->ginst = ginst;
7803 context->gmethod = gmethod;
7805 return mono_class_inflate_generic_method (method, context, ginst->klass);
7809 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7814 klass = mono_class_from_mono_type (type->type.type);
7816 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7817 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7818 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7819 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7820 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7821 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7822 method = ((MonoReflectionMethod *) obj)->method;
7824 method = NULL; /* prevent compiler warning */
7825 g_assert_not_reached ();
7828 return inflate_mono_method (type, method, obj);
7832 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7833 MonoArray *methods, MonoArray *ctors,
7834 MonoArray *fields, MonoArray *properties,
7837 MonoGenericInst *ginst;
7838 MonoDynamicGenericInst *dginst;
7839 MonoClass *klass, *gklass, *pklass;
7842 MONO_ARCH_SAVE_REGS;
7844 klass = mono_class_from_mono_type (type->type.type);
7845 ginst = type->type.type->data.generic_inst;
7847 if (ginst->initialized)
7850 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7852 gklass = mono_class_from_mono_type (ginst->generic_type);
7853 mono_class_init (gklass);
7856 pklass = mono_class_from_mono_type (ginst->parent);
7858 pklass = gklass->parent;
7860 mono_class_setup_parent (klass, pklass);
7862 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7863 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7864 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7865 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7866 dginst->count_events = events ? mono_array_length (events) : 0;
7868 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7869 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7870 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7871 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7872 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7874 for (i = 0; i < dginst->count_methods; i++) {
7875 MonoObject *obj = mono_array_get (methods, gpointer, i);
7877 dginst->methods [i] = inflate_method (type, obj);
7880 for (i = 0; i < dginst->count_ctors; i++) {
7881 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7883 dginst->ctors [i] = inflate_method (type, obj);
7886 for (i = 0; i < dginst->count_fields; i++) {
7887 MonoObject *obj = mono_array_get (fields, gpointer, i);
7888 MonoClassField *field;
7889 MonoInflatedField *ifield;
7891 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7892 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7893 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7894 field = ((MonoReflectionField *) obj)->field;
7896 field = NULL; /* prevent compiler warning */
7897 g_assert_not_reached ();
7900 ifield = g_new0 (MonoInflatedField, 1);
7901 ifield->generic_type = field->type;
7902 ifield->reflection_info = obj;
7904 dginst->fields [i] = *field;
7905 dginst->fields [i].generic_info = ifield;
7906 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7909 for (i = 0; i < dginst->count_properties; i++) {
7910 MonoObject *obj = mono_array_get (properties, gpointer, i);
7911 MonoProperty *property = &dginst->properties [i];
7913 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7914 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7916 property->parent = klass;
7917 property->attrs = pb->attrs;
7918 property->name = mono_string_to_utf8 (pb->name);
7920 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7922 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7923 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7924 *property = *((MonoReflectionProperty *) obj)->property;
7927 property->get = inflate_mono_method (type, property->get, NULL);
7929 property->set = inflate_mono_method (type, property->set, NULL);
7931 g_assert_not_reached ();
7934 for (i = 0; i < dginst->count_events; i++) {
7935 MonoObject *obj = mono_array_get (events, gpointer, i);
7936 MonoEvent *event = &dginst->events [i];
7938 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7939 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7941 event->parent = klass;
7942 event->attrs = eb->attrs;
7943 event->name = mono_string_to_utf8 (eb->name);
7945 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7946 if (eb->remove_method)
7947 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7948 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7949 *event = *((MonoReflectionEvent *) obj)->event;
7952 event->add = inflate_mono_method (type, event->add, NULL);
7954 event->remove = inflate_mono_method (type, event->remove, NULL);
7956 g_assert_not_reached ();
7959 ginst->initialized = TRUE;
7963 ensure_runtime_vtable (MonoClass *klass)
7965 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7966 int i, num, j, onum;
7967 MonoMethod **overrides;
7969 if (!tb || klass->wastypebuilder)
7972 ensure_runtime_vtable (klass->parent);
7974 num = tb->ctors? mono_array_length (tb->ctors): 0;
7975 num += tb->num_methods;
7976 klass->method.count = num;
7977 klass->methods = g_new (MonoMethod*, num);
7978 num = tb->ctors? mono_array_length (tb->ctors): 0;
7979 for (i = 0; i < num; ++i)
7980 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7981 num = tb->num_methods;
7983 for (i = 0; i < num; ++i)
7984 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7986 klass->wastypebuilder = TRUE;
7987 if (tb->interfaces) {
7988 klass->interface_count = mono_array_length (tb->interfaces);
7989 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7990 for (i = 0; i < klass->interface_count; ++i) {
7991 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7992 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7996 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7997 for (i = 0; i < klass->method.count; ++i)
7998 klass->methods [i]->slot = i;
8003 for (i = 0; i < tb->num_methods; ++i) {
8004 MonoReflectionMethodBuilder *mb =
8005 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8006 if (mb->override_method)
8011 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
8015 for (i = 0; i < tb->num_methods; ++i) {
8016 MonoReflectionMethodBuilder *mb =
8017 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8018 if (mb->override_method) {
8019 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8020 overrides [onum * 2] =
8021 mb->override_method->method;
8022 overrides [onum * 2 + 1] =
8025 g_assert (mb->mhandle);
8032 mono_class_setup_vtable (klass, overrides, onum);
8036 typebuilder_setup_fields (MonoClass *klass)
8038 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8039 MonoReflectionFieldBuilder *fb;
8040 MonoClassField *field;
8045 klass->field.count = tb->num_fields;
8046 klass->field.first = 0;
8047 klass->field.last = klass->field.count;
8049 if (!klass->field.count)
8052 klass->fields = g_new0 (MonoClassField, klass->field.count);
8054 for (i = 0; i < klass->field.count; ++i) {
8055 fb = mono_array_get (tb->fields, gpointer, i);
8056 field = &klass->fields [i];
8057 field->name = mono_string_to_utf8 (fb->name);
8059 /* FIXME: handle type modifiers */
8060 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8061 field->type->attrs = fb->attrs;
8063 field->type = fb->type->type;
8065 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8066 field->data = mono_array_addr (fb->rva_data, char, 0);
8067 if (fb->offset != -1)
8068 field->offset = fb->offset;
8069 field->parent = klass;
8071 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8073 if (fb->def_value) {
8074 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8075 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8076 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8077 /* Copy the data from the blob since it might get realloc-ed */
8078 p = assembly->blob.data + idx;
8079 len = mono_metadata_decode_blob_size (p, &p2);
8081 field->data = g_malloc (len);
8082 memcpy ((gpointer)field->data, p, len);
8085 mono_class_layout_fields (klass);
8089 typebuilder_setup_properties (MonoClass *klass)
8091 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8092 MonoReflectionPropertyBuilder *pb;
8095 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8096 klass->property.first = 0;
8097 klass->property.last = klass->property.count;
8099 klass->properties = g_new0 (MonoProperty, klass->property.count);
8100 for (i = 0; i < klass->property.count; ++i) {
8101 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8102 klass->properties [i].parent = klass;
8103 klass->properties [i].attrs = pb->attrs;
8104 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8106 klass->properties [i].get = pb->get_method->mhandle;
8108 klass->properties [i].set = pb->set_method->mhandle;
8112 MonoReflectionEvent *
8113 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8115 MonoEvent *event = g_new0 (MonoEvent, 1);
8119 klass = my_mono_class_from_mono_type (tb->type.type);
8121 event->parent = klass;
8122 event->attrs = eb->attrs;
8123 event->name = mono_string_to_utf8 (eb->name);
8125 event->add = eb->add_method->mhandle;
8126 if (eb->remove_method)
8127 event->remove = eb->remove_method->mhandle;
8128 if (eb->raise_method)
8129 event->raise = eb->raise_method->mhandle;
8131 if (eb->other_methods) {
8132 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
8133 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8134 MonoReflectionMethodBuilder *mb =
8135 mono_array_get (eb->other_methods,
8136 MonoReflectionMethodBuilder*, j);
8137 event->other [j] = mb->mhandle;
8141 return mono_event_get_object (mono_object_domain (tb), klass, event);
8145 typebuilder_setup_events (MonoClass *klass)
8147 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8148 MonoReflectionEventBuilder *eb;
8151 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8152 klass->event.first = 0;
8153 klass->event.last = klass->event.count;
8155 klass->events = g_new0 (MonoEvent, klass->event.count);
8156 for (i = 0; i < klass->event.count; ++i) {
8157 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8158 klass->events [i].parent = klass;
8159 klass->events [i].attrs = eb->attrs;
8160 klass->events [i].name = mono_string_to_utf8 (eb->name);
8162 klass->events [i].add = eb->add_method->mhandle;
8163 if (eb->remove_method)
8164 klass->events [i].remove = eb->remove_method->mhandle;
8165 if (eb->raise_method)
8166 klass->events [i].raise = eb->raise_method->mhandle;
8168 if (eb->other_methods) {
8169 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
8170 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8171 MonoReflectionMethodBuilder *mb =
8172 mono_array_get (eb->other_methods,
8173 MonoReflectionMethodBuilder*, j);
8174 klass->events [i].other [j] = mb->mhandle;
8181 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8184 MonoReflectionType* res;
8187 MONO_ARCH_SAVE_REGS;
8189 klass = my_mono_class_from_mono_type (tb->type.type);
8191 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8194 * Fields to set in klass:
8195 * the various flags: delegate/unicode/contextbound etc.
8197 klass->flags = tb->attrs;
8199 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8200 /* No need to fully construct the type */
8201 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8203 /* enums are done right away */
8204 if (!klass->enumtype)
8205 ensure_runtime_vtable (klass);
8208 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8209 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8210 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8214 /* fields and object layout */
8215 if (klass->parent) {
8216 if (!klass->parent->size_inited)
8217 mono_class_init (klass->parent);
8218 klass->instance_size += klass->parent->instance_size;
8219 klass->class_size += klass->parent->class_size;
8220 klass->min_align = klass->parent->min_align;
8222 klass->instance_size = sizeof (MonoObject);
8223 klass->min_align = 1;
8226 /* FIXME: handle packing_size and instance_size */
8227 typebuilder_setup_fields (klass);
8229 typebuilder_setup_properties (klass);
8231 typebuilder_setup_events (klass);
8233 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8234 /* with enums res == tb: need to fix that. */
8235 if (!klass->enumtype)
8236 g_assert (res != (MonoReflectionType*)tb);
8241 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8243 MonoGenericParam *param;
8246 MONO_ARCH_SAVE_REGS;
8248 param = g_new0 (MonoGenericParam, 1);
8250 param->method = NULL;
8251 param->name = mono_string_to_utf8 (gparam->name);
8252 param->num = gparam->index;
8254 image = &gparam->tbuilder->module->dynamic_image->image;
8255 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8257 param->pklass->reflection_info = gparam;
8259 gparam->type.type = g_new0 (MonoType, 1);
8260 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8261 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8262 gparam->type.type->data.generic_param = param;
8266 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8268 MonoDynamicImage *assembly = sig->module->dynamic_image;
8269 guint32 na = mono_array_length (sig->arguments);
8274 MONO_ARCH_SAVE_REGS;
8276 p = buf = g_malloc (10 + na * 10);
8278 mono_metadata_encode_value (0x07, p, &p);
8279 mono_metadata_encode_value (na, p, &p);
8280 for (i = 0; i < na; ++i) {
8281 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8282 encode_reflection_type (assembly, type, p, &p);
8286 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8287 p = mono_array_addr (result, char, 0);
8288 memcpy (p, buf, buflen);
8295 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8297 MonoDynamicImage *assembly = sig->module->dynamic_image;
8298 guint32 na = mono_array_length (sig->arguments);
8303 MONO_ARCH_SAVE_REGS;
8305 p = buf = g_malloc (10 + na * 10);
8307 mono_metadata_encode_value (0x06, p, &p);
8308 for (i = 0; i < na; ++i) {
8309 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8310 encode_reflection_type (assembly, type, p, &p);
8314 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8315 p = mono_array_addr (result, char, 0);
8316 memcpy (p, buf, buflen);
8323 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8325 ReflectionMethodBuilder rmb;
8326 MonoMethodSignature *sig;
8329 sig = dynamic_method_to_signature (mb);
8331 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8334 * Resolve references.
8336 rmb.nrefs = mb->nrefs;
8337 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8338 for (i = 0; i < mb->nrefs; ++i) {
8339 gpointer ref = resolve_object (mb->module->image,
8340 mono_array_get (mb->refs, MonoObject*, i));
8343 mono_raise_exception (mono_get_exception_type_load (NULL));
8350 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8354 /* ilgen is no longer needed */
8359 * mono_reflection_lookup_dynamic_token:
8361 * Finish the Builder object pointed to by TOKEN and return the corresponding
8362 * runtime structure.
8365 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8367 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8370 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8373 return resolve_object (image, obj);
8377 resolve_object (MonoImage *image, MonoObject *obj)
8379 gpointer result = NULL;
8381 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8382 result = mono_string_intern ((MonoString*)obj);
8385 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8386 MonoReflectionType *tb = (MonoReflectionType*)obj;
8387 result = mono_class_from_mono_type (tb->type);
8390 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8391 result = ((MonoReflectionMethod*)obj)->method;
8394 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8395 result = ((MonoReflectionMethod*)obj)->method;
8398 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8399 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8400 result = mb->mhandle;
8402 /* Type is not yet created */
8403 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8405 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8408 * Hopefully this has been filled in by calling CreateType() on the
8412 * TODO: This won't work if the application finishes another
8413 * TypeBuilder instance instead of this one.
8415 result = mb->mhandle;
8418 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8419 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8421 result = cb->mhandle;
8423 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8425 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8426 result = cb->mhandle;
8429 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8430 result = ((MonoReflectionField*)obj)->field;
8433 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8434 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8435 result = fb->handle;
8438 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8440 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8441 result = fb->handle;
8444 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8445 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8448 klass = tb->type.type->data.klass;
8449 if (klass->wastypebuilder) {
8450 /* Already created */
8454 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8455 result = tb->type.type->data.klass;
8459 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8460 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8461 MonoMethodSignature *sig;
8464 if (helper->arguments)
8465 nargs = mono_array_length (helper->arguments);
8469 sig = mono_metadata_signature_alloc (image, nargs);
8470 sig->explicit_this = helper->call_conv & 64;
8471 sig->hasthis = helper->call_conv & 32;
8473 if (helper->call_conv == 0) /* unmanaged */
8474 sig->call_convention = helper->unmanaged_call_conv - 1;
8476 if (helper->call_conv & 0x02)
8477 sig->call_convention = MONO_CALL_VARARG;
8479 sig->call_convention = MONO_CALL_DEFAULT;
8481 sig->param_count = nargs;
8482 /* TODO: Copy type ? */
8483 sig->ret = helper->return_type->type;
8484 for (i = 0; i < nargs; ++i) {
8485 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8486 sig->params [i] = rt->type;
8492 g_print (obj->vtable->klass->name);
8493 g_assert_not_reached ();