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/tokentype.h"
15 #include "mono/metadata/appdomain.h"
16 #include "mono/metadata/opcodes.h"
17 #include "mono/metadata/assembly.h"
18 #include <mono/metadata/exception.h>
27 #include "rawbuffer.h"
28 #include "mono-endian.h"
30 #include <mono/os/gc_wrapper.h>
32 #define TEXT_OFFSET 512
33 #define CLI_H_SIZE 136
34 #define FILE_ALIGN 512
35 #define VIRT_ALIGN 8192
36 #define START_TEXT_RVA 0x00002000
39 MonoReflectionILGen *ilgen;
40 MonoReflectionType *rtype;
41 MonoArray *parameters;
42 MonoArray *generic_params;
48 guint32 *table_idx; /* note: it's a pointer */
52 MonoBoolean init_locals;
53 MonoArray *return_modreq;
54 MonoArray *return_modopt;
55 MonoArray *param_modreq;
56 MonoArray *param_modopt;
57 MonoArray *permissions;
61 } ReflectionMethodBuilder;
63 const unsigned char table_sizes [64] = {
73 MONO_INTERFACEIMPL_SIZE,
74 MONO_MEMBERREF_SIZE, /* 0x0A */
76 MONO_CUSTOM_ATTR_SIZE,
77 MONO_FIELD_MARSHAL_SIZE,
78 MONO_DECL_SECURITY_SIZE,
79 MONO_CLASS_LAYOUT_SIZE,
80 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
81 MONO_STAND_ALONE_SIGNATURE_SIZE,
85 MONO_PROPERTY_MAP_SIZE,
88 MONO_METHOD_SEMA_SIZE,
90 MONO_MODULEREF_SIZE, /* 0x1A */
96 MONO_ASSEMBLY_SIZE, /* 0x20 */
97 MONO_ASSEMBLY_PROCESSOR_SIZE,
99 MONO_ASSEMBLYREF_SIZE,
100 MONO_ASSEMBLYREFPROC_SIZE,
101 MONO_ASSEMBLYREFOS_SIZE,
105 MONO_NESTED_CLASS_SIZE,
107 MONO_GENERICPARAM_SIZE, /* 0x2A */
108 MONO_METHODSPEC_SIZE,
109 MONO_GENPARCONSTRAINT_SIZE,
115 * These macros can be used to allocate long living atomic data so it won't be
116 * tracked by the garbage collector. We use libgc because it's apparently faster
120 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
121 #define FREE_ATOMIC(ptr)
122 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
124 #define ALLOC_ATOMIC(size) g_malloc (size)
125 #define FREE_ATOMIC(ptr) g_free (ptr)
126 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
129 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
130 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
131 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
132 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
133 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
134 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
135 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
136 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
137 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
138 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
139 static void ensure_runtime_vtable (MonoClass *klass);
140 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
141 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
142 static guint32 type_get_signature_size (MonoType *type);
146 alloc_table (MonoDynamicTable *table, guint nrows)
149 g_assert (table->columns);
150 if (nrows + 1 >= table->alloc_rows) {
151 while (nrows + 1 >= table->alloc_rows)
152 if (table->alloc_rows == 0)
153 table->alloc_rows = 16;
155 table->alloc_rows *= 2;
158 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
160 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
165 make_room_in_stream (MonoDynamicStream *stream, int size)
167 while (stream->alloc_size <= size) {
168 if (stream->alloc_size < 4096)
169 stream->alloc_size = 4096;
171 stream->alloc_size *= 2;
174 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
176 stream->data = ALLOC_ATOMIC (stream->alloc_size);
180 string_heap_insert (MonoDynamicStream *sh, const char *str)
184 gpointer oldkey, oldval;
186 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
187 return GPOINTER_TO_UINT (oldval);
189 len = strlen (str) + 1;
191 if (idx + len > sh->alloc_size)
192 make_room_in_stream (sh, idx + len);
195 * We strdup the string even if we already copy them in sh->data
196 * so that the string pointers in the hash remain valid even if
197 * we need to realloc sh->data. We may want to avoid that later.
199 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
200 memcpy (sh->data + idx, str, len);
206 string_heap_init (MonoDynamicStream *sh)
209 sh->alloc_size = 4096;
210 sh->data = ALLOC_ATOMIC (4096);
211 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
212 string_heap_insert (sh, "");
215 #if 0 /* never used */
217 string_heap_free (MonoDynamicStream *sh)
219 FREE_ATOMIC (sh->data);
220 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
221 g_hash_table_destroy (sh->hash);
226 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
229 if (stream->alloc_size < stream->index + len)
230 make_room_in_stream (stream, stream->index + len);
231 memcpy (stream->data + stream->index, data, len);
233 stream->index += len;
235 * align index? Not without adding an additional param that controls it since
236 * we may store a blob value in pieces.
242 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
245 if (stream->alloc_size < stream->index + len)
246 make_room_in_stream (stream, stream->index + len);
247 memset (stream->data + stream->index, 0, len);
249 stream->index += len;
254 stream_data_align (MonoDynamicStream *stream)
257 guint32 count = stream->index % 4;
259 /* we assume the stream data will be aligned */
261 mono_image_add_stream_data (stream, buf, 4 - count);
265 mono_blob_entry_hash (const char* str)
269 len = mono_metadata_decode_blob_size (str, &str);
273 for (str += 1; str < end; str++)
274 h = (h << 5) - h + *str;
282 mono_blob_entry_equal (const char *str1, const char *str2) {
286 len = mono_metadata_decode_blob_size (str1, &end1);
287 len2 = mono_metadata_decode_blob_size (str2, &end2);
290 return memcmp (end1, end2, len) == 0;
294 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
298 gpointer oldkey, oldval;
300 copy = ALLOC_ATOMIC (s1+s2);
301 memcpy (copy, b1, s1);
302 memcpy (copy + s1, b2, s2);
303 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
305 idx = GPOINTER_TO_UINT (oldval);
307 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
308 mono_image_add_stream_data (&assembly->blob, b2, s2);
309 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
315 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
316 * dest may be misaligned.
319 swap_with_size (char *dest, const char* val, int len, int nelem) {
320 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
323 for (elem = 0; elem < nelem; ++elem) {
349 g_assert_not_reached ();
355 memcpy (dest, val, len * nelem);
360 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
364 guint32 idx = 0, len;
366 len = str->length * 2;
367 mono_metadata_encode_value (len, b, &b);
368 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
370 char *swapped = g_malloc (2 * mono_string_length (str));
371 const char *p = (const char*)mono_string_chars (str);
373 swap_with_size (swapped, p, 2, mono_string_length (str));
374 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
378 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
383 /* modified version needed to handle building corlib */
385 my_mono_class_from_mono_type (MonoType *type) {
386 switch (type->type) {
387 case MONO_TYPE_ARRAY:
389 case MONO_TYPE_SZARRAY:
390 case MONO_TYPE_GENERICINST:
391 return mono_class_from_mono_type (type);
394 g_assert (type->data.generic_param->pklass);
395 return type->data.generic_param->pklass;
397 /* should be always valid when we reach this case... */
398 return type->data.klass;
403 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
408 g_assert_not_reached ();
412 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
413 encode_type (assembly, ginst->generic_type, p, &p);
414 mono_metadata_encode_value (ginst->type_argc, p, &p);
415 for (i = 0; i < ginst->type_argc; ++i)
416 encode_type (assembly, ginst->type_argv [i], p, &p);
422 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
425 g_assert_not_reached ();
430 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
434 case MONO_TYPE_BOOLEAN:
448 case MONO_TYPE_STRING:
449 case MONO_TYPE_OBJECT:
450 case MONO_TYPE_TYPEDBYREF:
451 mono_metadata_encode_value (type->type, p, &p);
454 mono_metadata_encode_value (type->type, p, &p);
455 encode_type (assembly, type->data.type, p, &p);
457 case MONO_TYPE_SZARRAY:
458 mono_metadata_encode_value (type->type, p, &p);
459 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
462 case MONO_TYPE_VALUETYPE:
463 case MONO_TYPE_CLASS: {
464 MonoClass *k = mono_class_from_mono_type (type);
465 mono_metadata_encode_value (type->type, p, &p);
467 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
468 * otherwise two typerefs could point to the same type, leading to
469 * verification errors.
471 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
475 case MONO_TYPE_ARRAY:
476 mono_metadata_encode_value (type->type, p, &p);
477 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
478 mono_metadata_encode_value (type->data.array->rank, p, &p);
479 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
480 mono_metadata_encode_value (0, p, &p);
482 case MONO_TYPE_GENERICINST:
483 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
487 mono_metadata_encode_value (type->type, p, &p);
488 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
492 g_error ("need to encode type %x", type->type);
498 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
501 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
505 encode_type (assembly, type->type, p, endbuf);
509 g_assert_not_reached ();
514 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
519 for (i = 0; i < mono_array_length (modreq); ++i) {
520 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
521 *p = MONO_TYPE_CMOD_REQD;
523 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
527 for (i = 0; i < mono_array_length (modopt); ++i) {
528 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
529 *p = MONO_TYPE_CMOD_OPT;
531 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
538 generic_inst_get_signature_size (MonoGenericInst *ginst)
544 g_assert_not_reached ();
547 size += 1 + type_get_signature_size (ginst->generic_type);
549 for (i = 0; i < ginst->type_argc; ++i)
550 size += type_get_signature_size (ginst->type_argv [i]);
556 type_get_signature_size (MonoType *type)
561 g_assert_not_reached ();
569 case MONO_TYPE_BOOLEAN:
583 case MONO_TYPE_STRING:
584 case MONO_TYPE_OBJECT:
585 case MONO_TYPE_TYPEDBYREF:
588 return size + 1 + type_get_signature_size (type->data.type);
589 case MONO_TYPE_SZARRAY:
590 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
592 case MONO_TYPE_VALUETYPE:
593 case MONO_TYPE_CLASS:
596 case MONO_TYPE_ARRAY:
597 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
598 case MONO_TYPE_GENERICINST:
599 return size + generic_inst_get_signature_size (type->data.generic_inst);
605 g_error ("need to encode type %x", type->type);
611 method_get_signature_size (MonoMethodSignature *sig)
616 size = type_get_signature_size (sig->ret);
617 for (i = 0; i < sig->param_count; i++)
618 size += type_get_signature_size (sig->params [i]);
620 if (sig->generic_param_count)
622 if (sig->sentinelpos >= 0)
629 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
634 guint32 nparams = sig->param_count;
635 guint32 size = 11 + method_get_signature_size (sig);
643 p = buf = g_malloc (size);
645 * FIXME: vararg, explicit_this, differenc call_conv values...
647 *p = sig->call_convention;
649 *p |= 0x20; /* hasthis */
650 if (sig->generic_param_count)
651 *p |= 0x10; /* generic */
653 if (sig->generic_param_count)
654 mono_metadata_encode_value (sig->generic_param_count, p, &p);
655 mono_metadata_encode_value (nparams, p, &p);
656 encode_type (assembly, sig->ret, p, &p);
657 for (i = 0; i < nparams; ++i) {
658 if (i == sig->sentinelpos)
659 *p++ = MONO_TYPE_SENTINEL;
660 encode_type (assembly, sig->params [i], p, &p);
663 g_assert (p - buf < size);
664 mono_metadata_encode_value (p-buf, b, &b);
665 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
671 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
674 * FIXME: reuse code from method_encode_signature().
679 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
680 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
681 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
682 guint32 size = 21 + nparams * 20 + notypes * 20;
687 p = buf = g_malloc (size);
688 /* LAMESPEC: all the call conv spec is foobared */
689 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
690 if (mb->call_conv & 2)
691 *p |= 0x5; /* vararg */
692 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
693 *p |= 0x20; /* hasthis */
695 *p |= 0x10; /* generic */
698 mono_metadata_encode_value (ngparams, p, &p);
699 mono_metadata_encode_value (nparams + notypes, p, &p);
700 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
701 encode_reflection_type (assembly, mb->rtype, p, &p);
702 for (i = 0; i < nparams; ++i) {
703 MonoArray *modreq = NULL;
704 MonoArray *modopt = NULL;
705 MonoReflectionType *pt;
707 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
708 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
709 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
710 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
711 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
712 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
713 encode_reflection_type (assembly, pt, p, &p);
716 *p++ = MONO_TYPE_SENTINEL;
717 for (i = 0; i < notypes; ++i) {
718 MonoReflectionType *pt;
720 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
721 encode_reflection_type (assembly, pt, p, &p);
725 g_assert (p - buf < size);
726 mono_metadata_encode_value (p-buf, b, &b);
727 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
733 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
735 MonoDynamicTable *table;
738 guint32 idx, sig_idx, size;
739 guint nl = mono_array_length (ilgen->locals);
746 p = buf = g_malloc (size);
747 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
748 idx = table->next_idx ++;
750 alloc_table (table, table->rows);
751 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
753 mono_metadata_encode_value (0x07, p, &p);
754 mono_metadata_encode_value (nl, p, &p);
755 for (i = 0; i < nl; ++i) {
756 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
759 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
761 encode_reflection_type (assembly, lb->type, p, &p);
763 g_assert (p - buf < size);
764 mono_metadata_encode_value (p-buf, b, &b);
765 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
768 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
774 method_count_clauses (MonoReflectionILGen *ilgen)
776 guint32 num_clauses = 0;
779 MonoILExceptionInfo *ex_info;
780 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
781 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
782 if (ex_info->handlers)
783 num_clauses += mono_array_length (ex_info->handlers);
791 static MonoExceptionClause*
792 method_encode_clauses (MonoDynamicImage *assembly,
793 MonoReflectionILGen *ilgen, guint32 num_clauses)
795 MonoExceptionClause *clauses;
796 MonoExceptionClause *clause;
797 MonoILExceptionInfo *ex_info;
798 MonoILExceptionBlock *ex_block;
799 guint32 finally_start;
800 int i, j, clause_index;;
802 clauses = g_new0 (MonoExceptionClause, num_clauses);
805 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
806 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
807 finally_start = ex_info->start + ex_info->len;
808 g_assert (ex_info->handlers);
809 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
810 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
811 clause = &(clauses [clause_index]);
813 clause->flags = ex_block->type;
814 clause->try_offset = ex_info->start;
816 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
817 clause->try_len = finally_start - ex_info->start;
819 clause->try_len = ex_info->len;
820 clause->handler_offset = ex_block->start;
821 clause->handler_len = ex_block->len;
822 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
823 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
824 if (ex_block->extype) {
825 mono_g_hash_table_insert (assembly->tokens,
826 GUINT_TO_POINTER (clause->token_or_filter),
829 finally_start = ex_block->start + ex_block->len;
839 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
845 gint32 num_locals = 0;
846 gint32 num_exception = 0;
849 char fat_header [12];
852 guint32 local_sig = 0;
853 guint32 header_size = 12;
856 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
857 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
858 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
859 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
863 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
865 code = mb->ilgen->code;
866 code_size = mb->ilgen->code_len;
867 max_stack = mb->ilgen->max_stack;
868 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
869 if (mb->ilgen->ex_handlers)
870 num_exception = method_count_clauses (mb->ilgen);
874 char *name = mono_string_to_utf8 (mb->name);
875 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
876 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
879 mono_raise_exception (exception);
882 code_size = mono_array_length (code);
883 max_stack = 8; /* we probably need to run a verifier on the code... */
886 /* check for exceptions, maxstack, locals */
887 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
889 if (code_size < 64 && !(code_size & 1)) {
890 flags = (code_size << 2) | 0x2;
891 } else if (code_size < 32 && (code_size & 1)) {
892 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
896 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
897 /* add to the fixup todo list */
898 if (mb->ilgen && mb->ilgen->num_token_fixups)
899 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
900 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
901 return assembly->text_rva + idx;
905 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
907 * FIXME: need to set also the header size in fat_flags.
908 * (and more sects and init locals flags)
912 fat_flags |= METHOD_HEADER_MORE_SECTS;
914 fat_flags |= METHOD_HEADER_INIT_LOCALS;
915 fat_header [0] = fat_flags;
916 fat_header [1] = (header_size / 4 ) << 4;
917 shortp = (guint16*)(fat_header + 2);
918 *shortp = GUINT16_TO_LE (max_stack);
919 intp = (guint32*)(fat_header + 4);
920 *intp = GUINT32_TO_LE (code_size);
921 intp = (guint32*)(fat_header + 8);
922 *intp = GUINT32_TO_LE (local_sig);
923 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
924 /* add to the fixup todo list */
925 if (mb->ilgen && mb->ilgen->num_token_fixups)
926 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
928 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
930 unsigned char sheader [4];
931 MonoExceptionClause clause;
932 MonoILExceptionInfo * ex_info;
933 MonoILExceptionBlock * ex_block;
936 stream_data_align (&assembly->code);
937 /* always use fat format for now */
938 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
939 num_exception *= sizeof (MonoExceptionClause);
940 num_exception += 4; /* include the size of the header */
941 sheader [1] = num_exception & 0xff;
942 sheader [2] = (num_exception >> 8) & 0xff;
943 sheader [3] = (num_exception >> 16) & 0xff;
944 mono_image_add_stream_data (&assembly->code, sheader, 4);
945 /* fat header, so we are already aligned */
947 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
948 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
949 if (ex_info->handlers) {
950 int finally_start = ex_info->start + ex_info->len;
951 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
952 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
953 clause.flags = GUINT32_TO_LE (ex_block->type);
954 clause.try_offset = GUINT32_TO_LE (ex_info->start);
955 /* need fault, too, probably */
956 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
957 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
959 clause.try_len = GUINT32_TO_LE (ex_info->len);
960 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
961 clause.handler_len = GUINT32_TO_LE (ex_block->len);
962 finally_start = ex_block->start + ex_block->len;
963 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
964 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
965 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
966 /*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",
967 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);*/
968 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
971 g_error ("No clauses for ex info block %d", i);
975 return assembly->text_rva + idx;
979 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
982 MonoDynamicTable *table;
985 table = &assembly->tables [table_idx];
987 g_assert (col < table->columns);
989 values = table->values + table->columns;
990 for (i = 1; i <= table->rows; ++i) {
991 if (values [col] == token)
993 values += table->columns;
998 static GHashTable *dynamic_custom_attrs = NULL;
1000 static MonoCustomAttrInfo*
1001 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1004 MonoCustomAttrInfo *ainfo;
1005 MonoReflectionCustomAttr *cattr;
1009 /* FIXME: check in assembly the Run flag is set */
1011 count = mono_array_length (cattrs);
1013 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1015 ainfo->image = image;
1016 ainfo->num_attrs = count;
1017 for (i = 0; i < count; ++i) {
1018 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1019 ainfo->attrs [i].ctor = cattr->ctor->method;
1020 /* FIXME: might want to memdup the data here */
1021 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1022 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1029 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1031 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1036 if (!dynamic_custom_attrs)
1037 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1039 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1043 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1045 /* they are cached, so we don't free them */
1046 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1052 * idx is the table index of the object
1053 * type is one of CUSTOM_ATTR_*
1056 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1058 MonoDynamicTable *table;
1059 MonoReflectionCustomAttr *cattr;
1061 guint32 count, i, token;
1063 char *p = blob_size;
1065 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1068 count = mono_array_length (cattrs);
1069 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1070 table->rows += count;
1071 alloc_table (table, table->rows);
1072 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1073 idx <<= CUSTOM_ATTR_BITS;
1075 for (i = 0; i < count; ++i) {
1076 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1077 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1078 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
1079 type = mono_metadata_token_index (token);
1080 type <<= CUSTOM_ATTR_TYPE_BITS;
1081 switch (mono_metadata_token_table (token)) {
1082 case MONO_TABLE_METHOD:
1083 type |= CUSTOM_ATTR_TYPE_METHODDEF;
1085 case MONO_TABLE_MEMBERREF:
1086 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1089 g_warning ("got wrong token in custom attr");
1092 values [MONO_CUSTOM_ATTR_TYPE] = type;
1094 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1095 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1096 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1097 values += MONO_CUSTOM_ATTR_SIZE;
1103 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
1104 MonoArray *permissions)
1106 MonoDynamicTable *table;
1108 guint32 count, i, idx;
1109 MonoReflectionPermissionSet *perm;
1114 count = mono_array_length (permissions);
1115 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1116 table->rows += count;
1117 alloc_table (table, table->rows);
1119 for (i = 0; i < mono_array_length (permissions); ++i) {
1120 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1122 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1124 idx = mono_metadata_token_index (parent_token);
1125 idx <<= HAS_DECL_SECURITY_BITS;
1126 switch (mono_metadata_token_table (parent_token)) {
1127 case MONO_TABLE_TYPEDEF:
1128 idx |= HAS_DECL_SECURITY_TYPEDEF;
1130 case MONO_TABLE_METHOD:
1131 idx |= HAS_DECL_SECURITY_METHODDEF;
1133 case MONO_TABLE_ASSEMBLY:
1134 idx |= HAS_DECL_SECURITY_ASSEMBLY;
1137 g_assert_not_reached ();
1140 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1141 values [MONO_DECL_SECURITY_PARENT] = idx;
1142 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1149 * Fill in the MethodDef and ParamDef tables for a method.
1150 * This is used for both normal methods and constructors.
1153 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1155 MonoDynamicTable *table;
1160 /* room in this table is already allocated */
1161 table = &assembly->tables [MONO_TABLE_METHOD];
1162 *mb->table_idx = table->next_idx ++;
1163 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1164 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1165 name = mono_string_to_utf8 (mb->name);
1166 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1168 values [MONO_METHOD_FLAGS] = mb->attrs;
1169 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1170 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1171 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1173 table = &assembly->tables [MONO_TABLE_PARAM];
1174 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1176 mono_image_add_decl_security (assembly,
1177 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1181 MonoDynamicTable *mtable;
1184 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1185 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1188 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1189 if (mono_array_get (mb->pinfo, gpointer, i))
1192 table->rows += count;
1193 alloc_table (table, table->rows);
1194 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1195 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1196 MonoReflectionParamBuilder *pb;
1197 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1198 values [MONO_PARAM_FLAGS] = pb->attrs;
1199 values [MONO_PARAM_SEQUENCE] = i;
1200 if (pb->name != NULL) {
1201 name = mono_string_to_utf8 (pb->name);
1202 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1206 values [MONO_PARAM_NAME] = 0;
1207 values += MONO_PARAM_SIZE;
1208 if (pb->marshal_info) {
1210 alloc_table (mtable, mtable->rows);
1211 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1212 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
1213 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1215 pb->table_idx = table->next_idx++;
1222 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1223 MonoReflectionMethodBuilder *mb)
1225 rmb->ilgen = mb->ilgen;
1226 rmb->rtype = mb->rtype;
1227 rmb->parameters = mb->parameters;
1228 rmb->generic_params = mb->generic_params;
1229 rmb->opt_types = NULL;
1230 rmb->pinfo = mb->pinfo;
1231 rmb->attrs = mb->attrs;
1232 rmb->iattrs = mb->iattrs;
1233 rmb->call_conv = mb->call_conv;
1234 rmb->code = mb->code;
1235 rmb->type = mb->type;
1236 rmb->name = mb->name;
1237 rmb->table_idx = &mb->table_idx;
1238 rmb->init_locals = mb->init_locals;
1239 rmb->return_modreq = mb->return_modreq;
1240 rmb->return_modopt = mb->return_modopt;
1241 rmb->param_modreq = mb->param_modreq;
1242 rmb->param_modopt = mb->param_modopt;
1243 rmb->permissions = mb->permissions;
1244 rmb->mhandle = mb->mhandle;
1250 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1251 MonoReflectionCtorBuilder *mb)
1253 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1255 rmb->ilgen = mb->ilgen;
1256 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1257 rmb->parameters = mb->parameters;
1258 rmb->generic_params = NULL;
1259 rmb->opt_types = NULL;
1260 rmb->pinfo = mb->pinfo;
1261 rmb->attrs = mb->attrs;
1262 rmb->iattrs = mb->iattrs;
1263 rmb->call_conv = mb->call_conv;
1265 rmb->type = mb->type;
1266 rmb->name = mono_string_new (mono_domain_get (), name);
1267 rmb->table_idx = &mb->table_idx;
1268 rmb->init_locals = mb->init_locals;
1269 rmb->return_modreq = NULL;
1270 rmb->return_modopt = NULL;
1271 rmb->param_modreq = mb->param_modreq;
1272 rmb->param_modopt = mb->param_modopt;
1273 rmb->permissions = mb->permissions;
1274 rmb->mhandle = mb->mhandle;
1280 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1281 MonoReflectionDynamicMethod *mb)
1283 rmb->ilgen = mb->ilgen;
1284 rmb->rtype = mb->rtype;
1285 rmb->parameters = mb->parameters;
1286 rmb->generic_params = NULL;
1287 rmb->opt_types = NULL;
1289 rmb->attrs = mb->attrs;
1291 rmb->call_conv = mb->call_conv;
1294 rmb->name = mb->name;
1295 rmb->table_idx = NULL;
1296 rmb->init_locals = mb->init_locals;
1297 rmb->return_modreq = NULL;
1298 rmb->return_modopt = NULL;
1299 rmb->param_modreq = NULL;
1300 rmb->param_modopt = NULL;
1301 rmb->permissions = NULL;
1302 rmb->mhandle = mb->mhandle;
1308 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1310 MonoDynamicTable *table;
1313 ReflectionMethodBuilder rmb;
1316 reflection_methodbuilder_from_method_builder (&rmb, mb);
1318 mono_image_basic_method (&rmb, assembly);
1320 if (mb->dll) { /* It's a P/Invoke method */
1322 int charset = mb->charset & 0xf;
1323 int lasterr = mb->charset & 0x40;
1324 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1326 alloc_table (table, table->rows);
1327 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1328 /* map CharSet values to on-disk values */
1330 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1331 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1332 name = mono_string_to_utf8 (mb->dllentry);
1333 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1335 name = mono_string_to_utf8 (mb->dll);
1336 moduleref = string_heap_insert (&assembly->sheap, name);
1338 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1339 table = &assembly->tables [MONO_TABLE_MODULEREF];
1341 alloc_table (table, table->rows);
1342 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1343 values [MONO_IMPLMAP_SCOPE] = table->rows;
1347 if (mb->override_method) {
1348 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1350 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1352 alloc_table (table, table->rows);
1353 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1354 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1355 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
1356 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
1357 switch (mono_metadata_token_table (tok)) {
1358 case MONO_TABLE_MEMBERREF:
1359 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
1361 case MONO_TABLE_METHOD:
1362 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
1365 g_assert_not_reached ();
1367 values [MONO_METHODIMPL_DECLARATION] = tok;
1370 if (mb->generic_params) {
1371 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1372 table->rows += mono_array_length (mb->generic_params);
1373 alloc_table (table, table->rows);
1374 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1375 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1377 mono_image_get_generic_param_info (
1378 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1385 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1387 ReflectionMethodBuilder rmb;
1389 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1391 mono_image_basic_method (&rmb, assembly);
1395 type_get_fully_qualified_name (MonoType *type) {
1396 char *name, *result;
1400 name = mono_type_get_name (type);
1401 klass = my_mono_class_from_mono_type (type);
1402 ta = klass->image->assembly;
1404 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1405 name, ta->aname.name,
1406 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1407 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1408 ta->aname.public_tok_value ? ta->aname.public_tok_value : "null");
1414 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1418 klass = my_mono_class_from_mono_type (type);
1419 ta = klass->image->assembly;
1420 if (ta == ass || klass->image == mono_defaults.corlib)
1421 return mono_type_get_name (type);
1423 return type_get_fully_qualified_name (type);
1427 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1429 char blob_size [64];
1430 char *b = blob_size;
1435 if (!assembly->save)
1438 p = buf = g_malloc (64);
1440 mono_metadata_encode_value (0x06, p, &p);
1441 /* encode custom attributes before the type */
1442 encode_type (assembly, type, p, &p);
1443 g_assert (p-buf < 64);
1444 mono_metadata_encode_value (p-buf, b, &b);
1445 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1451 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1453 char blob_size [64];
1454 char *b = blob_size;
1459 p = buf = g_malloc (64);
1461 mono_metadata_encode_value (0x06, p, &p);
1462 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1463 /* encode custom attributes before the type */
1464 encode_reflection_type (assembly, fb->type, p, &p);
1465 g_assert (p-buf < 64);
1466 mono_metadata_encode_value (p-buf, b, &b);
1467 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1473 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1474 char blob_size [64];
1475 char *b = blob_size;
1478 guint32 idx = 0, len = 0, dummy = 0;
1480 p = buf = g_malloc (64);
1482 *ret_type = MONO_TYPE_CLASS;
1484 box_val = (char*)&dummy;
1486 box_val = ((char*)val) + sizeof (MonoObject);
1487 *ret_type = val->vtable->klass->byval_arg.type;
1490 switch (*ret_type) {
1491 case MONO_TYPE_BOOLEAN:
1496 case MONO_TYPE_CHAR:
1511 case MONO_TYPE_VALUETYPE:
1512 if (val->vtable->klass->enumtype) {
1513 *ret_type = val->vtable->klass->enum_basetype->type;
1516 g_error ("we can't encode valuetypes");
1517 case MONO_TYPE_CLASS:
1519 case MONO_TYPE_STRING: {
1520 MonoString *str = (MonoString*)val;
1521 /* there is no signature */
1522 len = str->length * 2;
1523 mono_metadata_encode_value (len, b, &b);
1524 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1526 char *swapped = g_malloc (2 * mono_string_length (str));
1527 const char *p = (const char*)mono_string_chars (str);
1529 swap_with_size (swapped, p, 2, mono_string_length (str));
1530 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1534 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1541 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1544 /* there is no signature */
1545 mono_metadata_encode_value (len, b, &b);
1546 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1547 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1548 swap_with_size (blob_size, box_val, len, 1);
1549 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1551 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1559 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1560 char blob_size [64];
1561 char *b = blob_size;
1562 char *p, *buf, *str;
1563 guint32 idx, len, bufsize = 256;
1565 p = buf = g_malloc (bufsize);
1567 switch (minfo->type) {
1568 case MONO_NATIVE_BYVALTSTR:
1569 case MONO_NATIVE_BYVALARRAY:
1570 mono_metadata_encode_value (minfo->type, p, &p);
1571 mono_metadata_encode_value (minfo->count, p, &p);
1573 case MONO_NATIVE_LPARRAY:
1574 mono_metadata_encode_value (minfo->type, p, &p);
1575 if (minfo->eltype || (minfo->count > 0)) {
1576 mono_metadata_encode_value (minfo->eltype, p, &p);
1577 if (minfo->count > 0) {
1578 mono_metadata_encode_value (0, p, &p);
1579 mono_metadata_encode_value (minfo->count, p, &p);
1583 case MONO_NATIVE_CUSTOM:
1584 mono_metadata_encode_value (minfo->type, p, &p);
1586 str = mono_string_to_utf8 (minfo->guid);
1588 mono_metadata_encode_value (len, p, &p);
1589 memcpy (p, str, len);
1593 mono_metadata_encode_value (0, p, &p);
1595 if (minfo->marshaltype) {
1596 str = mono_string_to_utf8 (minfo->marshaltype);
1598 mono_metadata_encode_value (len, p, &p);
1599 if (p + len >= buf + bufsize) {
1602 buf = g_realloc (buf, bufsize);
1605 memcpy (p, str, len);
1609 mono_metadata_encode_value (0, p, &p);
1611 if (minfo->marshaltyperef) {
1612 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1614 mono_metadata_encode_value (len, p, &p);
1615 if (p + len >= buf + bufsize) {
1618 buf = g_realloc (buf, bufsize);
1621 memcpy (p, str, len);
1625 mono_metadata_encode_value (0, p, &p);
1627 if (minfo->mcookie) {
1628 str = mono_string_to_utf8 (minfo->mcookie);
1630 mono_metadata_encode_value (len, p, &p);
1631 if (p + len >= buf + bufsize) {
1634 buf = g_realloc (buf, bufsize);
1637 memcpy (p, str, len);
1641 mono_metadata_encode_value (0, p, &p);
1645 mono_metadata_encode_value (minfo->type, p, &p);
1649 mono_metadata_encode_value (len, b, &b);
1650 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1656 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1658 MonoDynamicTable *table;
1662 /* maybe this fixup should be done in the C# code */
1663 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1664 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1665 table = &assembly->tables [MONO_TABLE_FIELD];
1666 fb->table_idx = table->next_idx ++;
1667 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1668 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1669 name = mono_string_to_utf8 (fb->name);
1670 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1672 values [MONO_FIELD_FLAGS] = fb->attrs;
1673 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1675 if (fb->offset != -1) {
1676 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1678 alloc_table (table, table->rows);
1679 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1680 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1681 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1683 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1684 guint32 field_type = 0;
1685 table = &assembly->tables [MONO_TABLE_CONSTANT];
1687 alloc_table (table, table->rows);
1688 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1689 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1690 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1691 values [MONO_CONSTANT_TYPE] = field_type;
1692 values [MONO_CONSTANT_PADDING] = 0;
1694 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1696 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1698 alloc_table (table, table->rows);
1699 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1700 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1702 * We store it in the code section because it's simpler for now.
1705 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1707 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1708 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1710 if (fb->marshal_info) {
1711 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1713 alloc_table (table, table->rows);
1714 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1715 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1716 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1721 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1725 char *b = blob_size;
1726 guint32 nparams = 0;
1727 MonoReflectionMethodBuilder *mb = fb->get_method;
1728 MonoReflectionMethodBuilder *smb = fb->set_method;
1729 guint32 idx, i, size;
1731 if (mb && mb->parameters)
1732 nparams = mono_array_length (mb->parameters);
1733 if (!mb && smb && smb->parameters)
1734 nparams = mono_array_length (smb->parameters) - 1;
1735 size = 24 + nparams * 10;
1736 buf = p = g_malloc (size);
1739 mono_metadata_encode_value (nparams, p, &p);
1741 encode_reflection_type (assembly, mb->rtype, p, &p);
1742 for (i = 0; i < nparams; ++i) {
1743 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1744 encode_reflection_type (assembly, pt, p, &p);
1747 /* the property type is the last param */
1748 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1749 for (i = 0; i < nparams; ++i) {
1750 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1751 encode_reflection_type (assembly, pt, p, &p);
1755 g_assert (p - buf < size);
1756 mono_metadata_encode_value (p-buf, b, &b);
1757 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1763 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1765 MonoDynamicTable *table;
1768 guint num_methods = 0;
1772 * we need to set things in the following tables:
1773 * PROPERTYMAP (info already filled in _get_type_info ())
1774 * PROPERTY (rows already preallocated in _get_type_info ())
1775 * METHOD (method info already done with the generic method code)
1778 table = &assembly->tables [MONO_TABLE_PROPERTY];
1779 pb->table_idx = table->next_idx ++;
1780 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1781 name = mono_string_to_utf8 (pb->name);
1782 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1784 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1785 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1787 /* FIXME: we still don't handle 'other' methods */
1788 if (pb->get_method) num_methods ++;
1789 if (pb->set_method) num_methods ++;
1791 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1792 table->rows += num_methods;
1793 alloc_table (table, table->rows);
1795 if (pb->get_method) {
1796 semaidx = table->next_idx ++;
1797 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1798 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1799 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1800 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1802 if (pb->set_method) {
1803 semaidx = table->next_idx ++;
1804 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1805 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1806 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1807 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1812 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1814 MonoDynamicTable *table;
1817 guint num_methods = 0;
1821 * we need to set things in the following tables:
1822 * EVENTMAP (info already filled in _get_type_info ())
1823 * EVENT (rows already preallocated in _get_type_info ())
1824 * METHOD (method info already done with the generic method code)
1827 table = &assembly->tables [MONO_TABLE_EVENT];
1828 eb->table_idx = table->next_idx ++;
1829 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1830 name = mono_string_to_utf8 (eb->name);
1831 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1833 values [MONO_EVENT_FLAGS] = eb->attrs;
1834 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1837 * FIXME: we still don't handle 'other' methods
1839 if (eb->add_method) num_methods ++;
1840 if (eb->remove_method) num_methods ++;
1841 if (eb->raise_method) num_methods ++;
1843 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1844 table->rows += num_methods;
1845 alloc_table (table, table->rows);
1847 if (eb->add_method) {
1848 semaidx = table->next_idx ++;
1849 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1850 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1851 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1852 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1854 if (eb->remove_method) {
1855 semaidx = table->next_idx ++;
1856 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1857 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1858 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1859 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1861 if (eb->raise_method) {
1862 semaidx = table->next_idx ++;
1863 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1864 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1865 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1866 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1871 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1873 static MonoClass *NewConstraintAttr;
1874 static MonoMethod *NewConstraintAttr_ctor;
1875 MonoDynamicTable *table;
1877 guint32 token, type;
1878 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1881 if (!NewConstraintAttr)
1882 NewConstraintAttr = mono_class_from_name (
1883 mono_defaults.corlib, "System.Runtime.CompilerServices",
1884 "NewConstraintAttribute");
1885 g_assert (NewConstraintAttr);
1887 if (!NewConstraintAttr_ctor) {
1890 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1891 MonoMethod *m = NewConstraintAttr->methods [i];
1893 if (strcmp (m->name, ".ctor"))
1896 NewConstraintAttr_ctor = m;
1900 g_assert (NewConstraintAttr_ctor);
1903 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1905 alloc_table (table, table->rows);
1907 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1908 owner <<= CUSTOM_ATTR_BITS;
1909 owner |= CUSTOM_ATTR_GENERICPAR;
1910 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1912 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1914 type = mono_metadata_token_index (token);
1915 type <<= CUSTOM_ATTR_TYPE_BITS;
1916 switch (mono_metadata_token_table (token)) {
1917 case MONO_TABLE_METHOD:
1918 type |= CUSTOM_ATTR_TYPE_METHODDEF;
1920 case MONO_TABLE_MEMBERREF:
1921 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1924 g_warning ("got wrong token in custom attr");
1927 values [MONO_CUSTOM_ATTR_TYPE] = type;
1929 buf = p = g_malloc (1);
1930 mono_metadata_encode_value (4, p, &p);
1931 g_assert (p-buf == 1);
1933 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1935 values += MONO_CUSTOM_ATTR_SIZE;
1940 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1942 MonoDynamicTable *table;
1943 guint32 num_constraints, i;
1947 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1948 num_constraints = gparam->iface_constraints ?
1949 mono_array_length (gparam->iface_constraints) : 0;
1950 table->rows += num_constraints;
1951 if (gparam->base_type)
1953 alloc_table (table, table->rows);
1955 if (gparam->base_type) {
1956 table_idx = table->next_idx ++;
1957 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1959 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1960 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1961 assembly, gparam->base_type->type);
1964 for (i = 0; i < num_constraints; i++) {
1965 MonoReflectionType *constraint = mono_array_get (
1966 gparam->iface_constraints, gpointer, i);
1968 table_idx = table->next_idx ++;
1969 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1971 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1972 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1973 assembly, constraint->type);
1976 if (gparam->has_ctor_constraint)
1977 encode_new_constraint (assembly, owner);
1981 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1983 MonoDynamicTable *table;
1984 MonoGenericParam *param;
1988 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1989 table_idx = table->next_idx ++;
1990 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
1992 param = gparam->type.type->data.generic_param;
1994 values [MONO_GENERICPARAM_OWNER] = owner;
1995 if (gparam->has_value_type)
1996 values [MONO_GENERICPARAM_FLAGS] = 0x18;
1997 else if (gparam->has_reference_type)
1998 values [MONO_GENERICPARAM_FLAGS] = 0x04;
2000 values [MONO_GENERICPARAM_FLAGS] = 0x00;
2001 values [MONO_GENERICPARAM_NUMBER] = param->num;
2002 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2003 values [MONO_GENERICPARAM_KIND] = 0;
2005 encode_constraints (gparam, table_idx, assembly);
2009 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2011 MonoDynamicTable *table;
2014 guint32 cols [MONO_ASSEMBLY_SIZE];
2018 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2021 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2022 table = &assembly->tables [MONO_TABLE_MODULEREF];
2023 token = table->next_idx ++;
2025 alloc_table (table, table->rows);
2026 values = table->values + token * MONO_MODULEREF_SIZE;
2027 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2029 token <<= RESOLTION_SCOPE_BITS;
2030 token |= RESOLTION_SCOPE_MODULEREF;
2031 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2036 if (image->assembly->dynamic)
2038 memset (cols, 0, sizeof (cols));
2040 /* image->assembly->image is the manifest module */
2041 image = image->assembly->image;
2042 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2045 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2046 token = table->next_idx ++;
2048 alloc_table (table, table->rows);
2049 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2050 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2051 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2052 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2053 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2054 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2055 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2056 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2057 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2059 if (strcmp ("", image->assembly->aname.culture)) {
2060 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2061 image->assembly->aname.culture);
2064 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2065 guchar pubtoken [9];
2067 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2068 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2070 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2072 token <<= RESOLTION_SCOPE_BITS;
2073 token |= RESOLTION_SCOPE_ASSEMBLYREF;
2074 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2079 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2081 MonoDynamicTable *table;
2087 char *b = blob_size;
2089 switch (type->type) {
2090 case MONO_TYPE_FNPTR:
2092 case MONO_TYPE_SZARRAY:
2093 case MONO_TYPE_ARRAY:
2095 case MONO_TYPE_MVAR:
2096 case MONO_TYPE_GENERICINST:
2097 encode_type (assembly, type, p, &p);
2099 case MONO_TYPE_CLASS:
2100 case MONO_TYPE_VALUETYPE: {
2101 MonoClass *k = mono_class_from_mono_type (type);
2102 if (!k || !k->generic_inst)
2104 encode_generic_inst (assembly, k->generic_inst, p, &p);
2111 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2112 if (assembly->save) {
2113 g_assert (p-sig < 128);
2114 mono_metadata_encode_value (p-sig, b, &b);
2115 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2116 alloc_table (table, table->rows + 1);
2117 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2118 values [MONO_TYPESPEC_SIGNATURE] = token;
2121 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2122 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2128 * Despite the name, we handle also TypeSpec (with the above helper).
2131 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2133 MonoDynamicTable *table;
2135 guint32 token, scope, enclosing;
2138 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2141 token = create_typespec (assembly, type);
2144 klass = my_mono_class_from_mono_type (type);
2146 klass = mono_class_from_mono_type (type);
2149 * If it's in the same module and not a generic type parameter:
2151 if ((klass->image == &assembly->image) &&
2152 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2153 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2154 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
2155 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2159 if (klass->nested_in) {
2160 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2161 /* get the typeref idx of the enclosing type */
2162 enclosing >>= TYPEDEFORREF_BITS;
2163 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
2165 scope = resolution_scope_from_image (assembly, klass->image);
2167 table = &assembly->tables [MONO_TABLE_TYPEREF];
2168 if (assembly->save) {
2169 alloc_table (table, table->rows + 1);
2170 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2171 values [MONO_TYPEREF_SCOPE] = scope;
2172 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2173 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2175 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
2176 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2178 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2183 * Insert a memberef row into the metadata: the token that point to the memberref
2184 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2185 * mono_image_get_fieldref_token()).
2186 * The sig param is an index to an already built signature.
2189 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2191 MonoDynamicTable *table;
2193 guint32 token, pclass;
2196 parent = mono_image_typedef_or_ref (assembly, type);
2197 switch (parent & TYPEDEFORREF_MASK) {
2198 case TYPEDEFORREF_TYPEREF:
2199 pclass = MEMBERREF_PARENT_TYPEREF;
2201 case TYPEDEFORREF_TYPESPEC:
2202 pclass = MEMBERREF_PARENT_TYPESPEC;
2204 case TYPEDEFORREF_TYPEDEF:
2205 pclass = MEMBERREF_PARENT_TYPEDEF;
2208 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2211 /* extract the index */
2212 parent >>= TYPEDEFORREF_BITS;
2214 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2216 if (assembly->save) {
2217 alloc_table (table, table->rows + 1);
2218 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2219 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2220 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2221 values [MONO_MEMBERREF_SIGNATURE] = sig;
2224 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2231 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2235 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2238 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2239 method->name, method_encode_signature (assembly, method->signature));
2240 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2245 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2246 const gchar *name, guint32 sig)
2248 MonoDynamicTable *table;
2249 guint32 parent, token;
2252 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2254 parent = mono_metadata_token_index (original);
2255 parent <<= MEMBERREF_PARENT_BITS;
2256 switch (mono_metadata_token_table (original)) {
2257 case MONO_TABLE_METHOD:
2258 parent |= MEMBERREF_PARENT_METHODDEF;
2260 case MONO_TABLE_MEMBERREF:
2261 parent |= MEMBERREF_PARENT_TYPEREF;
2264 g_warning ("got wrong token in varargs method token");
2268 if (assembly->save) {
2269 alloc_table (table, table->rows + 1);
2270 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2271 values [MONO_MEMBERREF_CLASS] = parent;
2272 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2273 values [MONO_MEMBERREF_SIGNATURE] = sig;
2276 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2283 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2286 ReflectionMethodBuilder rmb;
2288 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2292 reflection_methodbuilder_from_method_builder (&rmb, mb);
2294 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2295 mono_string_to_utf8 (rmb.name),
2296 method_builder_encode_signature (assembly, &rmb));
2297 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2302 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2305 ReflectionMethodBuilder rmb;
2307 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2311 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2313 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2314 mono_string_to_utf8 (rmb.name),
2315 method_builder_encode_signature (assembly, &rmb));
2316 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2321 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2326 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2329 g_assert (f->field->parent);
2330 type = f->field->generic_type ? f->field->generic_type : f->field->type;
2331 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2332 f->field->name, fieldref_encode_signature (assembly, type));
2333 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2338 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2343 guint32 nparams = gmethod->mtype_argc;
2344 guint32 size = 10 + nparams * 10;
2347 char *b = blob_size;
2349 if (!assembly->save)
2352 p = buf = g_malloc (size);
2354 * FIXME: vararg, explicit_this, differenc call_conv values...
2356 mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2357 mono_metadata_encode_value (nparams, p, &p);
2359 for (i = 0; i < nparams; i++)
2360 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2363 g_assert (p - buf < size);
2364 mono_metadata_encode_value (p-buf, b, &b);
2365 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2371 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2373 MonoDynamicTable *table;
2375 guint32 token, mtoken = 0, sig;
2376 MonoMethodInflated *imethod;
2377 MonoMethod *declaring;
2379 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2381 g_assert (method->signature->is_inflated);
2382 imethod = (MonoMethodInflated *) method;
2383 declaring = imethod->declaring;
2385 sig = method_encode_signature (assembly, declaring->signature);
2386 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2387 declaring->name, sig);
2389 if (!declaring->signature->generic_param_count)
2392 switch (mono_metadata_token_table (mtoken)) {
2393 case MONO_TABLE_MEMBERREF:
2394 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2396 case MONO_TABLE_METHOD:
2397 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2400 g_assert_not_reached ();
2403 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2405 if (assembly->save) {
2406 alloc_table (table, table->rows + 1);
2407 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2408 values [MONO_METHODSPEC_METHOD] = mtoken;
2409 values [MONO_METHODSPEC_SIGNATURE] = sig;
2412 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2419 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2421 MonoMethodInflated *imethod;
2424 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2428 g_assert (m->signature->is_inflated);
2429 imethod = (MonoMethodInflated *) m;
2431 if (imethod->declaring->signature->generic_param_count)
2432 token = method_encode_methodspec (assembly, m);
2434 guint32 sig = method_encode_signature (
2435 assembly, imethod->declaring->signature);
2436 token = mono_image_get_memberref_token (
2437 assembly, &m->klass->byval_arg, m->name, sig);
2440 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2445 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2447 MonoDynamicTable *table;
2454 char *b = blob_size;
2458 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2459 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2460 * Because of this, we must not insert it into the `typeref' hash table.
2463 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2467 g_assert (tb->generic_params);
2468 klass = mono_class_from_mono_type (tb->type.type);
2470 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2471 encode_type (assembly, &klass->byval_arg, p, &p);
2473 count = mono_array_length (tb->generic_params);
2474 mono_metadata_encode_value (count, p, &p);
2475 for (i = 0; i < count; i++) {
2476 MonoReflectionGenericParam *gparam;
2478 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2480 encode_type (assembly, gparam->type.type, p, &p);
2483 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2484 if (assembly->save) {
2485 g_assert (p-sig < 128);
2486 mono_metadata_encode_value (p-sig, b, &b);
2487 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2488 alloc_table (table, table->rows + 1);
2489 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2490 values [MONO_TYPESPEC_SIGNATURE] = token;
2493 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2494 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2500 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2502 MonoDynamicTable *table;
2505 guint32 token, pclass, parent, sig;
2508 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2512 klass = mono_class_from_mono_type (fb->typeb->type);
2513 name = mono_string_to_utf8 (fb->name);
2515 sig = fieldref_encode_signature (assembly, fb->type->type);
2517 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2518 g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2520 pclass = MEMBERREF_PARENT_TYPESPEC;
2521 parent >>= TYPEDEFORREF_BITS;
2523 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2525 if (assembly->save) {
2526 alloc_table (table, table->rows + 1);
2527 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2528 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2529 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2530 values [MONO_MEMBERREF_SIGNATURE] = sig;
2533 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2535 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2540 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2548 char *b = blob_size;
2550 if (!assembly->save)
2554 g_assert (helper->type == 2);
2556 if (helper->arguments)
2557 nargs = mono_array_length (helper->arguments);
2561 size = 10 + (nargs * 10);
2563 p = buf = g_malloc (size);
2565 /* Encode calling convention */
2566 /* Change Any to Standard */
2567 if ((helper->call_conv & 0x03) == 0x03)
2568 helper->call_conv = 0x01;
2569 /* explicit_this implies has_this */
2570 if (helper->call_conv & 0x40)
2571 helper->call_conv &= 0x20;
2573 if (helper->call_conv == 0) /* Unmanaged */
2574 *p = helper->unmanaged_call_conv - 1;
2577 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2578 if (helper->call_conv & 0x02) /* varargs */
2583 mono_metadata_encode_value (nargs, p, &p);
2584 encode_reflection_type (assembly, helper->return_type, p, &p);
2585 for (i = 0; i < nargs; ++i) {
2586 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2587 encode_reflection_type (assembly, pt, p, &p);
2590 g_assert (p - buf < size);
2591 mono_metadata_encode_value (p-buf, b, &b);
2592 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2599 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2602 MonoDynamicTable *table;
2605 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2606 idx = table->next_idx ++;
2608 alloc_table (table, table->rows);
2609 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2611 values [MONO_STAND_ALONE_SIGNATURE] =
2612 mono_reflection_encode_sighelper (assembly, helper);
2618 reflection_cc_to_file (int call_conv) {
2619 switch (call_conv & 0x3) {
2621 case 1: return MONO_CALL_DEFAULT;
2622 case 2: return MONO_CALL_VARARG;
2624 g_assert_not_reached ();
2631 MonoMethodSignature *sig;
2637 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2642 MonoMethodSignature *sig;
2645 name = mono_string_to_utf8 (m->name);
2646 nparams = mono_array_length (m->parameters);
2647 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2649 sig->sentinelpos = -1;
2650 sig->call_convention = reflection_cc_to_file (m->call_conv);
2651 sig->param_count = nparams;
2652 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2653 for (i = 0; i < nparams; ++i) {
2654 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2655 sig->params [i] = t->type;
2658 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2660 if (strcmp (name, am->name) == 0 &&
2661 mono_metadata_type_equal (am->parent, m->parent->type) &&
2662 mono_metadata_signature_equal (am->sig, sig)) {
2665 m->table_idx = am->token & 0xffffff;
2669 am = g_new0 (ArrayMethod, 1);
2672 am->parent = m->parent->type;
2673 am->token = mono_image_get_memberref_token (assembly, am->parent,
2674 name, method_encode_signature (assembly, sig));
2675 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2676 m->table_idx = am->token & 0xffffff;
2681 * Insert into the metadata tables all the info about the TypeBuilder tb.
2682 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2685 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2687 MonoDynamicTable *table;
2689 int i, is_object = 0, is_system = 0;
2692 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2693 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2694 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2695 n = mono_string_to_utf8 (tb->name);
2696 if (strcmp (n, "Object") == 0)
2698 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2700 n = mono_string_to_utf8 (tb->nspace);
2701 if (strcmp (n, "System") == 0)
2703 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2705 if (tb->parent && !(is_system && is_object) &&
2706 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2707 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2709 values [MONO_TYPEDEF_EXTENDS] = 0;
2710 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2711 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2714 * if we have explicitlayout or sequentiallayouts, output data in the
2715 * ClassLayout table.
2717 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2718 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2720 alloc_table (table, table->rows);
2721 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2722 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2723 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2724 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2727 /* handle interfaces */
2728 if (tb->interfaces) {
2729 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2731 table->rows += mono_array_length (tb->interfaces);
2732 alloc_table (table, table->rows);
2733 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2734 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2735 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2736 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2737 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2738 values += MONO_INTERFACEIMPL_SIZE;
2742 /* handle generic parameters */
2743 if (tb->generic_params) {
2744 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2745 table->rows += mono_array_length (tb->generic_params);
2746 alloc_table (table, table->rows);
2747 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2748 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2750 mono_image_get_generic_param_info (
2751 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2757 table = &assembly->tables [MONO_TABLE_FIELD];
2758 table->rows += tb->num_fields;
2759 alloc_table (table, table->rows);
2760 for (i = 0; i < tb->num_fields; ++i)
2761 mono_image_get_field_info (
2762 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2765 /* handle constructors */
2767 table = &assembly->tables [MONO_TABLE_METHOD];
2768 table->rows += mono_array_length (tb->ctors);
2769 alloc_table (table, table->rows);
2770 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2771 mono_image_get_ctor_info (domain,
2772 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2775 /* handle methods */
2777 table = &assembly->tables [MONO_TABLE_METHOD];
2778 table->rows += tb->num_methods;
2779 alloc_table (table, table->rows);
2780 for (i = 0; i < tb->num_methods; ++i)
2781 mono_image_get_method_info (
2782 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2785 /* Do the same with properties etc.. */
2786 if (tb->events && mono_array_length (tb->events)) {
2787 table = &assembly->tables [MONO_TABLE_EVENT];
2788 table->rows += mono_array_length (tb->events);
2789 alloc_table (table, table->rows);
2790 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2792 alloc_table (table, table->rows);
2793 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2794 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2795 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2796 for (i = 0; i < mono_array_length (tb->events); ++i)
2797 mono_image_get_event_info (
2798 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2800 if (tb->properties && mono_array_length (tb->properties)) {
2801 table = &assembly->tables [MONO_TABLE_PROPERTY];
2802 table->rows += mono_array_length (tb->properties);
2803 alloc_table (table, table->rows);
2804 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2806 alloc_table (table, table->rows);
2807 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2808 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2809 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2810 for (i = 0; i < mono_array_length (tb->properties); ++i)
2811 mono_image_get_property_info (
2812 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2815 mono_image_add_decl_security (assembly,
2816 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2820 MonoDynamicTable *ntable;
2822 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2823 ntable->rows += mono_array_length (tb->subtypes);
2824 alloc_table (ntable, ntable->rows);
2825 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2827 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2828 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2830 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2831 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2832 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2833 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2834 mono_string_to_utf8 (tb->name), tb->table_idx,
2835 ntable->next_idx, ntable->rows);*/
2836 values += MONO_NESTED_CLASS_SIZE;
2843 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2847 g_ptr_array_add (types, type);
2849 if (!type->subtypes)
2852 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2853 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2854 collect_types (types, subtype);
2859 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2860 MonoReflectionTypeBuilder **type2)
2862 if ((*type1)->table_idx < (*type2)->table_idx)
2865 if ((*type1)->table_idx > (*type2)->table_idx)
2872 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2877 for (i = 0; i < mono_array_length (pinfo); ++i) {
2878 MonoReflectionParamBuilder *pb;
2879 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2882 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2887 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2890 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2892 for (i = 0; i < tb->num_fields; ++i) {
2893 MonoReflectionFieldBuilder* fb;
2894 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2895 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2899 for (i = 0; i < mono_array_length (tb->events); ++i) {
2900 MonoReflectionEventBuilder* eb;
2901 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2902 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2905 if (tb->properties) {
2906 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2907 MonoReflectionPropertyBuilder* pb;
2908 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2909 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2913 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2914 MonoReflectionCtorBuilder* cb;
2915 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2916 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2917 params_add_cattrs (assembly, cb->pinfo);
2922 for (i = 0; i < tb->num_methods; ++i) {
2923 MonoReflectionMethodBuilder* mb;
2924 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2925 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2926 params_add_cattrs (assembly, mb->pinfo);
2931 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2932 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2937 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2940 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2942 /* no types in the module */
2946 for (i = 0; i < mb->num_types; ++i)
2947 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2951 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2952 MonoDynamicImage *assembly)
2954 MonoDynamicTable *table;
2958 char *b = blob_size;
2961 table = &assembly->tables [MONO_TABLE_FILE];
2963 alloc_table (table, table->rows);
2964 values = table->values + table->next_idx * MONO_FILE_SIZE;
2965 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2966 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2967 if (module->image->dynamic) {
2968 /* This depends on the fact that the main module is emitted last */
2969 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2970 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2974 path = g_strdup (module->image->name);
2976 mono_sha1_get_digest_from_file (path, hash);
2979 mono_metadata_encode_value (20, b, &b);
2980 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2981 mono_image_add_stream_data (&assembly->blob, hash, 20);
2986 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2988 MonoDynamicTable *table;
2992 table = &assembly->tables [MONO_TABLE_MODULE];
2993 mb->table_idx = table->next_idx ++;
2994 name = mono_string_to_utf8 (mb->module.name);
2995 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2997 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3000 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3001 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3002 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3006 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3007 guint32 module_index, guint32 parent_index,
3008 MonoDynamicImage *assembly)
3010 MonoDynamicTable *table;
3014 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3015 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3018 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3020 alloc_table (table, table->rows);
3021 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3023 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3024 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3025 if (klass->nested_in)
3026 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
3028 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
3029 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3030 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3032 res = table->next_idx;
3036 /* Emit nested types */
3037 if (klass->nested_classes) {
3040 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3041 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3048 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3049 guint32 module_index, guint32 parent_index,
3050 MonoDynamicImage *assembly)
3055 klass = mono_class_from_mono_type (tb->type.type);
3057 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3059 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3060 parent_index, assembly);
3064 * We need to do this ourselves since klass->nested_classes is not set up.
3067 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3068 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3073 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3074 guint32 module_index,
3075 MonoDynamicImage *assembly)
3077 MonoImage *image = module->image;
3081 t = &image->tables [MONO_TABLE_TYPEDEF];
3083 for (i = 0; i < t->rows; ++i) {
3084 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3086 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3087 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3091 #define align_pointer(base,p)\
3093 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3095 (p) += 4 - (__diff & 3);\
3099 compare_semantics (const void *a, const void *b)
3101 const guint32 *a_values = a;
3102 const guint32 *b_values = b;
3103 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3106 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3110 compare_custom_attrs (const void *a, const void *b)
3112 const guint32 *a_values = a;
3113 const guint32 *b_values = b;
3115 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3119 compare_field_marshal (const void *a, const void *b)
3121 const guint32 *a_values = a;
3122 const guint32 *b_values = b;
3124 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3128 compare_nested (const void *a, const void *b)
3130 const guint32 *a_values = a;
3131 const guint32 *b_values = b;
3133 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3137 * build_compressed_metadata() fills in the blob of data that represents the
3138 * raw metadata as it will be saved in the PE file. The five streams are output
3139 * and the metadata tables are comnpressed from the guint32 array representation,
3140 * to the compressed on-disk format.
3143 build_compressed_metadata (MonoDynamicImage *assembly)
3145 MonoDynamicTable *table;
3147 guint64 valid_mask = 0;
3148 guint64 sorted_mask;
3149 guint32 heapt_size = 0;
3150 guint32 meta_size = 256; /* allow for header and other stuff */
3151 guint32 table_offset;
3152 guint32 ntables = 0;
3161 MonoDynamicStream *stream;
3164 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3165 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3166 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3167 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3168 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3170 /* tables that are sorted */
3171 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3172 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3173 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3174 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3175 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3176 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
3178 /* Compute table sizes */
3179 /* the MonoImage has already been created in mono_image_basic_init() */
3180 meta = &assembly->image;
3182 /* Setup the info used by compute_sizes () */
3183 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3184 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3185 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3187 meta_size += assembly->blob.index;
3188 meta_size += assembly->guid.index;
3189 meta_size += assembly->sheap.index;
3190 meta_size += assembly->us.index;
3192 for (i=0; i < 64; ++i)
3193 meta->tables [i].rows = assembly->tables [i].rows;
3195 for (i = 0; i < 64; i++){
3196 if (meta->tables [i].rows == 0)
3198 valid_mask |= (guint64)1 << i;
3200 meta->tables [i].row_size = mono_metadata_compute_size (
3201 meta, i, &meta->tables [i].size_bitfield);
3202 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3204 heapt_size += 24; /* #~ header size */
3205 heapt_size += ntables * 4;
3206 meta_size += heapt_size;
3207 meta->raw_metadata = g_malloc0 (meta_size);
3208 p = meta->raw_metadata;
3209 /* the metadata signature */
3210 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3211 /* version numbers and 4 bytes reserved */
3212 int16val = (guint16*)p;
3213 *int16val++ = GUINT16_TO_LE (1);
3214 *int16val = GUINT16_TO_LE (1);
3216 /* version string */
3217 int32val = (guint32*)p;
3218 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3220 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3221 p += GUINT32_FROM_LE (*int32val);
3222 align_pointer (meta->raw_metadata, p);
3223 int16val = (guint16*)p;
3224 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3225 *int16val = GUINT16_TO_LE (5); /* number of streams */
3229 * write the stream info.
3231 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3232 table_offset += 3; table_offset &= ~3;
3234 assembly->tstream.index = heapt_size;
3235 for (i = 0; i < 5; ++i) {
3236 int32val = (guint32*)p;
3237 stream_desc [i].stream->offset = table_offset;
3238 *int32val++ = GUINT32_TO_LE (table_offset);
3239 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3240 table_offset += GUINT32_FROM_LE (*int32val);
3241 table_offset += 3; table_offset &= ~3;
3243 strcpy (p, stream_desc [i].name);
3244 p += strlen (stream_desc [i].name) + 1;
3245 align_pointer (meta->raw_metadata, p);
3248 * now copy the data, the table stream header and contents goes first.
3250 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3251 p = meta->raw_metadata + assembly->tstream.offset;
3252 int32val = (guint32*)p;
3253 *int32val = GUINT32_TO_LE (0); /* reserved */
3256 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3257 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3258 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3259 *p++ = 1; /* version */
3262 *p++ = 1; /* version */
3266 if (meta->idx_string_wide)
3268 if (meta->idx_guid_wide)
3270 if (meta->idx_blob_wide)
3273 *p++ = 0; /* reserved */
3274 int64val = (guint64*)p;
3275 *int64val++ = GUINT64_TO_LE (valid_mask);
3276 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3278 int32val = (guint32*)p;
3279 for (i = 0; i < 64; i++){
3280 if (meta->tables [i].rows == 0)
3282 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3284 p = (unsigned char*)int32val;
3286 /* sort the tables that still need sorting */
3287 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3289 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3290 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3292 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3293 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3295 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3296 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3298 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3300 /* compress the tables */
3301 for (i = 0; i < 64; i++){
3304 guint32 bitfield = meta->tables [i].size_bitfield;
3305 if (!meta->tables [i].rows)
3307 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3308 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3309 meta->tables [i].base = p;
3310 for (row = 1; row <= meta->tables [i].rows; ++row) {
3311 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3312 for (col = 0; col < assembly->tables [i].columns; ++col) {
3313 switch (mono_metadata_table_size (bitfield, col)) {
3315 *p++ = values [col];
3318 *p++ = values [col] & 0xff;
3319 *p++ = (values [col] >> 8) & 0xff;
3322 *p++ = values [col] & 0xff;
3323 *p++ = (values [col] >> 8) & 0xff;
3324 *p++ = (values [col] >> 16) & 0xff;
3325 *p++ = (values [col] >> 24) & 0xff;
3328 g_assert_not_reached ();
3332 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3335 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3336 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3337 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3338 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3339 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3341 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3345 * Some tables in metadata need to be sorted according to some criteria, but
3346 * when methods and fields are first created with reflection, they may be assigned a token
3347 * that doesn't correspond to the final token they will get assigned after the sorting.
3348 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3349 * with the reflection objects that represent them. Once all the tables are set up, the
3350 * reflection objects will contains the correct table index. fixup_method() will fixup the
3351 * tokens for the method with ILGenerator @ilgen.
3354 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3355 guint32 code_idx = GPOINTER_TO_UINT (value);
3356 MonoReflectionILTokenInfo *iltoken;
3357 MonoReflectionFieldBuilder *field;
3358 MonoReflectionCtorBuilder *ctor;
3359 MonoReflectionMethodBuilder *method;
3360 MonoReflectionTypeBuilder *tb;
3361 MonoReflectionArrayMethod *am;
3363 unsigned char *target;
3365 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3366 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3367 target = assembly->code.data + code_idx + iltoken->code_pos;
3368 switch (target [3]) {
3369 case MONO_TABLE_FIELD:
3370 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3371 field = (MonoReflectionFieldBuilder *)iltoken->member;
3372 idx = field->table_idx;
3373 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3374 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3375 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3377 g_assert_not_reached ();
3380 case MONO_TABLE_METHOD:
3381 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3382 method = (MonoReflectionMethodBuilder *)iltoken->member;
3383 idx = method->table_idx;
3384 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3385 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3386 idx = ctor->table_idx;
3387 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3388 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3389 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3390 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3392 g_assert_not_reached ();
3395 case MONO_TABLE_TYPEDEF:
3396 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3397 g_assert_not_reached ();
3398 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3399 idx = tb->table_idx;
3401 case MONO_TABLE_MEMBERREF:
3402 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3403 am = (MonoReflectionArrayMethod*)iltoken->member;
3404 idx = am->table_idx;
3405 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3406 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3407 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3408 g_assert (m->klass->generic_inst);
3410 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3412 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3413 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3414 g_assert (f->generic_type);
3416 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3419 g_assert_not_reached ();
3422 case MONO_TABLE_METHODSPEC:
3423 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3424 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3425 g_assert (m->signature->generic_param_count);
3428 g_assert_not_reached ();
3432 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3434 target [0] = idx & 0xff;
3435 target [1] = (idx >> 8) & 0xff;
3436 target [2] = (idx >> 16) & 0xff;
3443 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3444 * value is not known when the table is emitted.
3447 fixup_cattrs (MonoDynamicImage *assembly)
3449 MonoDynamicTable *table;
3451 guint32 type, i, idx, token;
3454 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3456 for (i = 0; i < table->rows; ++i) {
3457 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3459 type = values [MONO_CUSTOM_ATTR_TYPE];
3460 if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
3461 idx = type >> CUSTOM_ATTR_TYPE_BITS;
3462 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3463 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3466 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3467 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3468 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3469 values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
3476 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3478 MonoDynamicTable *table;
3482 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3484 alloc_table (table, table->rows);
3485 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3486 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3487 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3488 name = mono_string_to_utf8 (rsrc->name);
3489 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3491 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3496 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3498 MonoDynamicTable *table;
3502 char *b = blob_size;
3504 guint32 idx, offset;
3506 if (rsrc->filename) {
3507 name = mono_string_to_utf8 (rsrc->filename);
3508 sname = g_path_get_basename (name);
3510 table = &assembly->tables [MONO_TABLE_FILE];
3512 alloc_table (table, table->rows);
3513 values = table->values + table->next_idx * MONO_FILE_SIZE;
3514 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3515 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3518 mono_sha1_get_digest_from_file (name, hash);
3519 mono_metadata_encode_value (20, b, &b);
3520 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3521 mono_image_add_stream_data (&assembly->blob, hash, 20);
3523 idx = table->next_idx++;
3525 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3528 offset = mono_array_length (rsrc->data);
3529 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3530 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3531 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3532 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3536 * The entry should be emitted into the MANIFESTRESOURCE table of
3537 * the main module, but that needs to reference the FILE table
3538 * which isn't emitted yet.
3545 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3549 set_version_from_string (MonoString *version, guint32 *values)
3551 gchar *ver, *p, *str;
3554 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3555 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3556 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3557 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3560 ver = str = mono_string_to_utf8 (version);
3561 for (i = 0; i < 4; ++i) {
3562 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3568 /* handle Revision and Build */
3578 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3582 char *b = blob_size;
3587 len = mono_array_length (pkey);
3588 mono_metadata_encode_value (len, b, &b);
3589 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3590 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3592 /* need to get the actual value from the key type... */
3593 assembly->strong_name_size = 128;
3594 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3600 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3602 MonoDynamicTable *table;
3603 MonoDynamicImage *assembly;
3604 MonoReflectionAssemblyBuilder *assemblyb;
3609 guint32 module_index;
3611 assemblyb = moduleb->assemblyb;
3612 assembly = moduleb->dynamic_image;
3613 domain = mono_object_domain (assemblyb);
3615 /* Emit ASSEMBLY table */
3616 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3617 alloc_table (table, 1);
3618 values = table->values + MONO_ASSEMBLY_SIZE;
3619 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3620 name = mono_string_to_utf8 (assemblyb->name);
3621 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3623 if (assemblyb->culture) {
3624 name = mono_string_to_utf8 (assemblyb->culture);
3625 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3628 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3630 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3631 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3632 set_version_from_string (assemblyb->version, values);
3634 /* Emit FILE + EXPORTED_TYPE table */
3636 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3638 MonoReflectionModuleBuilder *file_module =
3639 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3640 if (file_module != moduleb) {
3641 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3643 if (file_module->types) {
3644 for (j = 0; j < file_module->num_types; ++j) {
3645 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3646 mono_image_fill_export_table (domain, tb, module_index, 0,
3652 if (assemblyb->loaded_modules) {
3653 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3654 MonoReflectionModule *file_module =
3655 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3656 mono_image_fill_file_table (domain, file_module, assembly);
3658 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3662 /* Emit MANIFESTRESOURCE table */
3664 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3666 MonoReflectionModuleBuilder *file_module =
3667 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3668 /* The table for the main module is emitted later */
3669 if (file_module != moduleb) {
3671 if (file_module->resources) {
3672 int len = mono_array_length (file_module->resources);
3673 for (j = 0; j < len; ++j) {
3674 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3675 assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
3683 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3684 * for the modulebuilder @moduleb.
3685 * At the end of the process, method and field tokens are fixed up and the
3686 * on-disk compressed metadata representation is created.
3689 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3691 MonoDynamicTable *table;
3692 MonoDynamicImage *assembly;
3693 MonoReflectionAssemblyBuilder *assemblyb;
3698 assemblyb = moduleb->assemblyb;
3699 assembly = moduleb->dynamic_image;
3700 domain = mono_object_domain (assemblyb);
3702 if (assembly->text_rva)
3705 assembly->text_rva = START_TEXT_RVA;
3707 if (moduleb->is_main) {
3708 mono_image_emit_manifest (moduleb);
3711 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3712 table->rows = 1; /* .<Module> */
3714 alloc_table (table, table->rows);
3716 * Set the first entry.
3718 values = table->values + table->columns;
3719 values [MONO_TYPEDEF_FLAGS] = 0;
3720 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3721 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3722 values [MONO_TYPEDEF_EXTENDS] = 0;
3723 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3724 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3727 * handle global methods
3728 * FIXME: test what to do when global methods are defined in multiple modules.
3730 if (moduleb->global_methods) {
3731 table = &assembly->tables [MONO_TABLE_METHOD];
3732 table->rows += mono_array_length (moduleb->global_methods);
3733 alloc_table (table, table->rows);
3734 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3735 mono_image_get_method_info (
3736 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3738 if (moduleb->global_fields) {
3739 table = &assembly->tables [MONO_TABLE_FIELD];
3740 table->rows += mono_array_length (moduleb->global_fields);
3741 alloc_table (table, table->rows);
3742 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3743 mono_image_get_field_info (
3744 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3747 table = &assembly->tables [MONO_TABLE_MODULE];
3748 alloc_table (table, 1);
3749 mono_image_fill_module_table (domain, moduleb, assembly);
3753 /* Collect all types into a list sorted by their table_idx */
3754 GPtrArray *types = g_ptr_array_new ();
3757 for (i = 0; i < moduleb->num_types; ++i) {
3758 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3759 collect_types (types, type);
3762 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3763 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3764 table->rows += types->len;
3765 alloc_table (table, table->rows);
3767 for (i = 0; i < types->len; ++i) {
3768 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3769 mono_image_get_type_info (domain, type, assembly);
3771 g_ptr_array_free (types, TRUE);
3775 * table->rows is already set above and in mono_image_fill_module_table.
3777 /* add all the custom attributes at the end, once all the indexes are stable */
3778 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3780 module_add_cattrs (assembly, moduleb);
3783 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3784 fixup_cattrs (assembly);
3788 * mono_image_insert_string:
3789 * @module: module builder object
3792 * Insert @str into the user string stream of @module.
3795 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3797 MonoDynamicImage *assembly;
3802 MONO_ARCH_SAVE_REGS;
3804 if (!module->dynamic_image)
3805 mono_image_module_basic_init (module);
3807 assembly = module->dynamic_image;
3809 if (assembly->save) {
3810 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3811 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3812 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3814 char *swapped = g_malloc (2 * mono_string_length (str));
3815 const char *p = (const char*)mono_string_chars (str);
3817 swap_with_size (swapped, p, 2, mono_string_length (str));
3818 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3822 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3824 mono_image_add_stream_data (&assembly->us, "", 1);
3827 idx = assembly->us.index ++;
3829 mono_g_hash_table_insert (assembly->tokens,
3830 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3832 return MONO_TOKEN_STRING | idx;
3836 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj,
3837 MonoArray *opt_param_types)
3840 guint32 original_token, token = 0;
3842 original_token = mono_image_create_token (assembly, obj);
3844 klass = obj->vtable->klass;
3845 if (strcmp (klass->name, "MonoMethod") == 0) {
3846 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3847 MonoMethodSignature *sig, *old;
3851 g_assert (opt_param_types && method->signature->param_count &&
3852 (method->signature->sentinelpos >= 0));
3854 nargs = mono_array_length (opt_param_types);
3855 old = method->signature;
3856 sig = mono_metadata_signature_alloc (
3857 &assembly->image, old->param_count + nargs);
3859 sig->hasthis = old->hasthis;
3860 sig->explicit_this = old->explicit_this;
3861 sig->call_convention = old->call_convention;
3862 sig->generic_param_count = old->generic_param_count;
3863 sig->param_count = old->param_count + nargs;
3864 sig->sentinelpos = old->param_count;
3865 sig->ret = old->ret;
3867 for (i = 0; i < old->param_count; i++)
3868 sig->params [i] = old->params [i];
3870 for (i = 0; i < nargs; i++) {
3871 MonoReflectionType *rt = mono_array_get (
3872 opt_param_types, MonoReflectionType *, i);
3873 sig->params [old->param_count + i] = rt->type;
3876 sig_token = method_encode_signature (assembly, sig);
3877 token = mono_image_get_varargs_method_token (
3878 assembly, original_token, method->name, sig_token);
3879 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
3880 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3881 ReflectionMethodBuilder rmb;
3884 reflection_methodbuilder_from_method_builder (&rmb, mb);
3885 rmb.opt_types = opt_param_types;
3887 sig = method_builder_encode_signature (assembly, &rmb);
3889 token = mono_image_get_varargs_method_token (
3890 assembly, original_token, mono_string_to_utf8 (rmb.name), sig);
3892 g_error ("requested method token for %s\n", klass->name);
3898 * mono_image_create_token:
3899 * @assembly: a dynamic assembly
3902 * Get a token to insert in the IL code stream for the given MemberInfo.
3903 * @obj can be one of:
3904 * ConstructorBuilder
3914 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3919 klass = obj->vtable->klass;
3920 if (strcmp (klass->name, "MethodBuilder") == 0) {
3921 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3923 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3924 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3926 token = mono_image_get_methodbuilder_token (assembly, mb);
3927 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3929 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3930 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3932 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3933 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3935 token = mono_image_get_ctorbuilder_token (assembly, mb);
3936 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3938 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3939 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3940 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3941 if (tb->generic_params) {
3942 token = mono_image_get_generic_field_token (assembly, fb);
3944 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3947 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3948 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3949 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3951 else if (strcmp (klass->name, "MonoType") == 0 ||
3952 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
3953 MonoReflectionType *tb = (MonoReflectionType *)obj;
3954 token = mono_metadata_token_from_dor (
3955 mono_image_typedef_or_ref (assembly, tb->type));
3957 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
3958 MonoReflectionType *tb = (MonoReflectionType *)obj;
3959 token = mono_metadata_token_from_dor (
3960 mono_image_typedef_or_ref (assembly, tb->type));
3962 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3963 strcmp (klass->name, "MonoMethod") == 0) {
3964 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3965 if (m->method->signature->is_inflated) {
3966 token = mono_image_get_methodspec_token (assembly, m->method);
3967 } else if (m->method->signature->generic_param_count) {
3968 g_assert_not_reached ();
3969 } else if ((m->method->klass->image == &assembly->image) &&
3970 !m->method->klass->generic_inst) {
3971 static guint32 method_table_idx = 0xffffff;
3973 * Each token should have a unique index, but the indexes are
3974 * assigned by managed code, so we don't know about them. An
3975 * easy solution is to count backwards...
3977 method_table_idx --;
3978 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3980 token = mono_image_get_methodref_token (assembly, m->method);
3981 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3983 else if (strcmp (klass->name, "MonoField") == 0) {
3984 MonoReflectionField *f = (MonoReflectionField *)obj;
3985 if ((f->klass->image == &assembly->image) && !f->field->generic_type) {
3986 static guint32 field_table_idx = 0xffffff;
3988 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3990 token = mono_image_get_fieldref_token (assembly, f);
3991 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3993 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
3994 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
3995 token = mono_image_get_array_token (assembly, m);
3997 else if (strcmp (klass->name, "SignatureHelper") == 0) {
3998 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
3999 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4002 g_error ("requested token for %s\n", klass->name);
4004 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
4011 guint32 import_lookup_table;
4015 guint32 import_address_table_rva;
4023 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4025 static MonoDynamicImage*
4026 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
4027 char *assembly_name, char *module_name)
4029 static const guchar entrycode [16] = {0xff, 0x25, 0};
4030 MonoDynamicImage *image;
4034 * We need to use the current ms version or the ms runtime it won't find
4035 * the support dlls. D'oh!
4036 * const char *version = "mono-" VERSION;
4038 const char *version = "v1.0.3705";
4041 image = GC_MALLOC (sizeof (MonoDynamicImage));
4043 image = g_new0 (MonoDynamicImage, 1);
4046 /* keep in sync with image.c */
4047 image->image.name = assembly_name;
4048 image->image.assembly_name = image->image.name; /* they may be different */
4049 image->image.module_name = module_name;
4050 image->image.version = g_strdup (version);
4051 image->image.dynamic = TRUE;
4053 image->image.references = g_new0 (MonoAssembly*, 1);
4054 image->image.references [0] = NULL;
4056 mono_image_init (&image->image);
4058 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4059 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4060 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4061 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4062 image->handleref = g_hash_table_new (NULL, NULL);
4063 image->tokens = mono_g_hash_table_new (NULL, NULL);
4064 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4065 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4066 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4068 string_heap_init (&image->sheap);
4069 mono_image_add_stream_data (&image->us, "", 1);
4070 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4071 /* import tables... */
4072 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4073 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4074 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4075 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4076 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4077 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4078 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4079 stream_data_align (&image->code);
4081 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4083 for (i=0; i < 64; ++i) {
4084 image->tables [i].next_idx = 1;
4085 image->tables [i].columns = table_sizes [i];
4088 image->image.assembly = (MonoAssembly*)assembly;
4089 image->run = assembly->run;
4090 image->save = assembly->save;
4096 * mono_image_basic_init:
4097 * @assembly: an assembly builder object
4099 * Create the MonoImage that represents the assembly builder and setup some
4100 * of the helper hash table and the basic metadata streams.
4103 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4105 MonoDynamicAssembly *assembly;
4106 MonoDynamicImage *image;
4108 MONO_ARCH_SAVE_REGS;
4110 if (assemblyb->dynamic_assembly)
4114 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4116 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4119 assembly->assembly.dynamic = TRUE;
4120 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4121 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4122 if (assemblyb->culture)
4123 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4125 assembly->assembly.aname.culture = g_strdup ("");
4127 assembly->run = assemblyb->access != 2;
4128 assembly->save = assemblyb->access != 1;
4130 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4131 assembly->assembly.aname.name = image->image.name;
4132 assembly->assembly.image = &image->image;
4134 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4135 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4139 calc_section_size (MonoDynamicImage *assembly)
4143 /* alignment constraints */
4144 assembly->code.index += 3;
4145 assembly->code.index &= ~3;
4146 assembly->meta_size += 3;
4147 assembly->meta_size &= ~3;
4148 assembly->resources.index += 3;
4149 assembly->resources.index &= ~3;
4151 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4152 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4155 if (assembly->win32_res) {
4156 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4158 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4159 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4163 assembly->sections [MONO_SECTION_RELOC].size = 12;
4164 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4174 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4178 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4180 ResTreeNode *t1 = (ResTreeNode*)a;
4181 ResTreeNode *t2 = (ResTreeNode*)b;
4183 return t1->id - t2->id;
4187 * resource_tree_create:
4189 * Organize the resources into a resource tree.
4191 static ResTreeNode *
4192 resource_tree_create (MonoArray *win32_resources)
4194 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4198 tree = g_new0 (ResTreeNode, 1);
4200 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4201 MonoReflectionWin32Resource *win32_res =
4202 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4206 lang_node = g_new0 (ResTreeNode, 1);
4207 lang_node->id = win32_res->lang_id;
4208 lang_node->win32_res = win32_res;
4210 /* Create type node if neccesary */
4212 for (l = tree->children; l; l = l->next)
4213 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4214 type_node = (ResTreeNode*)l->data;
4219 type_node = g_new0 (ResTreeNode, 1);
4220 type_node->id = win32_res->res_type;
4223 * The resource types have to be sorted otherwise
4224 * Windows Explorer can't display the version information.
4226 tree->children = g_slist_insert_sorted (tree->children, type_node,
4227 resource_tree_compare_by_id);
4230 /* Create res node if neccesary */
4232 for (l = type_node->children; l; l = l->next)
4233 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4234 res_node = (ResTreeNode*)l->data;
4239 res_node = g_new0 (ResTreeNode, 1);
4240 res_node->id = win32_res->res_id;
4241 type_node->children = g_slist_append (type_node->children, res_node);
4244 res_node->children = g_slist_append (res_node->children, lang_node);
4251 * resource_tree_encode:
4253 * Encode the resource tree into the format used in the PE file.
4256 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4259 MonoPEResourceDir dir;
4260 MonoPEResourceDirEntry dir_entry;
4261 MonoPEResourceDataEntry data_entry;
4265 * For the format of the resource directory, see the article
4266 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4270 memset (&dir, 0, sizeof (dir));
4271 memset (&dir_entry, 0, sizeof (dir_entry));
4272 memset (&data_entry, 0, sizeof (data_entry));
4274 g_assert (sizeof (dir) == 16);
4275 g_assert (sizeof (dir_entry) == 8);
4276 g_assert (sizeof (data_entry) == 16);
4278 node->offset = p - begin;
4280 /* IMAGE_RESOURCE_DIRECTORY */
4281 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4283 memcpy (p, &dir, sizeof (dir));
4286 /* Reserve space for entries */
4288 p += sizeof (dir_entry) * dir.res_id_entries;
4290 /* Write children */
4291 for (l = node->children; l; l = l->next) {
4292 ResTreeNode *child = (ResTreeNode*)l->data;
4294 if (child->win32_res) {
4296 child->offset = p - begin;
4298 /* IMAGE_RESOURCE_DATA_ENTRY */
4299 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4300 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4302 memcpy (p, &data_entry, sizeof (data_entry));
4303 p += sizeof (data_entry);
4305 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4306 p += data_entry.rde_size;
4309 resource_tree_encode (child, begin, p, &p);
4312 /* IMAGE_RESOURCE_ENTRY */
4313 for (l = node->children; l; l = l->next) {
4314 ResTreeNode *child = (ResTreeNode*)l->data;
4315 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4317 dir_entry.is_dir = child->win32_res ? 0 : 1;
4318 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4320 memcpy (entries, &dir_entry, sizeof (dir_entry));
4321 entries += sizeof (dir_entry);
4328 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4333 MonoReflectionWin32Resource *win32_res;
4336 if (!assemblyb->win32_resources)
4340 * Resources are stored in a three level tree inside the PE file.
4341 * - level one contains a node for each type of resource
4342 * - level two contains a node for each resource
4343 * - level three contains a node for each instance of a resource for a
4344 * specific language.
4347 tree = resource_tree_create (assemblyb->win32_resources);
4349 /* Estimate the size of the encoded tree */
4351 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4352 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4353 size += mono_array_length (win32_res->res_data);
4355 /* Directory structure */
4356 size += mono_array_length (assemblyb->win32_resources) * 256;
4357 p = buf = g_malloc (size);
4359 resource_tree_encode (tree, p, p, &p);
4361 g_assert (p - buf < size);
4363 assembly->win32_res = g_malloc (p - buf);
4364 assembly->win32_res_size = p - buf;
4365 memcpy (assembly->win32_res, buf, p - buf);
4371 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4373 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4376 p += sizeof (MonoPEResourceDir);
4377 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4378 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4379 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4380 if (dir_entry->is_dir)
4381 fixup_resource_directory (res_section, child, rva);
4383 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4384 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4387 p += sizeof (MonoPEResourceDirEntry);
4392 * mono_image_create_pefile:
4393 * @mb: a module builder object
4395 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4396 * assembly->pefile where it can be easily retrieved later in chunks.
4399 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4400 MonoMSDOSHeader *msdos;
4401 MonoDotNetHeader *header;
4402 MonoSectionTable *section;
4403 MonoCLIHeader *cli_header;
4404 guint32 size, image_size, virtual_base, text_offset;
4405 guint32 header_start, section_start, file_offset, virtual_offset;
4406 MonoDynamicImage *assembly;
4407 MonoReflectionAssemblyBuilder *assemblyb;
4408 MonoDynamicStream *pefile;
4410 guint32 *rva, value;
4413 static const unsigned char msheader[] = {
4414 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4415 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4417 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4418 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4419 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4420 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4421 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4424 assemblyb = mb->assemblyb;
4426 mono_image_basic_init (assemblyb);
4427 assembly = mb->dynamic_image;
4429 /* already created */
4430 if (assembly->pefile.index)
4433 mono_image_build_metadata (mb);
4435 if (mb->is_main && assemblyb->resources) {
4436 int len = mono_array_length (assemblyb->resources);
4437 for (i = 0; i < len; ++i)
4438 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4441 if (mb->resources) {
4442 int len = mono_array_length (mb->resources);
4443 for (i = 0; i < len; ++i)
4444 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4447 build_compressed_metadata (assembly);
4450 assembly_add_win32_resources (assembly, assemblyb);
4452 nsections = calc_section_size (assembly);
4454 pefile = &assembly->pefile;
4456 /* The DOS header and stub */
4457 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4458 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4460 /* the dotnet header */
4461 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4463 /* the section tables */
4464 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4466 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4467 virtual_offset = VIRT_ALIGN;
4470 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4471 if (!assembly->sections [i].size)
4474 file_offset += FILE_ALIGN - 1;
4475 file_offset &= ~(FILE_ALIGN - 1);
4476 virtual_offset += VIRT_ALIGN - 1;
4477 virtual_offset &= ~(VIRT_ALIGN - 1);
4479 assembly->sections [i].offset = file_offset;
4480 assembly->sections [i].rva = virtual_offset;
4482 file_offset += assembly->sections [i].size;
4483 virtual_offset += assembly->sections [i].size;
4484 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4487 file_offset += FILE_ALIGN - 1;
4488 file_offset &= ~(FILE_ALIGN - 1);
4489 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4491 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4493 /* back-patch info */
4494 msdos = (MonoMSDOSHeader*)pefile->data;
4495 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4496 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4497 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4499 header = (MonoDotNetHeader*)(pefile->data + header_start);
4500 header->pesig [0] = 'P';
4501 header->pesig [1] = 'E';
4503 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4504 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4505 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4506 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4507 if (assemblyb->pekind == 1) {
4509 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4512 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4515 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4517 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4518 header->pe.pe_major = 6;
4519 header->pe.pe_minor = 0;
4520 size = assembly->sections [MONO_SECTION_TEXT].size;
4521 size += FILE_ALIGN - 1;
4522 size &= ~(FILE_ALIGN - 1);
4523 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4524 size = assembly->sections [MONO_SECTION_RSRC].size;
4525 size += FILE_ALIGN - 1;
4526 size &= ~(FILE_ALIGN - 1);
4527 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4528 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4529 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4530 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4531 /* pe_rva_entry_point always at the beginning of the text section */
4532 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4534 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4535 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4536 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4537 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4538 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4539 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4540 size = section_start;
4541 size += FILE_ALIGN - 1;
4542 size &= ~(FILE_ALIGN - 1);
4543 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4545 size += VIRT_ALIGN - 1;
4546 size &= ~(VIRT_ALIGN - 1);
4547 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4550 // Translate the PEFileKind value to the value expected by the Windows loader
4553 short kind = assemblyb->pekind;
4556 // PEFileKinds.ConsoleApplication == 2
4557 // PEFileKinds.WindowApplication == 3
4560 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4561 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4567 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4569 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4570 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4571 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4572 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4573 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4574 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4576 /* fill data directory entries */
4578 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4579 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4581 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4582 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4584 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4585 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4586 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4587 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4588 /* patch imported function RVA name */
4589 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4590 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4592 /* the import table */
4593 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4594 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4595 /* patch imported dll RVA name and other entries in the dir */
4596 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4597 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4598 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4599 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4600 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4601 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4603 p = (assembly->code.data + assembly->ilt_offset);
4604 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4605 *p++ = (value) & 0xff;
4606 *p++ = (value >> 8) & (0xff);
4607 *p++ = (value >> 16) & (0xff);
4608 *p++ = (value >> 24) & (0xff);
4610 /* the CLI header info */
4611 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4612 cli_header->ch_size = GUINT32_FROM_LE (72);
4613 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4614 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4615 if (assemblyb->entry_point) {
4616 guint32 table_idx = 0;
4617 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4618 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4619 table_idx = methodb->table_idx;
4622 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4623 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4626 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4627 /* The embedded managed resources */
4628 text_offset = assembly->text_rva + assembly->code.index;
4629 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4630 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4631 text_offset += assembly->resources.index;
4632 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4633 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4634 text_offset += assembly->meta_size;
4635 if (assembly->strong_name_size) {
4636 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4637 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4638 text_offset += assembly->strong_name_size;
4641 /* write the section tables and section content */
4642 section = (MonoSectionTable*)(pefile->data + section_start);
4643 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4644 static const char *section_names [] = {
4645 ".text", ".rsrc", ".reloc"
4647 if (!assembly->sections [i].size)
4649 strcpy (section->st_name, section_names [i]);
4650 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4651 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4652 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4653 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4654 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4655 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4656 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4658 case MONO_SECTION_TEXT:
4659 /* patch entry point */
4660 p = (assembly->code.data + 2);
4661 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4662 *p++ = (value) & 0xff;
4663 *p++ = (value >> 8) & 0xff;
4664 *p++ = (value >> 16) & 0xff;
4665 *p++ = (value >> 24) & 0xff;
4667 text_offset = assembly->sections [i].offset;
4668 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4669 text_offset += assembly->code.index;
4670 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4671 text_offset += assembly->resources.index;
4672 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4673 text_offset += assembly->meta_size;
4674 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4676 g_free (assembly->image.raw_metadata);
4678 case MONO_SECTION_RELOC:
4679 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4680 *rva = GUINT32_FROM_LE (assembly->text_rva);
4682 *rva = GUINT32_FROM_LE (12);
4684 data16 = (guint16*)rva;
4686 * the entrypoint is always at the start of the text section
4687 * 3 is IMAGE_REL_BASED_HIGHLOW
4688 * 2 is patch_size_rva - text_rva
4690 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4692 *data16 = 0; /* terminate */
4694 case MONO_SECTION_RSRC:
4695 if (assembly->win32_res) {
4696 text_offset = assembly->sections [i].offset;
4698 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4699 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4701 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4705 g_assert_not_reached ();
4710 /* check that the file is properly padded */
4713 FILE *f = fopen ("mypetest.exe", "w");
4714 fwrite (pefile->data, pefile->index, 1, f);
4720 MonoReflectionModule *
4721 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4725 MonoImageOpenStatus status;
4726 MonoDynamicAssembly *assembly;
4728 name = mono_string_to_utf8 (fileName);
4730 image = mono_image_open (name, &status);
4733 if (status == MONO_IMAGE_ERROR_ERRNO)
4734 exc = mono_get_exception_file_not_found (fileName);
4736 exc = mono_get_exception_bad_image_format (name);
4738 mono_raise_exception (exc);
4743 assembly = ab->dynamic_assembly;
4744 image->assembly = (MonoAssembly*)assembly;
4746 mono_assembly_load_references (image, &status);
4748 mono_image_close (image);
4749 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4752 return mono_module_get_object (mono_domain_get (), image);
4756 * We need to return always the same object for MethodInfo, FieldInfo etc..
4757 * but we need to consider the reflected type.
4758 * type uses a different hash, since it uses custom hash/equal functions.
4763 MonoClass *refclass;
4767 reflected_equal (gconstpointer a, gconstpointer b) {
4768 const ReflectedEntry *ea = a;
4769 const ReflectedEntry *eb = b;
4771 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4775 reflected_hash (gconstpointer a) {
4776 const ReflectedEntry *ea = a;
4777 return GPOINTER_TO_UINT (ea->item);
4780 #define CHECK_OBJECT(t,p,k) \
4786 mono_domain_lock (domain); \
4787 if (!domain->refobject_hash) \
4788 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4789 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4790 mono_domain_unlock (domain); \
4796 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4798 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4801 #define CACHE_OBJECT(p,o,k) \
4803 ReflectedEntry *e = ALLOC_REFENTRY; \
4805 e->refclass = (k); \
4806 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4807 mono_domain_unlock (domain); \
4811 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4813 /* this is done only once */
4814 mono_domain_lock (domain);
4815 CACHE_OBJECT (assembly, res, NULL);
4819 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4821 /* this is done only once */
4822 mono_domain_lock (domain);
4823 CACHE_OBJECT (module, res, NULL);
4827 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4829 MonoDynamicImage *image = moduleb->dynamic_image;
4830 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4833 * FIXME: we already created an image in mono_image_basic_init (), but
4834 * we don't know which module it belongs to, since that is only
4835 * determined at assembly save time.
4837 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4838 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4840 moduleb->module.image = &image->image;
4841 moduleb->dynamic_image = image;
4842 register_module (mono_object_domain (moduleb), moduleb, image);
4847 * mono_assembly_get_object:
4848 * @domain: an app domain
4849 * @assembly: an assembly
4851 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4853 MonoReflectionAssembly*
4854 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4856 static MonoClass *System_Reflection_Assembly;
4857 MonoReflectionAssembly *res;
4859 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4860 if (!System_Reflection_Assembly)
4861 System_Reflection_Assembly = mono_class_from_name (
4862 mono_defaults.corlib, "System.Reflection", "Assembly");
4863 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4864 res->assembly = assembly;
4865 CACHE_OBJECT (assembly, res, NULL);
4871 MonoReflectionModule*
4872 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4874 static MonoClass *System_Reflection_Module;
4875 MonoReflectionModule *res;
4877 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4878 if (!System_Reflection_Module)
4879 System_Reflection_Module = mono_class_from_name (
4880 mono_defaults.corlib, "System.Reflection", "Module");
4881 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4884 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4886 res->fqname = mono_string_new (domain, image->name);
4887 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4888 res->scopename = mono_string_new (domain, image->module_name);
4890 mono_image_addref (image);
4892 CACHE_OBJECT (image, res, NULL);
4896 MonoReflectionModule*
4897 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4899 static MonoClass *System_Reflection_Module;
4900 MonoReflectionModule *res;
4901 MonoTableInfo *table;
4902 guint32 cols [MONO_FILE_SIZE];
4904 guint32 i, name_idx;
4907 if (!System_Reflection_Module)
4908 System_Reflection_Module = mono_class_from_name (
4909 mono_defaults.corlib, "System.Reflection", "Module");
4910 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4912 table = &image->tables [MONO_TABLE_FILE];
4913 g_assert (table_index < table->rows);
4914 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4917 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4918 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4920 // Check whenever the row has a corresponding row in the moduleref table
4921 table = &image->tables [MONO_TABLE_MODULEREF];
4922 for (i = 0; i < table->rows; ++i) {
4923 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4924 val = mono_metadata_string_heap (image, name_idx);
4925 if (strcmp (val, name) == 0)
4926 res->image = image->modules [i];
4929 res->fqname = mono_string_new (domain, name);
4930 res->name = mono_string_new (domain, name);
4931 res->scopename = mono_string_new (domain, name);
4932 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4938 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4940 if ((t1->type != t2->type) ||
4941 (t1->byref != t2->byref))
4945 case MONO_TYPE_VOID:
4946 case MONO_TYPE_BOOLEAN:
4947 case MONO_TYPE_CHAR:
4958 case MONO_TYPE_STRING:
4961 case MONO_TYPE_OBJECT:
4962 case MONO_TYPE_TYPEDBYREF:
4964 case MONO_TYPE_VALUETYPE:
4965 case MONO_TYPE_CLASS:
4966 case MONO_TYPE_SZARRAY:
4967 return t1->data.klass == t2->data.klass;
4969 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4970 case MONO_TYPE_ARRAY:
4971 if (t1->data.array->rank != t2->data.array->rank)
4973 return t1->data.array->eklass == t2->data.array->eklass;
4974 case MONO_TYPE_GENERICINST: {
4976 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4978 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4980 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4981 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4987 case MONO_TYPE_MVAR:
4988 return t1->data.generic_param == t2->data.generic_param;
4990 g_error ("implement type compare for %0x!", t1->type);
4998 mymono_metadata_type_hash (MonoType *t1)
5004 hash |= t1->byref << 6; /* do not collide with t1->type values */
5006 case MONO_TYPE_VALUETYPE:
5007 case MONO_TYPE_CLASS:
5008 case MONO_TYPE_SZARRAY:
5009 /* check if the distribution is good enough */
5010 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5012 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5017 static MonoReflectionGenericInst*
5018 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5020 static MonoClass *System_Reflection_MonoGenericInst;
5021 MonoReflectionGenericInst *res;
5022 MonoGenericInst *ginst;
5025 if (!System_Reflection_MonoGenericInst) {
5026 System_Reflection_MonoGenericInst = mono_class_from_name (
5027 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5028 g_assert (System_Reflection_MonoGenericInst);
5031 ginst = geninst->data.generic_inst;
5032 gklass = mono_class_from_mono_type (ginst->generic_type);
5034 mono_class_init (ginst->klass);
5036 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5038 res->type.type = geninst;
5039 if (gklass->wastypebuilder && gklass->reflection_info)
5040 res->generic_type = gklass->reflection_info;
5042 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5048 * mono_type_get_object:
5049 * @domain: an app domain
5052 * Return an System.MonoType object representing the type @type.
5055 mono_type_get_object (MonoDomain *domain, MonoType *type)
5057 MonoReflectionType *res;
5058 MonoClass *klass = mono_class_from_mono_type (type);
5060 mono_domain_lock (domain);
5061 if (!domain->type_hash)
5062 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5063 (GCompareFunc)mymono_metadata_type_equal);
5064 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5065 mono_domain_unlock (domain);
5068 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5069 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5070 mono_g_hash_table_insert (domain->type_hash, type, res);
5071 mono_domain_unlock (domain);
5074 if (klass->reflection_info && !klass->wastypebuilder) {
5075 //g_assert_not_reached ();
5076 /* should this be considered an error condition? */
5078 mono_domain_unlock (domain);
5079 return klass->reflection_info;
5082 mono_class_init (klass);
5083 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5085 mono_g_hash_table_insert (domain->type_hash, type, res);
5086 mono_domain_unlock (domain);
5091 * mono_method_get_object:
5092 * @domain: an app domain
5094 * @refclass: the reflected type (can be NULL)
5096 * Return an System.Reflection.MonoMethod object representing the method @method.
5098 MonoReflectionMethod*
5099 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5102 * We use the same C representation for methods and constructors, but the type
5103 * name in C# is different.
5107 MonoReflectionMethod *ret;
5110 refclass = method->klass;
5112 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5113 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5114 cname = "MonoCMethod";
5116 cname = "MonoMethod";
5117 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5119 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5120 ret->method = method;
5121 ret->name = mono_string_new (domain, method->name);
5122 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5123 CACHE_OBJECT (method, ret, refclass);
5128 * mono_field_get_object:
5129 * @domain: an app domain
5133 * Return an System.Reflection.MonoField object representing the field @field
5136 MonoReflectionField*
5137 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5139 MonoReflectionField *res;
5142 CHECK_OBJECT (MonoReflectionField *, field, klass);
5143 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5144 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5147 res->name = mono_string_new (domain, field->name);
5148 res->attrs = field->type->attrs;
5149 res->type = mono_type_get_object (domain, field->type);
5150 CACHE_OBJECT (field, res, klass);
5155 * mono_property_get_object:
5156 * @domain: an app domain
5158 * @property: a property
5160 * Return an System.Reflection.MonoProperty object representing the property @property
5163 MonoReflectionProperty*
5164 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5166 MonoReflectionProperty *res;
5169 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5170 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5171 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5173 res->property = property;
5174 CACHE_OBJECT (property, res, klass);
5179 * mono_event_get_object:
5180 * @domain: an app domain
5184 * Return an System.Reflection.MonoEvent object representing the event @event
5187 MonoReflectionEvent*
5188 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5190 MonoReflectionEvent *res;
5193 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5194 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5195 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5198 CACHE_OBJECT (event, res, klass);
5203 * mono_param_get_objects:
5204 * @domain: an app domain
5207 * Return an System.Reflection.ParameterInfo array object representing the parameters
5208 * in the method @method.
5211 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5213 static MonoClass *System_Reflection_ParameterInfo;
5214 MonoArray *res = NULL;
5215 MonoReflectionMethod *member = NULL;
5216 MonoReflectionParameter *param = NULL;
5220 if (!System_Reflection_ParameterInfo)
5221 System_Reflection_ParameterInfo = mono_class_from_name (
5222 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5224 if (!method->signature->param_count)
5225 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5227 /* Note: the cache is based on the address of the signature into the method
5228 * since we already cache MethodInfos with the method as keys.
5230 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5232 member = mono_method_get_object (domain, method, NULL);
5233 names = g_new (char *, method->signature->param_count);
5234 mono_method_get_param_names (method, (const char **) names);
5236 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5237 for (i = 0; i < method->signature->param_count; ++i) {
5238 param = (MonoReflectionParameter *)mono_object_new (domain,
5239 System_Reflection_ParameterInfo);
5240 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5241 param->DefaultValueImpl = NULL; /* FIXME */
5242 param->MemberImpl = (MonoObject*)member;
5243 param->NameImpl = mono_string_new (domain, names [i]);
5244 param->PositionImpl = i;
5245 param->AttrsImpl = method->signature->params [i]->attrs;
5246 mono_array_set (res, gpointer, i, param);
5249 CACHE_OBJECT (&(method->signature), res, NULL);
5254 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5258 memset (assembly, 0, sizeof (MonoAssemblyName));
5260 assembly->culture = "";
5261 assembly->public_tok_value = NULL;
5263 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5266 while (*p == ' ' || *p == ',') {
5275 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5277 assembly->major = strtoul (p, &s, 10);
5278 if (s == p || *s != '.')
5281 assembly->minor = strtoul (p, &s, 10);
5282 if (s == p || *s != '.')
5285 assembly->build = strtoul (p, &s, 10);
5286 if (s == p || *s != '.')
5289 assembly->revision = strtoul (p, &s, 10);
5293 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5295 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5296 assembly->culture = g_strdup ("");
5299 assembly->culture = p;
5300 while (*p && *p != ',') {
5304 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5306 if (strncmp (p, "null", 4) == 0) {
5309 assembly->public_tok_value = p;
5310 while (*p && *p != ',') {
5315 while (*p && *p != ',')
5319 while (*p == ' ' || *p == ',') {
5333 * mono_reflection_parse_type:
5336 * Parse a type name as accepted by the GetType () method and output the info
5337 * extracted in the info structure.
5338 * the name param will be mangled, so, make a copy before passing it to this function.
5339 * The fields in info will be valid until the memory pointed to by name is valid.
5340 * Returns 0 on parse error.
5341 * See also mono_type_get_name () below.
5344 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5346 char *start, *p, *w, *last_point, *startn;
5347 int in_modifiers = 0;
5348 int isbyref = 0, rank;
5350 start = p = w = name;
5352 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5353 info->name = info->name_space = NULL;
5354 info->nested = NULL;
5355 info->modifiers = NULL;
5357 /* last_point separates the namespace from the name */
5363 *p = 0; /* NULL terminate the name */
5365 info->nested = g_list_append (info->nested, startn);
5366 /* we have parsed the nesting namespace + name */
5370 info->name_space = start;
5372 info->name = last_point + 1;
5374 info->name_space = (char *)"";
5400 info->name_space = start;
5402 info->name = last_point + 1;
5404 info->name_space = (char *)"";
5411 if (isbyref) /* only one level allowed by the spec */
5414 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5418 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5429 else if (*p != '*') /* '*' means unknown lower bound */
5435 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5447 return 0; /* missing assembly name */
5448 if (!assembly_name_to_aname (&info->assembly, p))
5455 if (info->assembly.name)
5458 *w = 0; /* terminate class name */
5459 if (!info->name || !*info->name)
5461 /* add other consistency checks */
5466 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5473 image = mono_defaults.corlib;
5476 klass = mono_class_from_name_case (image, info->name_space, info->name);
5478 klass = mono_class_from_name (image, info->name_space, info->name);
5481 for (mod = info->nested; mod; mod = mod->next) {
5484 mono_class_init (klass);
5485 nested = klass->nested_classes;
5488 klass = nested->data;
5490 if (g_strcasecmp (klass->name, mod->data) == 0)
5493 if (strcmp (klass->name, mod->data) == 0)
5497 nested = nested->next;
5504 mono_class_init (klass);
5505 for (mod = info->modifiers; mod; mod = mod->next) {
5506 modval = GPOINTER_TO_UINT (mod->data);
5507 if (!modval) { /* byref: must be last modifier */
5508 return &klass->this_arg;
5509 } else if (modval == -1) {
5510 klass = mono_ptr_class_get (&klass->byval_arg);
5511 } else { /* array rank */
5512 klass = mono_array_class_get (klass, modval);
5514 mono_class_init (klass);
5517 return &klass->byval_arg;
5521 * mono_reflection_get_type:
5522 * @image: a metadata context
5523 * @info: type description structure
5524 * @ignorecase: flag for case-insensitive string compares
5526 * Build a MonoType from the type description in @info.
5531 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5534 MonoReflectionAssembly *assembly;
5538 type = mono_reflection_get_type_internal (image, info, ignorecase);
5541 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5544 // Reconstruct the type name
5545 fullName = g_string_new ("");
5546 if (info->name_space && (info->name_space [0] != '\0'))
5547 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5549 g_string_printf (fullName, info->name);
5550 for (mod = info->nested; mod; mod = mod->next)
5551 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5554 mono_domain_try_type_resolve (
5555 mono_domain_get (), fullName->str, NULL);
5556 if (assembly && (!image || (assembly->assembly->image == image))) {
5558 if (assembly->assembly->dynamic) {
5559 /* Enumerate all modules */
5560 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5564 if (abuilder->modules) {
5565 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5566 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5567 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5573 if (!type && abuilder->loaded_modules) {
5574 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5575 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5576 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5583 type = mono_reflection_get_type_internal (assembly->assembly->image,
5586 g_string_free (fullName, TRUE);
5591 * mono_reflection_type_from_name:
5593 * @image: a metadata context (can be NULL).
5595 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5596 * it defaults to get the type from @image or, if @image is NULL or loading
5597 * from it fails, uses corlib.
5601 mono_reflection_type_from_name (char *name, MonoImage *image)
5604 MonoTypeNameParse info;
5605 MonoAssembly *assembly;
5608 /* Make a copy since parse_type modifies its argument */
5609 tmp = g_strdup (name);
5611 /*g_print ("requested type %s\n", str);*/
5612 if (!mono_reflection_parse_type (tmp, &info)) {
5614 g_list_free (info.modifiers);
5615 g_list_free (info.nested);
5619 if (info.assembly.name) {
5620 assembly = mono_assembly_loaded (&info.assembly);
5621 /* do we need to load if it's not already loaded? */
5624 g_list_free (info.modifiers);
5625 g_list_free (info.nested);
5629 image = assembly->image;
5630 } else if (image == NULL) {
5631 image = mono_defaults.corlib;
5634 type = mono_reflection_get_type (image, &info, FALSE);
5635 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5636 image = mono_defaults.corlib;
5637 type = mono_reflection_get_type (image, &info, FALSE);
5641 g_list_free (info.modifiers);
5642 g_list_free (info.nested);
5647 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5649 int slen, type = t->type;
5654 case MONO_TYPE_BOOLEAN: {
5655 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5660 case MONO_TYPE_CHAR:
5662 case MONO_TYPE_I2: {
5663 guint16 *val = g_malloc (sizeof (guint16));
5668 #if SIZEOF_VOID_P == 4
5674 case MONO_TYPE_I4: {
5675 guint32 *val = g_malloc (sizeof (guint32));
5680 #if SIZEOF_VOID_P == 8
5681 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5686 case MONO_TYPE_I8: {
5687 guint64 *val = g_malloc (sizeof (guint64));
5692 case MONO_TYPE_VALUETYPE:
5693 if (t->data.klass->enumtype) {
5694 type = t->data.klass->enum_basetype->type;
5697 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5700 case MONO_TYPE_STRING:
5701 if (*p == (char)0xFF) {
5705 slen = mono_metadata_decode_value (p, &p);
5707 return mono_string_new_len (mono_domain_get (), p, slen);
5708 case MONO_TYPE_CLASS: {
5711 if (*p == (char)0xFF) {
5716 slen = mono_metadata_decode_value (p, &p);
5717 n = g_memdup (p, slen + 1);
5719 t = mono_reflection_type_from_name (n, image);
5721 g_warning ("Cannot load type '%s'", n);
5725 return mono_type_get_object (mono_domain_get (), t);
5729 case MONO_TYPE_OBJECT: {
5732 MonoClass *subc = NULL;
5737 } else if (subt == 0x0E) {
5738 type = MONO_TYPE_STRING;
5740 } else if (subt == 0x55) {
5743 slen = mono_metadata_decode_value (p, &p);
5744 n = g_memdup (p, slen + 1);
5746 t = mono_reflection_type_from_name (n, image);
5748 g_warning ("Cannot load type '%s'", n);
5751 subc = mono_class_from_mono_type (t);
5752 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5753 MonoType simple_type = {{0}};
5754 simple_type.type = subt;
5755 subc = mono_class_from_mono_type (&simple_type);
5757 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5759 val = load_cattr_value (image, &subc->byval_arg, p, end);
5760 obj = mono_object_new (mono_domain_get (), subc);
5761 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5765 case MONO_TYPE_SZARRAY:
5768 guint32 i, alen, basetype;
5771 if (alen == 0xffffffff) {
5775 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5776 basetype = t->data.klass->byval_arg.type;
5781 case MONO_TYPE_BOOLEAN:
5782 for (i=0;i<alen;i++)
5784 MonoBoolean val=*p++;
5785 mono_array_set(arr,MonoBoolean,i,val);
5788 case MONO_TYPE_CHAR:
5791 for (i=0;i<alen;i++)
5793 guint16 val=read16(p);
5794 mono_array_set(arr,guint16,i,val);
5801 for (i=0;i<alen;i++)
5803 guint32 val=read32(p);
5804 mono_array_set(arr,guint32,i,val);
5811 for (i=0;i<alen;i++)
5813 guint64 val=read64(p);
5814 mono_array_set(arr,guint64,i,val);
5818 case MONO_TYPE_CLASS:
5819 case MONO_TYPE_STRING:
5820 for (i = 0; i < alen; i++) {
5821 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5822 mono_array_set (arr, gpointer, i, item);
5826 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5832 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5838 type_is_reference (MonoType *type)
5840 switch (type->type) {
5841 case MONO_TYPE_BOOLEAN:
5842 case MONO_TYPE_CHAR:
5855 case MONO_TYPE_VALUETYPE:
5863 free_param_data (MonoMethodSignature *sig, void **params) {
5865 for (i = 0; i < sig->param_count; ++i) {
5866 if (!type_is_reference (sig->params [i]))
5867 g_free (params [i]);
5872 * Find the method index in the metadata methodDef table.
5873 * Later put these three helper methods in metadata and export them.
5876 find_method_index (MonoMethod *method) {
5877 MonoClass *klass = method->klass;
5880 for (i = 0; i < klass->method.count; ++i) {
5881 if (method == klass->methods [i])
5882 return klass->method.first + 1 + i;
5888 * Find the field index in the metadata FieldDef table.
5891 find_field_index (MonoClass *klass, MonoClassField *field) {
5894 for (i = 0; i < klass->field.count; ++i) {
5895 if (field == &klass->fields [i])
5896 return klass->field.first + 1 + i;
5902 * Find the property index in the metadata Property table.
5905 find_property_index (MonoClass *klass, MonoProperty *property) {
5908 for (i = 0; i < klass->property.count; ++i) {
5909 if (property == &klass->properties [i])
5910 return klass->property.first + 1 + i;
5916 * Find the event index in the metadata Event table.
5919 find_event_index (MonoClass *klass, MonoEvent *event) {
5922 for (i = 0; i < klass->event.count; ++i) {
5923 if (event == &klass->events [i])
5924 return klass->event.first + 1 + i;
5930 create_custom_attr (MonoImage *image, MonoMethod *method,
5931 const char *data, guint32 len)
5933 const char *p = data;
5935 guint32 i, j, num_named;
5939 mono_class_init (method->klass);
5942 attr = mono_object_new (mono_domain_get (), method->klass);
5943 mono_runtime_invoke (method, attr, NULL, NULL);
5947 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5950 /*g_print ("got attr %s\n", method->klass->name);*/
5952 params = g_new (void*, method->signature->param_count);
5956 for (i = 0; i < method->signature->param_count; ++i) {
5957 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5961 attr = mono_object_new (mono_domain_get (), method->klass);
5962 mono_runtime_invoke (method, attr, params, NULL);
5963 free_param_data (method->signature, params);
5965 num_named = read16 (named);
5967 for (j = 0; j < num_named; j++) {
5969 char *name, named_type, data_type;
5970 named_type = *named++;
5971 data_type = *named++; /* type of data */
5972 if (data_type == 0x55) {
5975 type_len = mono_metadata_decode_blob_size (named, &named);
5976 type_name = g_malloc (type_len + 1);
5977 memcpy (type_name, named, type_len);
5978 type_name [type_len] = 0;
5980 /* FIXME: lookup the type and check type consistency */
5983 if (data_type == MONO_TYPE_SZARRAY)
5984 /* The spec does not mention this */
5986 name_len = mono_metadata_decode_blob_size (named, &named);
5987 name = g_malloc (name_len + 1);
5988 memcpy (name, named, name_len);
5989 name [name_len] = 0;
5991 if (named_type == 0x53) {
5992 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
5993 void *val = load_cattr_value (image, field->type, named, &named);
5994 mono_field_set_value (attr, field, val);
5995 if (!type_is_reference (field->type))
5997 } else if (named_type == 0x54) {
6000 MonoType *prop_type;
6002 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6003 /* can we have more that 1 arg in a custom attr named property? */
6004 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6005 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6006 mono_property_set_value (prop, attr, pparams, NULL);
6007 if (!type_is_reference (prop_type))
6008 g_free (pparams [0]);
6017 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6024 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6025 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6026 for (i = 0; i < cinfo->num_attrs; ++i) {
6027 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6028 mono_array_set (result, gpointer, i, attr);
6034 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6036 guint32 mtoken, i, len;
6037 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6039 MonoCustomAttrInfo *ainfo;
6040 GList *tmp, *list = NULL;
6043 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6045 i = mono_metadata_custom_attrs_from_index (image, idx);
6049 while (i < ca->rows) {
6050 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6052 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6055 len = g_list_length (list);
6058 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6059 ainfo->num_attrs = len;
6060 ainfo->image = image;
6061 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6062 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6063 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
6064 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
6065 case CUSTOM_ATTR_TYPE_METHODDEF:
6066 mtoken |= MONO_TOKEN_METHOD_DEF;
6068 case CUSTOM_ATTR_TYPE_MEMBERREF:
6069 mtoken |= MONO_TOKEN_MEMBER_REF;
6072 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6075 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6076 if (!ainfo->attrs [i].ctor)
6077 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6078 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6079 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6080 ainfo->attrs [i].data = data;
6088 mono_custom_attrs_from_method (MonoMethod *method)
6090 MonoCustomAttrInfo *cinfo;
6093 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6095 idx = find_method_index (method);
6096 idx <<= CUSTOM_ATTR_BITS;
6097 idx |= CUSTOM_ATTR_METHODDEF;
6098 return mono_custom_attrs_from_index (method->klass->image, idx);
6102 mono_custom_attrs_from_class (MonoClass *klass)
6104 MonoCustomAttrInfo *cinfo;
6107 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6109 idx = mono_metadata_token_index (klass->type_token);
6110 idx <<= CUSTOM_ATTR_BITS;
6111 idx |= CUSTOM_ATTR_TYPEDEF;
6112 return mono_custom_attrs_from_index (klass->image, idx);
6116 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6118 MonoCustomAttrInfo *cinfo;
6121 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6123 idx = 1; /* there is only one assembly */
6124 idx <<= CUSTOM_ATTR_BITS;
6125 idx |= CUSTOM_ATTR_ASSEMBLY;
6126 return mono_custom_attrs_from_index (assembly->image, idx);
6129 static MonoCustomAttrInfo*
6130 mono_custom_attrs_from_module (MonoImage *image)
6132 MonoCustomAttrInfo *cinfo;
6135 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6137 idx = 1; /* there is only one module */
6138 idx <<= CUSTOM_ATTR_BITS;
6139 idx |= CUSTOM_ATTR_MODULE;
6140 return mono_custom_attrs_from_index (image, idx);
6144 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6146 MonoCustomAttrInfo *cinfo;
6149 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6151 idx = find_property_index (klass, property);
6152 idx <<= CUSTOM_ATTR_BITS;
6153 idx |= CUSTOM_ATTR_PROPERTY;
6154 return mono_custom_attrs_from_index (klass->image, idx);
6158 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6160 MonoCustomAttrInfo *cinfo;
6163 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6165 idx = find_event_index (klass, event);
6166 idx <<= CUSTOM_ATTR_BITS;
6167 idx |= CUSTOM_ATTR_EVENT;
6168 return mono_custom_attrs_from_index (klass->image, idx);
6172 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6174 MonoCustomAttrInfo *cinfo;
6177 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6179 idx = find_field_index (klass, field);
6180 idx <<= CUSTOM_ATTR_BITS;
6181 idx |= CUSTOM_ATTR_FIELDDEF;
6182 return mono_custom_attrs_from_index (klass->image, idx);
6186 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6189 guint32 i, idx, method_index;
6190 guint32 param_list, param_last, param_pos, found;
6192 MonoReflectionMethodAux *aux;
6194 if (method->klass->image->dynamic) {
6195 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6196 if (!aux || !aux->param_cattr)
6198 return aux->param_cattr [param];
6201 image = method->klass->image;
6202 method_index = find_method_index (method);
6203 ca = &image->tables [MONO_TABLE_METHOD];
6205 if (method->klass->generic_inst || method->klass->gen_params ||
6206 method->signature->generic_param_count) {
6207 // FIXME FIXME FIXME
6211 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6212 if (method_index == ca->rows) {
6213 ca = &image->tables [MONO_TABLE_PARAM];
6214 param_last = ca->rows + 1;
6216 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6217 ca = &image->tables [MONO_TABLE_PARAM];
6220 for (i = param_list; i < param_last; ++i) {
6221 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6222 if (param_pos == param) {
6230 idx <<= CUSTOM_ATTR_BITS;
6231 idx |= CUSTOM_ATTR_PARAMDEF;
6232 return mono_custom_attrs_from_index (image, idx);
6236 * mono_reflection_get_custom_attrs:
6237 * @obj: a reflection object handle
6239 * Return an array with all the custom attributes defined of the
6240 * reflection handle @obj. The objects are fully build.
6243 mono_reflection_get_custom_attrs (MonoObject *obj)
6247 MonoCustomAttrInfo *cinfo = NULL;
6249 MONO_ARCH_SAVE_REGS;
6251 klass = obj->vtable->klass;
6252 /* FIXME: need to handle: Module */
6253 if (klass == mono_defaults.monotype_class) {
6254 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6255 klass = mono_class_from_mono_type (rtype->type);
6256 cinfo = mono_custom_attrs_from_class (klass);
6257 } else if (strcmp ("Assembly", klass->name) == 0) {
6258 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6259 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6260 } else if (strcmp ("Module", klass->name) == 0) {
6261 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6262 cinfo = mono_custom_attrs_from_module (module->image);
6263 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6264 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6265 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6266 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6267 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6268 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6269 } else if (strcmp ("MonoField", klass->name) == 0) {
6270 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6271 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6272 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6273 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6274 cinfo = mono_custom_attrs_from_method (rmethod->method);
6275 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6276 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6277 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6278 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6279 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6280 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6281 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6282 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6283 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6284 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6285 } else { /* handle other types here... */
6286 g_error ("get custom attrs not yet supported for %s", klass->name);
6290 result = mono_custom_attrs_construct (cinfo);
6292 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6293 result = mono_array_new (mono_domain_get (), klass, 0);
6299 static MonoMethodSignature*
6300 parameters_to_signature (MonoArray *parameters) {
6301 MonoMethodSignature *sig;
6304 count = parameters? mono_array_length (parameters): 0;
6306 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6307 sig->param_count = count;
6308 sig->sentinelpos = -1; /* FIXME */
6309 for (i = 0; i < count; ++i) {
6310 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6311 sig->params [i] = pt->type;
6316 static MonoMethodSignature*
6317 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6318 MonoMethodSignature *sig;
6320 sig = parameters_to_signature (ctor->parameters);
6321 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6322 sig->ret = &mono_defaults.void_class->byval_arg;
6326 static MonoMethodSignature*
6327 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6328 MonoMethodSignature *sig;
6330 sig = parameters_to_signature (method->parameters);
6331 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6332 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6333 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6337 static MonoMethodSignature*
6338 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6339 MonoMethodSignature *sig;
6341 sig = parameters_to_signature (method->parameters);
6342 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6343 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6344 sig->generic_param_count = 0;
6349 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6351 MonoClass *klass = mono_object_class (prop);
6352 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6353 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6354 *name = mono_string_to_utf8 (pb->name);
6355 *type = pb->type->type;
6357 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6358 *name = g_strdup (p->property->name);
6359 if (p->property->get)
6360 *type = p->property->get->signature->ret;
6362 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6367 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6369 MonoClass *klass = mono_object_class (field);
6370 if (strcmp (klass->name, "FieldBuilder") == 0) {
6371 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6372 *name = mono_string_to_utf8 (fb->name);
6373 *type = fb->type->type;
6375 MonoReflectionField *f = (MonoReflectionField *)field;
6376 *name = g_strdup (f->field->name);
6377 *type = f->field->type;
6382 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6385 MonoTypeEnum simple_type;
6387 if ((p-buffer) + 10 >= *buflen) {
6390 newbuf = g_realloc (buffer, *buflen);
6391 p = newbuf + (p-buffer);
6394 argval = ((char*)arg + sizeof (MonoObject));
6395 simple_type = type->type;
6397 switch (simple_type) {
6398 case MONO_TYPE_BOOLEAN:
6403 case MONO_TYPE_CHAR:
6406 swap_with_size (p, argval, 2, 1);
6412 swap_with_size (p, argval, 4, 1);
6418 swap_with_size (p, argval, 8, 1);
6421 case MONO_TYPE_VALUETYPE:
6422 if (type->data.klass->enumtype) {
6423 simple_type = type->data.klass->enum_basetype->type;
6426 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6429 case MONO_TYPE_STRING: {
6436 str = mono_string_to_utf8 ((MonoString*)arg);
6437 slen = strlen (str);
6438 if ((p-buffer) + 10 + slen >= *buflen) {
6442 newbuf = g_realloc (buffer, *buflen);
6443 p = newbuf + (p-buffer);
6446 mono_metadata_encode_value (slen, p, &p);
6447 memcpy (p, str, slen);
6452 case MONO_TYPE_CLASS: {
6460 k = mono_object_class (arg);
6461 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6462 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6463 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6465 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6466 slen = strlen (str);
6467 if ((p-buffer) + 10 + slen >= *buflen) {
6471 newbuf = g_realloc (buffer, *buflen);
6472 p = newbuf + (p-buffer);
6475 mono_metadata_encode_value (slen, p, &p);
6476 memcpy (p, str, slen);
6481 case MONO_TYPE_SZARRAY: {
6486 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6489 len = mono_array_length ((MonoArray*)arg);
6491 *p++ = (len >> 8) & 0xff;
6492 *p++ = (len >> 16) & 0xff;
6493 *p++ = (len >> 24) & 0xff;
6495 *retbuffer = buffer;
6496 eclass = type->data.klass;
6497 for (i = 0; i < len; ++i) {
6498 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6502 /* it may be a boxed value or a Type */
6503 case MONO_TYPE_OBJECT: {
6504 MonoClass *klass = mono_object_class (arg);
6508 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6511 } else if (klass->enumtype) {
6513 } else if (klass == mono_defaults.string_class) {
6514 simple_type = MONO_TYPE_STRING;
6517 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6518 *p++ = simple_type = klass->byval_arg.type;
6521 g_error ("unhandled type in custom attr");
6523 str = type_get_qualified_name (klass->enum_basetype, NULL);
6524 slen = strlen (str);
6525 if ((p-buffer) + 10 + slen >= *buflen) {
6529 newbuf = g_realloc (buffer, *buflen);
6530 p = newbuf + (p-buffer);
6533 mono_metadata_encode_value (slen, p, &p);
6534 memcpy (p, str, slen);
6537 simple_type = klass->enum_basetype->type;
6541 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6544 *retbuffer = buffer;
6548 * mono_reflection_get_custom_attrs_blob:
6549 * @ctor: custom attribute constructor
6550 * @ctorArgs: arguments o the constructor
6556 * Creates the blob of data that needs to be saved in the metadata and that represents
6557 * the custom attributed described by @ctor, @ctorArgs etc.
6558 * Returns: a Byte array representing the blob of data.
6561 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6564 MonoMethodSignature *sig;
6569 MONO_ARCH_SAVE_REGS;
6571 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6572 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6574 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6576 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6578 p = buffer = g_malloc (buflen);
6579 /* write the prolog */
6582 for (i = 0; i < sig->param_count; ++i) {
6583 arg = mono_array_get (ctorArgs, MonoObject*, i);
6584 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6588 i += mono_array_length (properties);
6590 i += mono_array_length (fields);
6592 *p++ = (i >> 8) & 0xff;
6595 for (i = 0; i < mono_array_length (properties); ++i) {
6600 prop = mono_array_get (properties, gpointer, i);
6601 get_prop_name_and_type (prop, &pname, &ptype);
6602 *p++ = 0x54; /* PROPERTY signature */
6604 /* Preallocate a large enough buffer */
6605 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6606 char *str = type_get_qualified_name (ptype, NULL);
6612 len += strlen (pname);
6614 if ((p-buffer) + 20 + len >= buflen) {
6618 newbuf = g_realloc (buffer, buflen);
6619 p = newbuf + (p-buffer);
6623 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6624 char *str = type_get_qualified_name (ptype, NULL);
6625 int slen = strlen (str);
6629 * This seems to be optional...
6632 mono_metadata_encode_value (slen, p, &p);
6633 memcpy (p, str, slen);
6637 mono_metadata_encode_value (ptype->type, p, &p);
6638 if (ptype->type == MONO_TYPE_SZARRAY)
6639 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6641 len = strlen (pname);
6642 mono_metadata_encode_value (len, p, &p);
6643 memcpy (p, pname, len);
6645 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6652 for (i = 0; i < mono_array_length (fields); ++i) {
6657 field = mono_array_get (fields, gpointer, i);
6658 get_field_name_and_type (field, &fname, &ftype);
6659 *p++ = 0x53; /* FIELD signature */
6660 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6661 char *str = type_get_qualified_name (ftype, NULL);
6662 int slen = strlen (str);
6663 if ((p-buffer) + 10 + slen >= buflen) {
6667 newbuf = g_realloc (buffer, buflen);
6668 p = newbuf + (p-buffer);
6673 * This seems to be optional...
6676 mono_metadata_encode_value (slen, p, &p);
6677 memcpy (p, str, slen);
6681 mono_metadata_encode_value (ftype->type, p, &p);
6683 len = strlen (fname);
6684 mono_metadata_encode_value (len, p, &p);
6685 memcpy (p, fname, len);
6687 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6692 g_assert (p - buffer <= buflen);
6693 buflen = p - buffer;
6694 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6695 p = mono_array_addr (result, char, 0);
6696 memcpy (p, buffer, buflen);
6698 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6704 * mono_reflection_setup_internal_class:
6705 * @tb: a TypeBuilder object
6707 * Creates a MonoClass that represents the TypeBuilder.
6708 * This is a trick that lets us simplify a lot of reflection code
6709 * (and will allow us to support Build and Run assemblies easier).
6712 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6714 MonoClass *klass, *parent;
6716 MONO_ARCH_SAVE_REGS;
6718 klass = g_new0 (MonoClass, 1);
6720 klass->image = &tb->module->dynamic_image->image;
6723 /* check so we can compile corlib correctly */
6724 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6725 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6726 parent = tb->parent->type->data.klass;
6728 parent = my_mono_class_from_mono_type (tb->parent->type);
6732 klass->inited = 1; /* we lie to the runtime */
6733 klass->name = mono_string_to_utf8 (tb->name);
6734 klass->name_space = mono_string_to_utf8 (tb->nspace);
6735 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6736 klass->flags = tb->attrs;
6738 klass->element_class = klass;
6739 klass->reflection_info = tb; /* need to pin. */
6741 /* Put into cache so mono_class_get () will find it */
6742 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6745 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6746 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6750 mono_class_setup_parent (klass, parent);
6751 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6752 const char *old_n = klass->name;
6753 /* trick to get relative numbering right when compiling corlib */
6754 klass->name = "BuildingObject";
6755 mono_class_setup_parent (klass, mono_defaults.object_class);
6756 klass->name = old_n;
6758 mono_class_setup_mono_type (klass);
6760 mono_class_setup_supertypes (klass);
6763 * FIXME: handle interfaces.
6766 tb->type.type = &klass->byval_arg;
6768 if (tb->nesting_type) {
6769 g_assert (tb->nesting_type->type);
6770 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6773 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6777 * mono_reflection_setup_generic_class:
6778 * @tb: a TypeBuilder object
6780 * Setup the generic class after all generic parameters have been added.
6783 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6788 MONO_ARCH_SAVE_REGS;
6790 klass = my_mono_class_from_mono_type (tb->type.type);
6792 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6794 if (klass->gen_params || (count == 0))
6797 klass->num_gen_params = count;
6798 klass->gen_params = g_new0 (MonoGenericParam, count);
6800 for (i = 0; i < count; i++) {
6801 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6802 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6807 * mono_reflection_create_internal_class:
6808 * @tb: a TypeBuilder object
6810 * Actually create the MonoClass that is associated with the TypeBuilder.
6813 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6817 MONO_ARCH_SAVE_REGS;
6819 klass = my_mono_class_from_mono_type (tb->type.type);
6821 if (klass->enumtype && klass->enum_basetype == NULL) {
6822 MonoReflectionFieldBuilder *fb;
6824 g_assert (tb->fields != NULL);
6825 g_assert (mono_array_length (tb->fields) >= 1);
6827 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6829 klass->enum_basetype = fb->type->type;
6830 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6831 if (!klass->element_class)
6832 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6833 klass->instance_size = klass->element_class->instance_size;
6834 klass->size_inited = 1;
6836 * this is almost safe to do with enums and it's needed to be able
6837 * to create objects of the enum type (for use in SetConstant).
6839 /* FIXME: Does this mean enums can't have method overrides ? */
6840 mono_class_setup_vtable (klass, NULL, 0);
6844 static MonoMarshalSpec*
6845 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6846 MonoReflectionMarshal *minfo)
6848 MonoMarshalSpec *res;
6850 res = g_new0 (MonoMarshalSpec, 1);
6851 res->native = minfo->type;
6853 switch (minfo->type) {
6854 case MONO_NATIVE_LPARRAY:
6855 res->data.array_data.elem_type = minfo->eltype;
6856 res->data.array_data.param_num = 0; /* Not yet */
6857 res->data.array_data.num_elem = minfo->count;
6860 case MONO_NATIVE_BYVALTSTR:
6861 case MONO_NATIVE_BYVALARRAY:
6862 res->data.array_data.num_elem = minfo->count;
6865 case MONO_NATIVE_CUSTOM:
6866 if (minfo->marshaltyperef)
6867 res->data.custom_data.custom_name =
6868 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6870 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6881 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6882 ReflectionMethodBuilder *rmb,
6883 MonoMethodSignature *sig)
6886 MonoMethodNormal *pm;
6887 MonoMarshalSpec **specs;
6888 MonoReflectionMethodAux *method_aux;
6891 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6892 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6893 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6896 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6898 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6900 pm = (MonoMethodNormal*)m;
6903 m->flags = rmb->attrs;
6904 m->iflags = rmb->iattrs;
6905 m->name = mono_string_to_utf8 (rmb->name);
6909 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6911 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6912 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6915 m->signature->pinvoke = 1;
6916 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6918 m->signature->pinvoke = 1;
6920 } else if (!m->klass->dummy &&
6921 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6922 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6923 MonoMethodHeader *header;
6925 gint32 max_stack, i;
6926 gint32 num_locals = 0;
6927 gint32 num_clauses = 0;
6931 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6932 code_size = rmb->ilgen->code_len;
6933 max_stack = rmb->ilgen->max_stack;
6934 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6935 if (rmb->ilgen->ex_handlers)
6936 num_clauses = method_count_clauses (rmb->ilgen);
6939 code = mono_array_addr (rmb->code, guint8, 0);
6940 code_size = mono_array_length (rmb->code);
6941 /* we probably need to run a verifier on the code... */
6951 header = g_malloc0 (sizeof (MonoMethodHeader) +
6952 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6953 header->code_size = code_size;
6954 header->code = g_malloc (code_size);
6955 memcpy ((char*)header->code, code, code_size);
6956 header->max_stack = max_stack;
6957 header->init_locals = rmb->init_locals;
6958 header->num_locals = num_locals;
6960 for (i = 0; i < num_locals; ++i) {
6961 MonoReflectionLocalBuilder *lb =
6962 mono_array_get (rmb->ilgen->locals,
6963 MonoReflectionLocalBuilder*, i);
6965 header->locals [i] = g_new0 (MonoType, 1);
6966 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6969 header->num_clauses = num_clauses;
6971 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6976 if (rmb->generic_params) {
6977 int count = mono_array_length (rmb->generic_params);
6978 header->gen_params = g_new0 (MonoGenericParam, count);
6979 for (i = 0; i < count; i++) {
6980 MonoReflectionGenericParam *gp =
6981 mono_array_get (rmb->generic_params,
6982 MonoReflectionGenericParam*, i);
6984 header->gen_params [i] = *gp->type.type->data.generic_param;
6988 pm->header = header;
6992 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
6995 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
6997 for (i = 0; i < rmb->nrefs; ++i)
6998 mw->data = g_list_append (mw->data, rmb->refs [i]);
7003 /* Parameter names */
7006 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7007 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7008 for (i = 0; i <= m->signature->param_count; ++i) {
7009 MonoReflectionParamBuilder *pb;
7010 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7012 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7014 if (!method_aux->param_cattr)
7015 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7016 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7022 /* Parameter marshalling */
7025 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7026 MonoReflectionParamBuilder *pb;
7027 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7028 if (pb->marshal_info) {
7030 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7031 specs [pb->position] =
7032 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7036 if (specs != NULL) {
7038 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7039 method_aux->param_marshall = specs;
7042 if (klass->image->dynamic && method_aux)
7043 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7049 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7051 ReflectionMethodBuilder rmb;
7052 MonoMethodSignature *sig;
7054 sig = ctor_builder_to_signature (mb);
7056 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7058 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7059 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7061 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7062 /* ilgen is no longer needed */
7070 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7072 ReflectionMethodBuilder rmb;
7073 MonoMethodSignature *sig;
7075 sig = method_builder_to_signature (mb);
7077 reflection_methodbuilder_from_method_builder (&rmb, mb);
7079 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7080 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7082 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7083 /* ilgen is no longer needed */
7089 static MonoClassField*
7090 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7092 MonoClassField *field;
7099 field = g_new0 (MonoClassField, 1);
7101 field->name = mono_string_to_utf8 (fb->name);
7103 /* FIXME: handle type modifiers */
7104 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7105 field->type->attrs = fb->attrs;
7107 field->type = fb->type->type;
7109 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7110 field->data = mono_array_addr (fb->rva_data, char, 0);
7111 if (fb->offset != -1)
7112 field->offset = fb->offset;
7113 field->parent = klass;
7115 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7117 if (fb->def_value) {
7118 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7119 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7120 field->def_value = g_new0 (MonoConstant, 1);
7121 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7122 /* Copy the data from the blob since it might get realloc-ed */
7123 p = assembly->blob.data + idx;
7124 len = mono_metadata_decode_blob_size (p, &p2);
7126 field->def_value->value = g_malloc (len);
7127 memcpy (field->def_value->value, p, len);
7134 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7138 MonoReflectionTypeBuilder *tb = NULL;
7139 MonoGenericInst *ginst;
7144 klass = mono_class_from_mono_type (type->type);
7145 if (!klass->gen_params && !klass->generic_inst &&
7146 !(klass->nested_in && klass->nested_in->gen_params))
7149 mono_loader_lock ();
7151 domain = mono_object_domain (type);
7153 ginst = g_new0 (MonoGenericInst, 1);
7155 if (!klass->generic_inst) {
7156 ginst->type_argc = type_argc;
7157 ginst->type_argv = types;
7159 for (i = 0; i < ginst->type_argc; ++i) {
7160 if (!ginst->is_open)
7161 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7164 ginst->generic_type = &klass->byval_arg;
7166 MonoGenericInst *kginst = klass->generic_inst;
7168 ginst->type_argc = kginst->type_argc;
7169 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7171 for (i = 0; i < ginst->type_argc; i++) {
7172 MonoType *t = kginst->type_argv [i];
7174 if (t->type == MONO_TYPE_VAR)
7175 t = types [t->data.generic_param->num];
7177 if (!ginst->is_open)
7178 ginst->is_open = mono_class_is_open_constructed_type (t);
7180 ginst->type_argv [i] = t;
7183 ginst->generic_type = kginst->generic_type;
7186 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7189 mono_loader_unlock ();
7193 ginst->context = g_new0 (MonoGenericContext, 1);
7194 ginst->context->ginst = ginst;
7196 geninst = g_new0 (MonoType, 1);
7197 geninst->type = MONO_TYPE_GENERICINST;
7198 geninst->data.generic_inst = ginst;
7200 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7201 tb = (MonoReflectionTypeBuilder *) type;
7203 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7204 ginst->is_dynamic = TRUE;
7205 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7206 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7207 MonoReflectionType *rgt = rgi->generic_type;
7209 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7210 tb = (MonoReflectionTypeBuilder *) rgt;
7212 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7213 ginst->is_dynamic = TRUE;
7215 icount = klass->interface_count;
7217 ginst->ifaces = g_new0 (MonoType *, icount);
7218 ginst->count_ifaces = icount;
7220 for (i = 0; i < icount; i++) {
7221 MonoReflectionType *itype;
7224 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7226 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7227 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7228 if (!ginst->ifaces [i])
7229 ginst->ifaces [i] = itype->type;
7232 mono_class_create_generic (ginst);
7234 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7236 mono_loader_unlock ();
7242 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7244 MonoClass *klass, *pklass = NULL;
7245 MonoReflectionType *parent = NULL;
7247 MonoReflectionTypeBuilder *tb = NULL;
7248 MonoGenericInst *ginst;
7251 domain = mono_object_domain (type);
7252 klass = mono_class_from_mono_type (type->type);
7254 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7255 tb = (MonoReflectionTypeBuilder *) type;
7258 parent = tb->parent;
7259 pklass = mono_class_from_mono_type (parent->type);
7262 pklass = klass->parent;
7264 parent = mono_type_get_object (domain, &pklass->byval_arg);
7267 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7271 ginst = geninst->data.generic_inst;
7273 if (pklass && pklass->generic_inst)
7274 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7279 MonoReflectionMethod*
7280 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7282 MonoMethod *method, *inflated;
7283 MonoReflectionMethodBuilder *mb = NULL;
7284 MonoGenericMethod *gmethod;
7285 MonoGenericContext *context;
7288 MONO_ARCH_SAVE_REGS;
7289 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7290 MonoReflectionTypeBuilder *tb;
7293 mb = (MonoReflectionMethodBuilder *) rmethod;
7294 tb = (MonoReflectionTypeBuilder *) mb->type;
7295 klass = mono_class_from_mono_type (tb->type.type);
7297 method = methodbuilder_to_mono_method (klass, mb);
7299 method = rmethod->method;
7301 count = method->signature->generic_param_count;
7302 if (count != mono_array_length (types))
7305 gmethod = g_new0 (MonoGenericMethod, 1);
7306 gmethod->mtype_argc = count;
7307 gmethod->mtype_argv = g_new0 (MonoType *, count);
7308 for (i = 0; i < count; i++) {
7309 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7310 gmethod->mtype_argv [i] = garg->type;
7313 context = g_new0 (MonoGenericContext, 1);
7314 context->ginst = method->klass->generic_inst;
7315 context->gmethod = gmethod;
7317 inflated = mono_class_inflate_generic_method (method, context, NULL);
7319 return mono_method_get_object (
7320 mono_object_domain (rmethod), inflated, NULL);
7324 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7326 MonoGenericMethod *gmethod;
7327 MonoGenericInst *ginst;
7328 MonoGenericContext *context;
7331 ginst = type->type.type->data.generic_inst;
7333 gmethod = g_new0 (MonoGenericMethod, 1);
7334 gmethod->reflection_info = obj;
7336 gmethod->mtype_argc = method->signature->generic_param_count;
7337 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7339 for (i = 0; i < gmethod->mtype_argc; i++) {
7340 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7341 MonoGenericParam *gparam = &mn->header->gen_params [i];
7343 g_assert (gparam->pklass);
7344 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7347 context = g_new0 (MonoGenericContext, 1);
7348 context->ginst = ginst;
7349 context->gmethod = gmethod;
7351 return mono_class_inflate_generic_method (method, context, ginst->klass);
7355 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7360 klass = mono_class_from_mono_type (type->type.type);
7362 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7363 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7364 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7365 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7366 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7367 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7368 method = ((MonoReflectionMethod *) obj)->method;
7370 method = NULL; /* prevent compiler warning */
7371 g_assert_not_reached ();
7374 return inflate_mono_method (type, method, obj);
7378 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7379 MonoArray *methods, MonoArray *ctors,
7380 MonoArray *fields, MonoArray *properties,
7383 MonoGenericInst *ginst;
7384 MonoDynamicGenericInst *dginst;
7385 MonoClass *klass, *gklass, *pklass;
7388 MONO_ARCH_SAVE_REGS;
7390 klass = mono_class_from_mono_type (type->type.type);
7391 ginst = type->type.type->data.generic_inst;
7393 if (ginst->initialized)
7396 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7398 gklass = mono_class_from_mono_type (ginst->generic_type);
7399 mono_class_init (gklass);
7402 pklass = mono_class_from_mono_type (ginst->parent);
7404 pklass = gklass->parent;
7406 mono_class_setup_parent (klass, pklass);
7408 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7409 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7410 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7411 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7412 dginst->count_events = events ? mono_array_length (events) : 0;
7414 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7415 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7416 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7417 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7418 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7420 for (i = 0; i < dginst->count_methods; i++) {
7421 MonoObject *obj = mono_array_get (methods, gpointer, i);
7423 dginst->methods [i] = inflate_method (type, obj);
7426 for (i = 0; i < dginst->count_ctors; i++) {
7427 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7429 dginst->ctors [i] = inflate_method (type, obj);
7432 for (i = 0; i < dginst->count_fields; i++) {
7433 MonoObject *obj = mono_array_get (fields, gpointer, i);
7434 MonoClassField *field;
7436 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7437 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7438 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7439 field = ((MonoReflectionField *) obj)->field;
7441 field = NULL; /* prevent compiler warning */
7442 g_assert_not_reached ();
7445 dginst->fields [i] = *field;
7446 dginst->fields [i].generic_type = field->type;
7447 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7450 for (i = 0; i < dginst->count_properties; i++) {
7451 MonoObject *obj = mono_array_get (properties, gpointer, i);
7452 MonoProperty *property = &dginst->properties [i];
7454 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7455 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7457 property->parent = klass;
7458 property->attrs = pb->attrs;
7459 property->name = mono_string_to_utf8 (pb->name);
7461 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7463 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7464 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7465 *property = *((MonoReflectionProperty *) obj)->property;
7468 property->get = inflate_mono_method (type, property->get, NULL);
7470 property->set = inflate_mono_method (type, property->set, NULL);
7472 g_assert_not_reached ();
7475 for (i = 0; i < dginst->count_events; i++) {
7476 MonoObject *obj = mono_array_get (events, gpointer, i);
7477 MonoEvent *event = &dginst->events [i];
7479 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7480 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7482 event->parent = klass;
7483 event->attrs = eb->attrs;
7484 event->name = mono_string_to_utf8 (eb->name);
7486 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7487 if (eb->remove_method)
7488 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7489 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7490 *event = *((MonoReflectionEvent *) obj)->event;
7493 event->add = inflate_mono_method (type, event->add, NULL);
7495 event->remove = inflate_mono_method (type, event->remove, NULL);
7497 g_assert_not_reached ();
7500 ginst->initialized = TRUE;
7504 ensure_runtime_vtable (MonoClass *klass)
7506 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7507 int i, num, j, onum;
7508 MonoMethod **overrides;
7510 if (!tb || klass->wastypebuilder)
7513 ensure_runtime_vtable (klass->parent);
7515 num = tb->ctors? mono_array_length (tb->ctors): 0;
7516 num += tb->num_methods;
7517 klass->method.count = num;
7518 klass->methods = g_new (MonoMethod*, num);
7519 num = tb->ctors? mono_array_length (tb->ctors): 0;
7520 for (i = 0; i < num; ++i)
7521 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7522 num = tb->num_methods;
7524 for (i = 0; i < num; ++i)
7525 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7527 klass->wastypebuilder = TRUE;
7528 if (tb->interfaces) {
7529 klass->interface_count = mono_array_length (tb->interfaces);
7530 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7531 for (i = 0; i < klass->interface_count; ++i) {
7532 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7533 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7537 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7538 for (i = 0; i < klass->method.count; ++i)
7539 klass->methods [i]->slot = i;
7544 for (i = 0; i < tb->num_methods; ++i) {
7545 MonoReflectionMethodBuilder *mb =
7546 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7547 if (mb->override_method)
7552 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7556 for (i = 0; i < tb->num_methods; ++i) {
7557 MonoReflectionMethodBuilder *mb =
7558 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7559 if (mb->override_method) {
7560 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7561 overrides [onum * 2] =
7562 mb->override_method->method;
7563 overrides [onum * 2 + 1] =
7566 g_assert (mb->mhandle);
7573 mono_class_setup_vtable (klass, overrides, onum);
7577 typebuilder_setup_fields (MonoClass *klass)
7579 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7580 MonoReflectionFieldBuilder *fb;
7581 MonoClassField *field;
7586 klass->field.count = tb->num_fields;
7587 klass->field.first = 0;
7588 klass->field.last = klass->field.count;
7590 if (!klass->field.count)
7593 klass->fields = g_new0 (MonoClassField, klass->field.count);
7595 for (i = 0; i < klass->field.count; ++i) {
7596 fb = mono_array_get (tb->fields, gpointer, i);
7597 field = &klass->fields [i];
7598 field->name = mono_string_to_utf8 (fb->name);
7600 /* FIXME: handle type modifiers */
7601 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7602 field->type->attrs = fb->attrs;
7604 field->type = fb->type->type;
7606 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7607 field->data = mono_array_addr (fb->rva_data, char, 0);
7608 if (fb->offset != -1)
7609 field->offset = fb->offset;
7610 field->parent = klass;
7612 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7614 if (fb->def_value) {
7615 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7616 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7617 field->def_value = g_new0 (MonoConstant, 1);
7618 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7619 /* Copy the data from the blob since it might get realloc-ed */
7620 p = assembly->blob.data + idx;
7621 len = mono_metadata_decode_blob_size (p, &p2);
7623 field->def_value->value = g_malloc (len);
7624 memcpy (field->def_value->value, p, len);
7627 mono_class_layout_fields (klass);
7631 typebuilder_setup_properties (MonoClass *klass)
7633 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7634 MonoReflectionPropertyBuilder *pb;
7637 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7638 klass->property.first = 0;
7639 klass->property.last = klass->property.count;
7641 klass->properties = g_new0 (MonoProperty, klass->property.count);
7642 for (i = 0; i < klass->property.count; ++i) {
7643 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7644 klass->properties [i].parent = klass;
7645 klass->properties [i].attrs = pb->attrs;
7646 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7648 klass->properties [i].get = pb->get_method->mhandle;
7650 klass->properties [i].set = pb->set_method->mhandle;
7654 MonoReflectionEvent *
7655 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7657 MonoEvent *event = g_new0 (MonoEvent, 1);
7661 klass = my_mono_class_from_mono_type (tb->type.type);
7663 event->parent = klass;
7664 event->attrs = eb->attrs;
7665 event->name = mono_string_to_utf8 (eb->name);
7667 event->add = eb->add_method->mhandle;
7668 if (eb->remove_method)
7669 event->remove = eb->remove_method->mhandle;
7670 if (eb->raise_method)
7671 event->raise = eb->raise_method->mhandle;
7673 if (eb->other_methods) {
7674 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7675 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7676 MonoReflectionMethodBuilder *mb =
7677 mono_array_get (eb->other_methods,
7678 MonoReflectionMethodBuilder*, j);
7679 event->other [j] = mb->mhandle;
7683 return mono_event_get_object (mono_object_domain (tb), klass, event);
7687 typebuilder_setup_events (MonoClass *klass)
7689 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7690 MonoReflectionEventBuilder *eb;
7693 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7694 klass->event.first = 0;
7695 klass->event.last = klass->event.count;
7697 klass->events = g_new0 (MonoEvent, klass->event.count);
7698 for (i = 0; i < klass->event.count; ++i) {
7699 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7700 klass->events [i].parent = klass;
7701 klass->events [i].attrs = eb->attrs;
7702 klass->events [i].name = mono_string_to_utf8 (eb->name);
7704 klass->events [i].add = eb->add_method->mhandle;
7705 if (eb->remove_method)
7706 klass->events [i].remove = eb->remove_method->mhandle;
7707 if (eb->raise_method)
7708 klass->events [i].raise = eb->raise_method->mhandle;
7710 if (eb->other_methods) {
7711 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7712 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7713 MonoReflectionMethodBuilder *mb =
7714 mono_array_get (eb->other_methods,
7715 MonoReflectionMethodBuilder*, j);
7716 klass->events [i].other [j] = mb->mhandle;
7723 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7726 MonoReflectionType* res;
7728 MONO_ARCH_SAVE_REGS;
7730 klass = my_mono_class_from_mono_type (tb->type.type);
7732 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7735 * Fields to set in klass:
7736 * the various flags: delegate/unicode/contextbound etc.
7739 klass->flags = tb->attrs;
7741 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7742 /* No need to fully construct the type */
7743 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7745 /* enums are done right away */
7746 if (!klass->enumtype)
7747 ensure_runtime_vtable (klass);
7749 /* fields and object layout */
7750 if (klass->parent) {
7751 if (!klass->parent->size_inited)
7752 mono_class_init (klass->parent);
7753 klass->instance_size += klass->parent->instance_size;
7754 klass->class_size += klass->parent->class_size;
7755 klass->min_align = klass->parent->min_align;
7757 klass->instance_size = sizeof (MonoObject);
7758 klass->min_align = 1;
7761 /* FIXME: handle packing_size and instance_size */
7762 typebuilder_setup_fields (klass);
7764 typebuilder_setup_properties (klass);
7766 typebuilder_setup_events (klass);
7768 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7769 /* with enums res == tb: need to fix that. */
7770 if (!klass->enumtype)
7771 g_assert (res != (MonoReflectionType*)tb);
7776 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7778 MonoGenericParam *param;
7781 MONO_ARCH_SAVE_REGS;
7783 param = g_new0 (MonoGenericParam, 1);
7785 param->method = NULL;
7786 param->name = mono_string_to_utf8 (gparam->name);
7787 param->num = gparam->index;
7789 image = &gparam->tbuilder->module->dynamic_image->image;
7790 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7792 param->pklass->reflection_info = gparam;
7794 gparam->type.type = g_new0 (MonoType, 1);
7795 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7796 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7797 gparam->type.type->data.generic_param = param;
7801 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7803 MonoDynamicImage *assembly = sig->module->dynamic_image;
7804 guint32 na = mono_array_length (sig->arguments);
7809 MONO_ARCH_SAVE_REGS;
7811 p = buf = g_malloc (10 + na * 10);
7813 mono_metadata_encode_value (0x07, p, &p);
7814 mono_metadata_encode_value (na, p, &p);
7815 for (i = 0; i < na; ++i) {
7816 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7817 encode_reflection_type (assembly, type, p, &p);
7821 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7822 p = mono_array_addr (result, char, 0);
7823 memcpy (p, buf, buflen);
7830 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7832 MonoDynamicImage *assembly = sig->module->dynamic_image;
7833 guint32 na = mono_array_length (sig->arguments);
7838 MONO_ARCH_SAVE_REGS;
7840 p = buf = g_malloc (10 + na * 10);
7842 mono_metadata_encode_value (0x06, p, &p);
7843 for (i = 0; i < na; ++i) {
7844 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7845 encode_reflection_type (assembly, type, p, &p);
7849 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7850 p = mono_array_addr (result, char, 0);
7851 memcpy (p, buf, buflen);
7858 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7860 ReflectionMethodBuilder rmb;
7861 MonoMethodSignature *sig;
7864 sig = dynamic_method_to_signature (mb);
7866 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7869 * Resolve references.
7871 rmb.nrefs = mb->nrefs;
7872 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7873 for (i = 0; i < mb->nrefs; ++i) {
7874 gpointer ref = resolve_object (mb->module->image,
7875 mono_array_get (mb->refs, MonoObject*, i));
7878 mono_raise_exception (mono_get_exception_type_load (NULL));
7885 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7889 /* ilgen is no longer needed */
7894 * mono_reflection_lookup_dynamic_token:
7896 * Finish the Builder object pointed to by TOKEN and return the corresponding
7897 * runtime structure.
7900 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7902 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7905 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7908 return resolve_object (image, obj);
7912 resolve_object (MonoImage *image, MonoObject *obj)
7914 gpointer result = NULL;
7916 if (strcmp (obj->vtable->klass->name, "String") == 0) {
7917 result = mono_string_intern ((MonoString*)obj);
7920 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7921 MonoReflectionType *tb = (MonoReflectionType*)obj;
7922 result = mono_class_from_mono_type (tb->type);
7925 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7926 result = ((MonoReflectionMethod*)obj)->method;
7929 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7930 result = ((MonoReflectionMethod*)obj)->method;
7933 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7934 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7935 result = mb->mhandle;
7937 /* Type is not yet created */
7938 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7940 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7943 * Hopefully this has been filled in by calling CreateType() on the
7947 * TODO: This won't work if the application finishes another
7948 * TypeBuilder instance instead of this one.
7950 result = mb->mhandle;
7953 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7954 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7956 result = cb->mhandle;
7958 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7960 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7961 result = cb->mhandle;
7964 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7965 result = ((MonoReflectionField*)obj)->field;
7968 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7969 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7970 result = fb->handle;
7973 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7975 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7976 result = fb->handle;
7979 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7980 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7983 klass = tb->type.type->data.klass;
7984 if (klass->wastypebuilder) {
7985 /* Already created */
7989 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7990 result = tb->type.type->data.klass;
7994 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
7995 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
7996 MonoMethodSignature *sig;
7999 if (helper->arguments)
8000 nargs = mono_array_length (helper->arguments);
8004 sig = mono_metadata_signature_alloc (image, nargs);
8005 sig->explicit_this = helper->call_conv & 64;
8006 sig->hasthis = helper->call_conv & 32;
8008 if (helper->call_conv == 0) /* unmanaged */
8009 sig->call_convention = helper->unmanaged_call_conv - 1;
8011 if (helper->call_conv & 0x02)
8012 sig->call_convention = MONO_CALL_VARARG;
8014 sig->call_convention = MONO_CALL_DEFAULT;
8016 sig->param_count = nargs;
8017 /* TODO: Copy type ? */
8018 sig->ret = helper->return_type->type;
8019 for (i = 0; i < nargs; ++i) {
8020 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8021 sig->params [i] = rt->type;
8027 g_print (obj->vtable->klass->name);
8028 g_assert_not_reached ();