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);
1040 ainfo->cached = TRUE;
1044 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1046 /* they are cached, so we don't free them */
1047 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1053 * idx is the table index of the object
1054 * type is one of CUSTOM_ATTR_*
1057 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1059 MonoDynamicTable *table;
1060 MonoReflectionCustomAttr *cattr;
1062 guint32 count, i, token;
1064 char *p = blob_size;
1066 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1069 count = mono_array_length (cattrs);
1070 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1071 table->rows += count;
1072 alloc_table (table, table->rows);
1073 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1074 idx <<= CUSTOM_ATTR_BITS;
1076 for (i = 0; i < count; ++i) {
1077 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1078 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1079 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
1080 type = mono_metadata_token_index (token);
1081 type <<= CUSTOM_ATTR_TYPE_BITS;
1082 switch (mono_metadata_token_table (token)) {
1083 case MONO_TABLE_METHOD:
1084 type |= CUSTOM_ATTR_TYPE_METHODDEF;
1086 case MONO_TABLE_MEMBERREF:
1087 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1090 g_warning ("got wrong token in custom attr");
1093 values [MONO_CUSTOM_ATTR_TYPE] = type;
1095 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1096 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1097 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1098 values += MONO_CUSTOM_ATTR_SIZE;
1104 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
1105 MonoArray *permissions)
1107 MonoDynamicTable *table;
1109 guint32 count, i, idx;
1110 MonoReflectionPermissionSet *perm;
1115 count = mono_array_length (permissions);
1116 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1117 table->rows += count;
1118 alloc_table (table, table->rows);
1120 for (i = 0; i < mono_array_length (permissions); ++i) {
1121 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1123 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1125 idx = mono_metadata_token_index (parent_token);
1126 idx <<= HAS_DECL_SECURITY_BITS;
1127 switch (mono_metadata_token_table (parent_token)) {
1128 case MONO_TABLE_TYPEDEF:
1129 idx |= HAS_DECL_SECURITY_TYPEDEF;
1131 case MONO_TABLE_METHOD:
1132 idx |= HAS_DECL_SECURITY_METHODDEF;
1134 case MONO_TABLE_ASSEMBLY:
1135 idx |= HAS_DECL_SECURITY_ASSEMBLY;
1138 g_assert_not_reached ();
1141 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1142 values [MONO_DECL_SECURITY_PARENT] = idx;
1143 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1150 * Fill in the MethodDef and ParamDef tables for a method.
1151 * This is used for both normal methods and constructors.
1154 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1156 MonoDynamicTable *table;
1161 /* room in this table is already allocated */
1162 table = &assembly->tables [MONO_TABLE_METHOD];
1163 *mb->table_idx = table->next_idx ++;
1164 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1165 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1166 name = mono_string_to_utf8 (mb->name);
1167 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1169 values [MONO_METHOD_FLAGS] = mb->attrs;
1170 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1171 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1172 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1174 table = &assembly->tables [MONO_TABLE_PARAM];
1175 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1177 mono_image_add_decl_security (assembly,
1178 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1182 MonoDynamicTable *mtable;
1185 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1186 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1189 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1190 if (mono_array_get (mb->pinfo, gpointer, i))
1193 table->rows += count;
1194 alloc_table (table, table->rows);
1195 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1196 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1197 MonoReflectionParamBuilder *pb;
1198 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1199 values [MONO_PARAM_FLAGS] = pb->attrs;
1200 values [MONO_PARAM_SEQUENCE] = i;
1201 if (pb->name != NULL) {
1202 name = mono_string_to_utf8 (pb->name);
1203 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1207 values [MONO_PARAM_NAME] = 0;
1208 values += MONO_PARAM_SIZE;
1209 if (pb->marshal_info) {
1211 alloc_table (mtable, mtable->rows);
1212 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1213 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
1214 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1216 pb->table_idx = table->next_idx++;
1223 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1224 MonoReflectionMethodBuilder *mb)
1226 rmb->ilgen = mb->ilgen;
1227 rmb->rtype = mb->rtype;
1228 rmb->parameters = mb->parameters;
1229 rmb->generic_params = mb->generic_params;
1230 rmb->opt_types = NULL;
1231 rmb->pinfo = mb->pinfo;
1232 rmb->attrs = mb->attrs;
1233 rmb->iattrs = mb->iattrs;
1234 rmb->call_conv = mb->call_conv;
1235 rmb->code = mb->code;
1236 rmb->type = mb->type;
1237 rmb->name = mb->name;
1238 rmb->table_idx = &mb->table_idx;
1239 rmb->init_locals = mb->init_locals;
1240 rmb->return_modreq = mb->return_modreq;
1241 rmb->return_modopt = mb->return_modopt;
1242 rmb->param_modreq = mb->param_modreq;
1243 rmb->param_modopt = mb->param_modopt;
1244 rmb->permissions = mb->permissions;
1245 rmb->mhandle = mb->mhandle;
1251 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1252 MonoReflectionCtorBuilder *mb)
1254 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1256 rmb->ilgen = mb->ilgen;
1257 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1258 rmb->parameters = mb->parameters;
1259 rmb->generic_params = NULL;
1260 rmb->opt_types = NULL;
1261 rmb->pinfo = mb->pinfo;
1262 rmb->attrs = mb->attrs;
1263 rmb->iattrs = mb->iattrs;
1264 rmb->call_conv = mb->call_conv;
1266 rmb->type = mb->type;
1267 rmb->name = mono_string_new (mono_domain_get (), name);
1268 rmb->table_idx = &mb->table_idx;
1269 rmb->init_locals = mb->init_locals;
1270 rmb->return_modreq = NULL;
1271 rmb->return_modopt = NULL;
1272 rmb->param_modreq = mb->param_modreq;
1273 rmb->param_modopt = mb->param_modopt;
1274 rmb->permissions = mb->permissions;
1275 rmb->mhandle = mb->mhandle;
1281 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1282 MonoReflectionDynamicMethod *mb)
1284 rmb->ilgen = mb->ilgen;
1285 rmb->rtype = mb->rtype;
1286 rmb->parameters = mb->parameters;
1287 rmb->generic_params = NULL;
1288 rmb->opt_types = NULL;
1290 rmb->attrs = mb->attrs;
1292 rmb->call_conv = mb->call_conv;
1295 rmb->name = mb->name;
1296 rmb->table_idx = NULL;
1297 rmb->init_locals = mb->init_locals;
1298 rmb->return_modreq = NULL;
1299 rmb->return_modopt = NULL;
1300 rmb->param_modreq = NULL;
1301 rmb->param_modopt = NULL;
1302 rmb->permissions = NULL;
1303 rmb->mhandle = mb->mhandle;
1309 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1311 MonoDynamicTable *table;
1314 ReflectionMethodBuilder rmb;
1317 reflection_methodbuilder_from_method_builder (&rmb, mb);
1319 mono_image_basic_method (&rmb, assembly);
1321 if (mb->dll) { /* It's a P/Invoke method */
1323 int charset = mb->charset & 0xf;
1324 int lasterr = mb->charset & 0x40;
1325 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1327 alloc_table (table, table->rows);
1328 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1329 /* map CharSet values to on-disk values */
1331 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1332 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1333 name = mono_string_to_utf8 (mb->dllentry);
1334 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1336 name = mono_string_to_utf8 (mb->dll);
1337 moduleref = string_heap_insert (&assembly->sheap, name);
1339 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1340 table = &assembly->tables [MONO_TABLE_MODULEREF];
1342 alloc_table (table, table->rows);
1343 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1344 values [MONO_IMPLMAP_SCOPE] = table->rows;
1348 if (mb->override_method) {
1349 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1351 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1353 alloc_table (table, table->rows);
1354 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1355 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1356 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
1357 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
1358 switch (mono_metadata_token_table (tok)) {
1359 case MONO_TABLE_MEMBERREF:
1360 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
1362 case MONO_TABLE_METHOD:
1363 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
1366 g_assert_not_reached ();
1368 values [MONO_METHODIMPL_DECLARATION] = tok;
1371 if (mb->generic_params) {
1372 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1373 table->rows += mono_array_length (mb->generic_params);
1374 alloc_table (table, table->rows);
1375 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1376 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1378 mono_image_get_generic_param_info (
1379 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1386 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1388 ReflectionMethodBuilder rmb;
1390 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1392 mono_image_basic_method (&rmb, assembly);
1396 type_get_fully_qualified_name (MonoType *type) {
1397 char *name, *result;
1401 name = mono_type_get_name (type);
1402 klass = my_mono_class_from_mono_type (type);
1403 ta = klass->image->assembly;
1405 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1406 name, ta->aname.name,
1407 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1408 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1409 ta->aname.public_tok_value ? ta->aname.public_tok_value : "null");
1415 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1419 klass = my_mono_class_from_mono_type (type);
1420 ta = klass->image->assembly;
1421 if (ta == ass || klass->image == mono_defaults.corlib)
1422 return mono_type_get_name (type);
1424 return type_get_fully_qualified_name (type);
1428 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1430 char blob_size [64];
1431 char *b = blob_size;
1436 if (!assembly->save)
1439 p = buf = g_malloc (64);
1441 mono_metadata_encode_value (0x06, p, &p);
1442 /* encode custom attributes before the type */
1443 encode_type (assembly, type, p, &p);
1444 g_assert (p-buf < 64);
1445 mono_metadata_encode_value (p-buf, b, &b);
1446 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1452 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1454 char blob_size [64];
1455 char *b = blob_size;
1460 p = buf = g_malloc (64);
1462 mono_metadata_encode_value (0x06, p, &p);
1463 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1464 /* encode custom attributes before the type */
1465 encode_reflection_type (assembly, fb->type, p, &p);
1466 g_assert (p-buf < 64);
1467 mono_metadata_encode_value (p-buf, b, &b);
1468 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1474 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1475 char blob_size [64];
1476 char *b = blob_size;
1479 guint32 idx = 0, len = 0, dummy = 0;
1481 p = buf = g_malloc (64);
1483 *ret_type = MONO_TYPE_CLASS;
1485 box_val = (char*)&dummy;
1487 box_val = ((char*)val) + sizeof (MonoObject);
1488 *ret_type = val->vtable->klass->byval_arg.type;
1491 switch (*ret_type) {
1492 case MONO_TYPE_BOOLEAN:
1497 case MONO_TYPE_CHAR:
1512 case MONO_TYPE_VALUETYPE:
1513 if (val->vtable->klass->enumtype) {
1514 *ret_type = val->vtable->klass->enum_basetype->type;
1517 g_error ("we can't encode valuetypes");
1518 case MONO_TYPE_CLASS:
1520 case MONO_TYPE_STRING: {
1521 MonoString *str = (MonoString*)val;
1522 /* there is no signature */
1523 len = str->length * 2;
1524 mono_metadata_encode_value (len, b, &b);
1525 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1527 char *swapped = g_malloc (2 * mono_string_length (str));
1528 const char *p = (const char*)mono_string_chars (str);
1530 swap_with_size (swapped, p, 2, mono_string_length (str));
1531 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1535 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1542 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1545 /* there is no signature */
1546 mono_metadata_encode_value (len, b, &b);
1547 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1548 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1549 swap_with_size (blob_size, box_val, len, 1);
1550 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1552 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1560 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1561 char blob_size [64];
1562 char *b = blob_size;
1563 char *p, *buf, *str;
1564 guint32 idx, len, bufsize = 256;
1566 p = buf = g_malloc (bufsize);
1568 switch (minfo->type) {
1569 case MONO_NATIVE_BYVALTSTR:
1570 case MONO_NATIVE_BYVALARRAY:
1571 mono_metadata_encode_value (minfo->type, p, &p);
1572 mono_metadata_encode_value (minfo->count, p, &p);
1574 case MONO_NATIVE_LPARRAY:
1575 mono_metadata_encode_value (minfo->type, p, &p);
1576 if (minfo->eltype || (minfo->count > 0)) {
1577 mono_metadata_encode_value (minfo->eltype, p, &p);
1578 if (minfo->count > 0) {
1579 mono_metadata_encode_value (0, p, &p);
1580 mono_metadata_encode_value (minfo->count, p, &p);
1584 case MONO_NATIVE_CUSTOM:
1585 mono_metadata_encode_value (minfo->type, p, &p);
1587 str = mono_string_to_utf8 (minfo->guid);
1589 mono_metadata_encode_value (len, p, &p);
1590 memcpy (p, str, len);
1594 mono_metadata_encode_value (0, p, &p);
1596 if (minfo->marshaltype) {
1597 str = mono_string_to_utf8 (minfo->marshaltype);
1599 mono_metadata_encode_value (len, p, &p);
1600 if (p + len >= buf + bufsize) {
1603 buf = g_realloc (buf, bufsize);
1606 memcpy (p, str, len);
1610 mono_metadata_encode_value (0, p, &p);
1612 if (minfo->marshaltyperef) {
1613 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1615 mono_metadata_encode_value (len, p, &p);
1616 if (p + len >= buf + bufsize) {
1619 buf = g_realloc (buf, bufsize);
1622 memcpy (p, str, len);
1626 mono_metadata_encode_value (0, p, &p);
1628 if (minfo->mcookie) {
1629 str = mono_string_to_utf8 (minfo->mcookie);
1631 mono_metadata_encode_value (len, p, &p);
1632 if (p + len >= buf + bufsize) {
1635 buf = g_realloc (buf, bufsize);
1638 memcpy (p, str, len);
1642 mono_metadata_encode_value (0, p, &p);
1646 mono_metadata_encode_value (minfo->type, p, &p);
1650 mono_metadata_encode_value (len, b, &b);
1651 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1657 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1659 MonoDynamicTable *table;
1663 /* maybe this fixup should be done in the C# code */
1664 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1665 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1666 table = &assembly->tables [MONO_TABLE_FIELD];
1667 fb->table_idx = table->next_idx ++;
1668 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1669 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1670 name = mono_string_to_utf8 (fb->name);
1671 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1673 values [MONO_FIELD_FLAGS] = fb->attrs;
1674 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1676 if (fb->offset != -1) {
1677 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1679 alloc_table (table, table->rows);
1680 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1681 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1682 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1684 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1685 guint32 field_type = 0;
1686 table = &assembly->tables [MONO_TABLE_CONSTANT];
1688 alloc_table (table, table->rows);
1689 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1690 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1691 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1692 values [MONO_CONSTANT_TYPE] = field_type;
1693 values [MONO_CONSTANT_PADDING] = 0;
1695 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1697 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1699 alloc_table (table, table->rows);
1700 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1701 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1703 * We store it in the code section because it's simpler for now.
1706 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1708 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1709 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1711 if (fb->marshal_info) {
1712 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1714 alloc_table (table, table->rows);
1715 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1716 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1717 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1722 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1726 char *b = blob_size;
1727 guint32 nparams = 0;
1728 MonoReflectionMethodBuilder *mb = fb->get_method;
1729 MonoReflectionMethodBuilder *smb = fb->set_method;
1730 guint32 idx, i, size;
1732 if (mb && mb->parameters)
1733 nparams = mono_array_length (mb->parameters);
1734 if (!mb && smb && smb->parameters)
1735 nparams = mono_array_length (smb->parameters) - 1;
1736 size = 24 + nparams * 10;
1737 buf = p = g_malloc (size);
1740 mono_metadata_encode_value (nparams, p, &p);
1742 encode_reflection_type (assembly, mb->rtype, p, &p);
1743 for (i = 0; i < nparams; ++i) {
1744 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1745 encode_reflection_type (assembly, pt, p, &p);
1748 /* the property type is the last param */
1749 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1750 for (i = 0; i < nparams; ++i) {
1751 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1752 encode_reflection_type (assembly, pt, p, &p);
1756 g_assert (p - buf < size);
1757 mono_metadata_encode_value (p-buf, b, &b);
1758 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1764 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1766 MonoDynamicTable *table;
1769 guint num_methods = 0;
1773 * we need to set things in the following tables:
1774 * PROPERTYMAP (info already filled in _get_type_info ())
1775 * PROPERTY (rows already preallocated in _get_type_info ())
1776 * METHOD (method info already done with the generic method code)
1779 table = &assembly->tables [MONO_TABLE_PROPERTY];
1780 pb->table_idx = table->next_idx ++;
1781 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1782 name = mono_string_to_utf8 (pb->name);
1783 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1785 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1786 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1788 /* FIXME: we still don't handle 'other' methods */
1789 if (pb->get_method) num_methods ++;
1790 if (pb->set_method) num_methods ++;
1792 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1793 table->rows += num_methods;
1794 alloc_table (table, table->rows);
1796 if (pb->get_method) {
1797 semaidx = table->next_idx ++;
1798 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1799 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1800 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1801 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1803 if (pb->set_method) {
1804 semaidx = table->next_idx ++;
1805 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1806 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1807 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1808 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1813 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1815 MonoDynamicTable *table;
1818 guint num_methods = 0;
1822 * we need to set things in the following tables:
1823 * EVENTMAP (info already filled in _get_type_info ())
1824 * EVENT (rows already preallocated in _get_type_info ())
1825 * METHOD (method info already done with the generic method code)
1828 table = &assembly->tables [MONO_TABLE_EVENT];
1829 eb->table_idx = table->next_idx ++;
1830 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1831 name = mono_string_to_utf8 (eb->name);
1832 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1834 values [MONO_EVENT_FLAGS] = eb->attrs;
1835 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1838 * FIXME: we still don't handle 'other' methods
1840 if (eb->add_method) num_methods ++;
1841 if (eb->remove_method) num_methods ++;
1842 if (eb->raise_method) num_methods ++;
1844 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1845 table->rows += num_methods;
1846 alloc_table (table, table->rows);
1848 if (eb->add_method) {
1849 semaidx = table->next_idx ++;
1850 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1851 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1852 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1853 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1855 if (eb->remove_method) {
1856 semaidx = table->next_idx ++;
1857 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1858 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1859 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1860 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1862 if (eb->raise_method) {
1863 semaidx = table->next_idx ++;
1864 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1865 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1866 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1867 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1872 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1874 static MonoClass *NewConstraintAttr;
1875 static MonoMethod *NewConstraintAttr_ctor;
1876 MonoDynamicTable *table;
1878 guint32 token, type;
1879 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1882 if (!NewConstraintAttr)
1883 NewConstraintAttr = mono_class_from_name (
1884 mono_defaults.corlib, "System.Runtime.CompilerServices",
1885 "NewConstraintAttribute");
1886 g_assert (NewConstraintAttr);
1888 if (!NewConstraintAttr_ctor) {
1891 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1892 MonoMethod *m = NewConstraintAttr->methods [i];
1894 if (strcmp (m->name, ".ctor"))
1897 NewConstraintAttr_ctor = m;
1901 g_assert (NewConstraintAttr_ctor);
1904 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1906 alloc_table (table, table->rows);
1908 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1909 owner <<= CUSTOM_ATTR_BITS;
1910 owner |= CUSTOM_ATTR_GENERICPAR;
1911 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1913 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1915 type = mono_metadata_token_index (token);
1916 type <<= CUSTOM_ATTR_TYPE_BITS;
1917 switch (mono_metadata_token_table (token)) {
1918 case MONO_TABLE_METHOD:
1919 type |= CUSTOM_ATTR_TYPE_METHODDEF;
1921 case MONO_TABLE_MEMBERREF:
1922 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1925 g_warning ("got wrong token in custom attr");
1928 values [MONO_CUSTOM_ATTR_TYPE] = type;
1930 buf = p = g_malloc (1);
1931 mono_metadata_encode_value (4, p, &p);
1932 g_assert (p-buf == 1);
1934 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1936 values += MONO_CUSTOM_ATTR_SIZE;
1941 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1943 MonoDynamicTable *table;
1944 guint32 num_constraints, i;
1948 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1949 num_constraints = gparam->iface_constraints ?
1950 mono_array_length (gparam->iface_constraints) : 0;
1951 table->rows += num_constraints;
1952 if (gparam->base_type)
1954 alloc_table (table, table->rows);
1956 if (gparam->base_type) {
1957 table_idx = table->next_idx ++;
1958 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1960 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1961 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1962 assembly, gparam->base_type->type);
1965 for (i = 0; i < num_constraints; i++) {
1966 MonoReflectionType *constraint = mono_array_get (
1967 gparam->iface_constraints, gpointer, i);
1969 table_idx = table->next_idx ++;
1970 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1972 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1973 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1974 assembly, constraint->type);
1977 if (gparam->has_ctor_constraint)
1978 encode_new_constraint (assembly, owner);
1982 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1984 MonoDynamicTable *table;
1985 MonoGenericParam *param;
1989 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1990 table_idx = table->next_idx ++;
1991 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
1993 param = gparam->type.type->data.generic_param;
1995 values [MONO_GENERICPARAM_OWNER] = owner;
1996 if (gparam->has_value_type)
1997 values [MONO_GENERICPARAM_FLAGS] = 0x18;
1998 else if (gparam->has_reference_type)
1999 values [MONO_GENERICPARAM_FLAGS] = 0x04;
2001 values [MONO_GENERICPARAM_FLAGS] = 0x00;
2002 values [MONO_GENERICPARAM_NUMBER] = param->num;
2003 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2004 values [MONO_GENERICPARAM_KIND] = 0;
2006 encode_constraints (gparam, table_idx, assembly);
2010 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2012 MonoDynamicTable *table;
2015 guint32 cols [MONO_ASSEMBLY_SIZE];
2019 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2022 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2023 table = &assembly->tables [MONO_TABLE_MODULEREF];
2024 token = table->next_idx ++;
2026 alloc_table (table, table->rows);
2027 values = table->values + token * MONO_MODULEREF_SIZE;
2028 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2030 token <<= RESOLTION_SCOPE_BITS;
2031 token |= RESOLTION_SCOPE_MODULEREF;
2032 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2037 if (image->assembly->dynamic)
2039 memset (cols, 0, sizeof (cols));
2041 /* image->assembly->image is the manifest module */
2042 image = image->assembly->image;
2043 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2046 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2047 token = table->next_idx ++;
2049 alloc_table (table, table->rows);
2050 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2051 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2052 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2053 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2054 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2055 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2056 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2057 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2058 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2060 if (strcmp ("", image->assembly->aname.culture)) {
2061 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2062 image->assembly->aname.culture);
2065 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2066 guchar pubtoken [9];
2068 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2069 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2071 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2073 token <<= RESOLTION_SCOPE_BITS;
2074 token |= RESOLTION_SCOPE_ASSEMBLYREF;
2075 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2080 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2082 MonoDynamicTable *table;
2088 char *b = blob_size;
2090 switch (type->type) {
2091 case MONO_TYPE_FNPTR:
2093 case MONO_TYPE_SZARRAY:
2094 case MONO_TYPE_ARRAY:
2096 case MONO_TYPE_MVAR:
2097 case MONO_TYPE_GENERICINST:
2098 encode_type (assembly, type, p, &p);
2100 case MONO_TYPE_CLASS:
2101 case MONO_TYPE_VALUETYPE: {
2102 MonoClass *k = mono_class_from_mono_type (type);
2103 if (!k || !k->generic_inst)
2105 encode_generic_inst (assembly, k->generic_inst, p, &p);
2112 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2113 if (assembly->save) {
2114 g_assert (p-sig < 128);
2115 mono_metadata_encode_value (p-sig, b, &b);
2116 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2117 alloc_table (table, table->rows + 1);
2118 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2119 values [MONO_TYPESPEC_SIGNATURE] = token;
2122 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2123 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2129 * Despite the name, we handle also TypeSpec (with the above helper).
2132 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2134 MonoDynamicTable *table;
2136 guint32 token, scope, enclosing;
2139 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2142 token = create_typespec (assembly, type);
2145 klass = my_mono_class_from_mono_type (type);
2147 klass = mono_class_from_mono_type (type);
2150 * If it's in the same module and not a generic type parameter:
2152 if ((klass->image == &assembly->image) &&
2153 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2154 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2155 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
2156 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2160 if (klass->nested_in) {
2161 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2162 /* get the typeref idx of the enclosing type */
2163 enclosing >>= TYPEDEFORREF_BITS;
2164 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
2166 scope = resolution_scope_from_image (assembly, klass->image);
2168 table = &assembly->tables [MONO_TABLE_TYPEREF];
2169 if (assembly->save) {
2170 alloc_table (table, table->rows + 1);
2171 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2172 values [MONO_TYPEREF_SCOPE] = scope;
2173 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2174 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2176 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
2177 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2179 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2184 * Insert a memberef row into the metadata: the token that point to the memberref
2185 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2186 * mono_image_get_fieldref_token()).
2187 * The sig param is an index to an already built signature.
2190 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2192 MonoDynamicTable *table;
2194 guint32 token, pclass;
2197 parent = mono_image_typedef_or_ref (assembly, type);
2198 switch (parent & TYPEDEFORREF_MASK) {
2199 case TYPEDEFORREF_TYPEREF:
2200 pclass = MEMBERREF_PARENT_TYPEREF;
2202 case TYPEDEFORREF_TYPESPEC:
2203 pclass = MEMBERREF_PARENT_TYPESPEC;
2205 case TYPEDEFORREF_TYPEDEF:
2206 pclass = MEMBERREF_PARENT_TYPEDEF;
2209 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2212 /* extract the index */
2213 parent >>= TYPEDEFORREF_BITS;
2215 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2217 if (assembly->save) {
2218 alloc_table (table, table->rows + 1);
2219 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2220 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2221 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2222 values [MONO_MEMBERREF_SIGNATURE] = sig;
2225 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2232 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2236 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2239 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2240 method->name, method_encode_signature (assembly, method->signature));
2241 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2246 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2247 const gchar *name, guint32 sig)
2249 MonoDynamicTable *table;
2250 guint32 parent, token;
2253 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2255 if (assembly->save) {
2256 alloc_table (table, table->rows + 1);
2257 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2258 values [MONO_MEMBERREF_CLASS] = original;
2259 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2260 values [MONO_MEMBERREF_SIGNATURE] = sig;
2263 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2270 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2273 ReflectionMethodBuilder rmb;
2275 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2279 reflection_methodbuilder_from_method_builder (&rmb, mb);
2281 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2282 mono_string_to_utf8 (rmb.name),
2283 method_builder_encode_signature (assembly, &rmb));
2284 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2289 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2292 ReflectionMethodBuilder rmb;
2294 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2298 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2300 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2301 mono_string_to_utf8 (rmb.name),
2302 method_builder_encode_signature (assembly, &rmb));
2303 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2308 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2313 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2316 g_assert (f->field->parent);
2317 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2318 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2319 f->field->name, fieldref_encode_signature (assembly, type));
2320 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2325 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2330 guint32 nparams = gmethod->mtype_argc;
2331 guint32 size = 10 + nparams * 10;
2334 char *b = blob_size;
2336 if (!assembly->save)
2339 p = buf = g_malloc (size);
2341 * FIXME: vararg, explicit_this, differenc call_conv values...
2343 mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2344 mono_metadata_encode_value (nparams, p, &p);
2346 for (i = 0; i < nparams; i++)
2347 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2350 g_assert (p - buf < size);
2351 mono_metadata_encode_value (p-buf, b, &b);
2352 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2358 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2360 MonoDynamicTable *table;
2362 guint32 token, mtoken = 0, sig;
2363 MonoMethodInflated *imethod;
2364 MonoMethod *declaring;
2366 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2368 g_assert (method->signature->is_inflated);
2369 imethod = (MonoMethodInflated *) method;
2370 declaring = imethod->declaring;
2372 sig = method_encode_signature (assembly, declaring->signature);
2373 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2374 declaring->name, sig);
2376 if (!declaring->signature->generic_param_count)
2379 switch (mono_metadata_token_table (mtoken)) {
2380 case MONO_TABLE_MEMBERREF:
2381 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2383 case MONO_TABLE_METHOD:
2384 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2387 g_assert_not_reached ();
2390 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2392 if (assembly->save) {
2393 alloc_table (table, table->rows + 1);
2394 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2395 values [MONO_METHODSPEC_METHOD] = mtoken;
2396 values [MONO_METHODSPEC_SIGNATURE] = sig;
2399 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2406 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2408 MonoMethodInflated *imethod;
2411 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2415 g_assert (m->signature->is_inflated);
2416 imethod = (MonoMethodInflated *) m;
2418 if (imethod->declaring->signature->generic_param_count)
2419 token = method_encode_methodspec (assembly, m);
2421 guint32 sig = method_encode_signature (
2422 assembly, imethod->declaring->signature);
2423 token = mono_image_get_memberref_token (
2424 assembly, &m->klass->byval_arg, m->name, sig);
2427 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2432 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2434 MonoDynamicTable *table;
2441 char *b = blob_size;
2445 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2446 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2447 * Because of this, we must not insert it into the `typeref' hash table.
2450 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2454 g_assert (tb->generic_params);
2455 klass = mono_class_from_mono_type (tb->type.type);
2457 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2458 encode_type (assembly, &klass->byval_arg, p, &p);
2460 count = mono_array_length (tb->generic_params);
2461 mono_metadata_encode_value (count, p, &p);
2462 for (i = 0; i < count; i++) {
2463 MonoReflectionGenericParam *gparam;
2465 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2467 encode_type (assembly, gparam->type.type, p, &p);
2470 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2471 if (assembly->save) {
2472 g_assert (p-sig < 128);
2473 mono_metadata_encode_value (p-sig, b, &b);
2474 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2475 alloc_table (table, table->rows + 1);
2476 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2477 values [MONO_TYPESPEC_SIGNATURE] = token;
2480 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2481 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2487 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2489 MonoDynamicTable *table;
2492 guint32 token, pclass, parent, sig;
2495 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2499 klass = mono_class_from_mono_type (fb->typeb->type);
2500 name = mono_string_to_utf8 (fb->name);
2502 sig = fieldref_encode_signature (assembly, fb->type->type);
2504 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2505 g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2507 pclass = MEMBERREF_PARENT_TYPESPEC;
2508 parent >>= TYPEDEFORREF_BITS;
2510 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2512 if (assembly->save) {
2513 alloc_table (table, table->rows + 1);
2514 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2515 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2516 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2517 values [MONO_MEMBERREF_SIGNATURE] = sig;
2520 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2522 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2527 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2535 char *b = blob_size;
2537 if (!assembly->save)
2541 g_assert (helper->type == 2);
2543 if (helper->arguments)
2544 nargs = mono_array_length (helper->arguments);
2548 size = 10 + (nargs * 10);
2550 p = buf = g_malloc (size);
2552 /* Encode calling convention */
2553 /* Change Any to Standard */
2554 if ((helper->call_conv & 0x03) == 0x03)
2555 helper->call_conv = 0x01;
2556 /* explicit_this implies has_this */
2557 if (helper->call_conv & 0x40)
2558 helper->call_conv &= 0x20;
2560 if (helper->call_conv == 0) /* Unmanaged */
2561 *p = helper->unmanaged_call_conv - 1;
2564 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2565 if (helper->call_conv & 0x02) /* varargs */
2570 mono_metadata_encode_value (nargs, p, &p);
2571 encode_reflection_type (assembly, helper->return_type, p, &p);
2572 for (i = 0; i < nargs; ++i) {
2573 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2574 encode_reflection_type (assembly, pt, p, &p);
2577 g_assert (p - buf < size);
2578 mono_metadata_encode_value (p-buf, b, &b);
2579 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2586 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2589 MonoDynamicTable *table;
2592 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2593 idx = table->next_idx ++;
2595 alloc_table (table, table->rows);
2596 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2598 values [MONO_STAND_ALONE_SIGNATURE] =
2599 mono_reflection_encode_sighelper (assembly, helper);
2605 reflection_cc_to_file (int call_conv) {
2606 switch (call_conv & 0x3) {
2608 case 1: return MONO_CALL_DEFAULT;
2609 case 2: return MONO_CALL_VARARG;
2611 g_assert_not_reached ();
2618 MonoMethodSignature *sig;
2624 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2629 MonoMethodSignature *sig;
2632 name = mono_string_to_utf8 (m->name);
2633 nparams = mono_array_length (m->parameters);
2634 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2636 sig->sentinelpos = -1;
2637 sig->call_convention = reflection_cc_to_file (m->call_conv);
2638 sig->param_count = nparams;
2639 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2640 for (i = 0; i < nparams; ++i) {
2641 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2642 sig->params [i] = t->type;
2645 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2647 if (strcmp (name, am->name) == 0 &&
2648 mono_metadata_type_equal (am->parent, m->parent->type) &&
2649 mono_metadata_signature_equal (am->sig, sig)) {
2652 m->table_idx = am->token & 0xffffff;
2656 am = g_new0 (ArrayMethod, 1);
2659 am->parent = m->parent->type;
2660 am->token = mono_image_get_memberref_token (assembly, am->parent,
2661 name, method_encode_signature (assembly, sig));
2662 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2663 m->table_idx = am->token & 0xffffff;
2668 * Insert into the metadata tables all the info about the TypeBuilder tb.
2669 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2672 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2674 MonoDynamicTable *table;
2676 int i, is_object = 0, is_system = 0;
2679 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2680 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2681 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2682 n = mono_string_to_utf8 (tb->name);
2683 if (strcmp (n, "Object") == 0)
2685 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2687 n = mono_string_to_utf8 (tb->nspace);
2688 if (strcmp (n, "System") == 0)
2690 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2692 if (tb->parent && !(is_system && is_object) &&
2693 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2694 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2696 values [MONO_TYPEDEF_EXTENDS] = 0;
2697 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2698 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2701 * if we have explicitlayout or sequentiallayouts, output data in the
2702 * ClassLayout table.
2704 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2705 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2707 alloc_table (table, table->rows);
2708 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2709 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2710 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2711 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2714 /* handle interfaces */
2715 if (tb->interfaces) {
2716 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2718 table->rows += mono_array_length (tb->interfaces);
2719 alloc_table (table, table->rows);
2720 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2721 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2722 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2723 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2724 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2725 values += MONO_INTERFACEIMPL_SIZE;
2729 /* handle generic parameters */
2730 if (tb->generic_params) {
2731 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2732 table->rows += mono_array_length (tb->generic_params);
2733 alloc_table (table, table->rows);
2734 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2735 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2737 mono_image_get_generic_param_info (
2738 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2744 table = &assembly->tables [MONO_TABLE_FIELD];
2745 table->rows += tb->num_fields;
2746 alloc_table (table, table->rows);
2747 for (i = 0; i < tb->num_fields; ++i)
2748 mono_image_get_field_info (
2749 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2752 /* handle constructors */
2754 table = &assembly->tables [MONO_TABLE_METHOD];
2755 table->rows += mono_array_length (tb->ctors);
2756 alloc_table (table, table->rows);
2757 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2758 mono_image_get_ctor_info (domain,
2759 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2762 /* handle methods */
2764 table = &assembly->tables [MONO_TABLE_METHOD];
2765 table->rows += tb->num_methods;
2766 alloc_table (table, table->rows);
2767 for (i = 0; i < tb->num_methods; ++i)
2768 mono_image_get_method_info (
2769 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2772 /* Do the same with properties etc.. */
2773 if (tb->events && mono_array_length (tb->events)) {
2774 table = &assembly->tables [MONO_TABLE_EVENT];
2775 table->rows += mono_array_length (tb->events);
2776 alloc_table (table, table->rows);
2777 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2779 alloc_table (table, table->rows);
2780 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2781 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2782 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2783 for (i = 0; i < mono_array_length (tb->events); ++i)
2784 mono_image_get_event_info (
2785 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2787 if (tb->properties && mono_array_length (tb->properties)) {
2788 table = &assembly->tables [MONO_TABLE_PROPERTY];
2789 table->rows += mono_array_length (tb->properties);
2790 alloc_table (table, table->rows);
2791 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2793 alloc_table (table, table->rows);
2794 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2795 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2796 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2797 for (i = 0; i < mono_array_length (tb->properties); ++i)
2798 mono_image_get_property_info (
2799 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2802 mono_image_add_decl_security (assembly,
2803 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2807 MonoDynamicTable *ntable;
2809 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2810 ntable->rows += mono_array_length (tb->subtypes);
2811 alloc_table (ntable, ntable->rows);
2812 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2814 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2815 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2817 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2818 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2819 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2820 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2821 mono_string_to_utf8 (tb->name), tb->table_idx,
2822 ntable->next_idx, ntable->rows);*/
2823 values += MONO_NESTED_CLASS_SIZE;
2830 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2834 g_ptr_array_add (types, type);
2836 if (!type->subtypes)
2839 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2840 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2841 collect_types (types, subtype);
2846 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2847 MonoReflectionTypeBuilder **type2)
2849 if ((*type1)->table_idx < (*type2)->table_idx)
2852 if ((*type1)->table_idx > (*type2)->table_idx)
2859 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2864 for (i = 0; i < mono_array_length (pinfo); ++i) {
2865 MonoReflectionParamBuilder *pb;
2866 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2869 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2874 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2877 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2879 for (i = 0; i < tb->num_fields; ++i) {
2880 MonoReflectionFieldBuilder* fb;
2881 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2882 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2886 for (i = 0; i < mono_array_length (tb->events); ++i) {
2887 MonoReflectionEventBuilder* eb;
2888 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2889 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2892 if (tb->properties) {
2893 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2894 MonoReflectionPropertyBuilder* pb;
2895 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2896 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2900 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2901 MonoReflectionCtorBuilder* cb;
2902 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2903 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2904 params_add_cattrs (assembly, cb->pinfo);
2909 for (i = 0; i < tb->num_methods; ++i) {
2910 MonoReflectionMethodBuilder* mb;
2911 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2912 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2913 params_add_cattrs (assembly, mb->pinfo);
2918 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2919 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2924 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2927 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2929 /* no types in the module */
2933 for (i = 0; i < mb->num_types; ++i)
2934 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2938 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2939 MonoDynamicImage *assembly)
2941 MonoDynamicTable *table;
2945 char *b = blob_size;
2948 table = &assembly->tables [MONO_TABLE_FILE];
2950 alloc_table (table, table->rows);
2951 values = table->values + table->next_idx * MONO_FILE_SIZE;
2952 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2953 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2954 if (module->image->dynamic) {
2955 /* This depends on the fact that the main module is emitted last */
2956 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2957 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2961 path = g_strdup (module->image->name);
2963 mono_sha1_get_digest_from_file (path, hash);
2966 mono_metadata_encode_value (20, b, &b);
2967 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2968 mono_image_add_stream_data (&assembly->blob, hash, 20);
2973 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2975 MonoDynamicTable *table;
2979 table = &assembly->tables [MONO_TABLE_MODULE];
2980 mb->table_idx = table->next_idx ++;
2981 name = mono_string_to_utf8 (mb->module.name);
2982 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2984 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2987 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2988 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2989 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2993 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
2994 guint32 module_index, guint32 parent_index,
2995 MonoDynamicImage *assembly)
2997 MonoDynamicTable *table;
3001 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3002 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3005 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3007 alloc_table (table, table->rows);
3008 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3010 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3011 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3012 if (klass->nested_in)
3013 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
3015 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
3016 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3017 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3019 res = table->next_idx;
3023 /* Emit nested types */
3024 if (klass->nested_classes) {
3027 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3028 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3035 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3036 guint32 module_index, guint32 parent_index,
3037 MonoDynamicImage *assembly)
3042 klass = mono_class_from_mono_type (tb->type.type);
3044 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3046 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3047 parent_index, assembly);
3051 * We need to do this ourselves since klass->nested_classes is not set up.
3054 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3055 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3060 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3061 guint32 module_index,
3062 MonoDynamicImage *assembly)
3064 MonoImage *image = module->image;
3068 t = &image->tables [MONO_TABLE_TYPEDEF];
3070 for (i = 0; i < t->rows; ++i) {
3071 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3073 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3074 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3078 #define align_pointer(base,p)\
3080 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3082 (p) += 4 - (__diff & 3);\
3086 compare_semantics (const void *a, const void *b)
3088 const guint32 *a_values = a;
3089 const guint32 *b_values = b;
3090 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3093 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3097 compare_custom_attrs (const void *a, const void *b)
3099 const guint32 *a_values = a;
3100 const guint32 *b_values = b;
3102 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3106 compare_field_marshal (const void *a, const void *b)
3108 const guint32 *a_values = a;
3109 const guint32 *b_values = b;
3111 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3115 compare_nested (const void *a, const void *b)
3117 const guint32 *a_values = a;
3118 const guint32 *b_values = b;
3120 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3124 * build_compressed_metadata() fills in the blob of data that represents the
3125 * raw metadata as it will be saved in the PE file. The five streams are output
3126 * and the metadata tables are comnpressed from the guint32 array representation,
3127 * to the compressed on-disk format.
3130 build_compressed_metadata (MonoDynamicImage *assembly)
3132 MonoDynamicTable *table;
3134 guint64 valid_mask = 0;
3135 guint64 sorted_mask;
3136 guint32 heapt_size = 0;
3137 guint32 meta_size = 256; /* allow for header and other stuff */
3138 guint32 table_offset;
3139 guint32 ntables = 0;
3148 MonoDynamicStream *stream;
3151 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3152 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3153 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3154 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3155 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3157 /* tables that are sorted */
3158 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3159 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3160 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3161 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3162 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3163 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
3165 /* Compute table sizes */
3166 /* the MonoImage has already been created in mono_image_basic_init() */
3167 meta = &assembly->image;
3169 /* Setup the info used by compute_sizes () */
3170 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3171 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3172 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3174 meta_size += assembly->blob.index;
3175 meta_size += assembly->guid.index;
3176 meta_size += assembly->sheap.index;
3177 meta_size += assembly->us.index;
3179 for (i=0; i < 64; ++i)
3180 meta->tables [i].rows = assembly->tables [i].rows;
3182 for (i = 0; i < 64; i++){
3183 if (meta->tables [i].rows == 0)
3185 valid_mask |= (guint64)1 << i;
3187 meta->tables [i].row_size = mono_metadata_compute_size (
3188 meta, i, &meta->tables [i].size_bitfield);
3189 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3191 heapt_size += 24; /* #~ header size */
3192 heapt_size += ntables * 4;
3193 meta_size += heapt_size;
3194 meta->raw_metadata = g_malloc0 (meta_size);
3195 p = meta->raw_metadata;
3196 /* the metadata signature */
3197 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3198 /* version numbers and 4 bytes reserved */
3199 int16val = (guint16*)p;
3200 *int16val++ = GUINT16_TO_LE (1);
3201 *int16val = GUINT16_TO_LE (1);
3203 /* version string */
3204 int32val = (guint32*)p;
3205 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3207 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3208 p += GUINT32_FROM_LE (*int32val);
3209 align_pointer (meta->raw_metadata, p);
3210 int16val = (guint16*)p;
3211 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3212 *int16val = GUINT16_TO_LE (5); /* number of streams */
3216 * write the stream info.
3218 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3219 table_offset += 3; table_offset &= ~3;
3221 assembly->tstream.index = heapt_size;
3222 for (i = 0; i < 5; ++i) {
3223 int32val = (guint32*)p;
3224 stream_desc [i].stream->offset = table_offset;
3225 *int32val++ = GUINT32_TO_LE (table_offset);
3226 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3227 table_offset += GUINT32_FROM_LE (*int32val);
3228 table_offset += 3; table_offset &= ~3;
3230 strcpy (p, stream_desc [i].name);
3231 p += strlen (stream_desc [i].name) + 1;
3232 align_pointer (meta->raw_metadata, p);
3235 * now copy the data, the table stream header and contents goes first.
3237 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3238 p = meta->raw_metadata + assembly->tstream.offset;
3239 int32val = (guint32*)p;
3240 *int32val = GUINT32_TO_LE (0); /* reserved */
3243 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3244 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3245 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3246 *p++ = 1; /* version */
3249 *p++ = 1; /* version */
3253 if (meta->idx_string_wide)
3255 if (meta->idx_guid_wide)
3257 if (meta->idx_blob_wide)
3260 *p++ = 0; /* reserved */
3261 int64val = (guint64*)p;
3262 *int64val++ = GUINT64_TO_LE (valid_mask);
3263 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3265 int32val = (guint32*)p;
3266 for (i = 0; i < 64; i++){
3267 if (meta->tables [i].rows == 0)
3269 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3271 p = (unsigned char*)int32val;
3273 /* sort the tables that still need sorting */
3274 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3276 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3277 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3279 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3280 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3282 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3283 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3285 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3287 /* compress the tables */
3288 for (i = 0; i < 64; i++){
3291 guint32 bitfield = meta->tables [i].size_bitfield;
3292 if (!meta->tables [i].rows)
3294 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3295 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3296 meta->tables [i].base = p;
3297 for (row = 1; row <= meta->tables [i].rows; ++row) {
3298 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3299 for (col = 0; col < assembly->tables [i].columns; ++col) {
3300 switch (mono_metadata_table_size (bitfield, col)) {
3302 *p++ = values [col];
3305 *p++ = values [col] & 0xff;
3306 *p++ = (values [col] >> 8) & 0xff;
3309 *p++ = values [col] & 0xff;
3310 *p++ = (values [col] >> 8) & 0xff;
3311 *p++ = (values [col] >> 16) & 0xff;
3312 *p++ = (values [col] >> 24) & 0xff;
3315 g_assert_not_reached ();
3319 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3322 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3323 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3324 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3325 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3326 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3328 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3332 * Some tables in metadata need to be sorted according to some criteria, but
3333 * when methods and fields are first created with reflection, they may be assigned a token
3334 * that doesn't correspond to the final token they will get assigned after the sorting.
3335 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3336 * with the reflection objects that represent them. Once all the tables are set up, the
3337 * reflection objects will contains the correct table index. fixup_method() will fixup the
3338 * tokens for the method with ILGenerator @ilgen.
3341 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3342 guint32 code_idx = GPOINTER_TO_UINT (value);
3343 MonoReflectionILTokenInfo *iltoken;
3344 MonoReflectionFieldBuilder *field;
3345 MonoReflectionCtorBuilder *ctor;
3346 MonoReflectionMethodBuilder *method;
3347 MonoReflectionTypeBuilder *tb;
3348 MonoReflectionArrayMethod *am;
3350 unsigned char *target;
3352 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3353 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3354 target = assembly->code.data + code_idx + iltoken->code_pos;
3355 switch (target [3]) {
3356 case MONO_TABLE_FIELD:
3357 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3358 field = (MonoReflectionFieldBuilder *)iltoken->member;
3359 idx = field->table_idx;
3360 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3361 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3362 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3364 g_assert_not_reached ();
3367 case MONO_TABLE_METHOD:
3368 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3369 method = (MonoReflectionMethodBuilder *)iltoken->member;
3370 idx = method->table_idx;
3371 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3372 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3373 idx = ctor->table_idx;
3374 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3375 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3376 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3377 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3379 g_assert_not_reached ();
3382 case MONO_TABLE_TYPEDEF:
3383 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3384 g_assert_not_reached ();
3385 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3386 idx = tb->table_idx;
3388 case MONO_TABLE_MEMBERREF:
3389 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3390 am = (MonoReflectionArrayMethod*)iltoken->member;
3391 idx = am->table_idx;
3392 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3393 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3394 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3395 g_assert (m->klass->generic_inst);
3397 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3399 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3400 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3401 g_assert (f->generic_info);
3403 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3406 g_assert_not_reached ();
3409 case MONO_TABLE_METHODSPEC:
3410 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3411 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3412 g_assert (m->signature->generic_param_count);
3415 g_assert_not_reached ();
3419 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3421 target [0] = idx & 0xff;
3422 target [1] = (idx >> 8) & 0xff;
3423 target [2] = (idx >> 16) & 0xff;
3430 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3431 * value is not known when the table is emitted.
3434 fixup_cattrs (MonoDynamicImage *assembly)
3436 MonoDynamicTable *table;
3438 guint32 type, i, idx, token;
3441 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3443 for (i = 0; i < table->rows; ++i) {
3444 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3446 type = values [MONO_CUSTOM_ATTR_TYPE];
3447 if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
3448 idx = type >> CUSTOM_ATTR_TYPE_BITS;
3449 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3450 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3453 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3454 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3455 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3456 values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
3463 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3465 MonoDynamicTable *table;
3469 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3471 alloc_table (table, table->rows);
3472 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3473 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3474 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3475 name = mono_string_to_utf8 (rsrc->name);
3476 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3478 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3483 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3485 MonoDynamicTable *table;
3489 char *b = blob_size;
3491 guint32 idx, offset;
3493 if (rsrc->filename) {
3494 name = mono_string_to_utf8 (rsrc->filename);
3495 sname = g_path_get_basename (name);
3497 table = &assembly->tables [MONO_TABLE_FILE];
3499 alloc_table (table, table->rows);
3500 values = table->values + table->next_idx * MONO_FILE_SIZE;
3501 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3502 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3505 mono_sha1_get_digest_from_file (name, hash);
3506 mono_metadata_encode_value (20, b, &b);
3507 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3508 mono_image_add_stream_data (&assembly->blob, hash, 20);
3510 idx = table->next_idx++;
3512 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3515 offset = mono_array_length (rsrc->data);
3516 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3517 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3518 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3519 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3523 * The entry should be emitted into the MANIFESTRESOURCE table of
3524 * the main module, but that needs to reference the FILE table
3525 * which isn't emitted yet.
3532 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3536 set_version_from_string (MonoString *version, guint32 *values)
3538 gchar *ver, *p, *str;
3541 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3542 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3543 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3544 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3547 ver = str = mono_string_to_utf8 (version);
3548 for (i = 0; i < 4; ++i) {
3549 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3555 /* handle Revision and Build */
3565 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3569 char *b = blob_size;
3574 len = mono_array_length (pkey);
3575 mono_metadata_encode_value (len, b, &b);
3576 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3577 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3579 /* need to get the actual value from the key type... */
3580 assembly->strong_name_size = 128;
3581 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3587 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3589 MonoDynamicTable *table;
3590 MonoDynamicImage *assembly;
3591 MonoReflectionAssemblyBuilder *assemblyb;
3596 guint32 module_index;
3598 assemblyb = moduleb->assemblyb;
3599 assembly = moduleb->dynamic_image;
3600 domain = mono_object_domain (assemblyb);
3602 /* Emit ASSEMBLY table */
3603 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3604 alloc_table (table, 1);
3605 values = table->values + MONO_ASSEMBLY_SIZE;
3606 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3607 name = mono_string_to_utf8 (assemblyb->name);
3608 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3610 if (assemblyb->culture) {
3611 name = mono_string_to_utf8 (assemblyb->culture);
3612 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3615 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3617 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3618 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3619 set_version_from_string (assemblyb->version, values);
3621 /* Emit FILE + EXPORTED_TYPE table */
3623 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3625 MonoReflectionModuleBuilder *file_module =
3626 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3627 if (file_module != moduleb) {
3628 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3630 if (file_module->types) {
3631 for (j = 0; j < file_module->num_types; ++j) {
3632 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3633 mono_image_fill_export_table (domain, tb, module_index, 0,
3639 if (assemblyb->loaded_modules) {
3640 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3641 MonoReflectionModule *file_module =
3642 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3643 mono_image_fill_file_table (domain, file_module, assembly);
3645 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3649 /* Emit MANIFESTRESOURCE table */
3651 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3653 MonoReflectionModuleBuilder *file_module =
3654 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3655 /* The table for the main module is emitted later */
3656 if (file_module != moduleb) {
3658 if (file_module->resources) {
3659 int len = mono_array_length (file_module->resources);
3660 for (j = 0; j < len; ++j) {
3661 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3662 assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
3670 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3671 * for the modulebuilder @moduleb.
3672 * At the end of the process, method and field tokens are fixed up and the
3673 * on-disk compressed metadata representation is created.
3676 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3678 MonoDynamicTable *table;
3679 MonoDynamicImage *assembly;
3680 MonoReflectionAssemblyBuilder *assemblyb;
3685 assemblyb = moduleb->assemblyb;
3686 assembly = moduleb->dynamic_image;
3687 domain = mono_object_domain (assemblyb);
3689 if (assembly->text_rva)
3692 assembly->text_rva = START_TEXT_RVA;
3694 if (moduleb->is_main) {
3695 mono_image_emit_manifest (moduleb);
3698 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3699 table->rows = 1; /* .<Module> */
3701 alloc_table (table, table->rows);
3703 * Set the first entry.
3705 values = table->values + table->columns;
3706 values [MONO_TYPEDEF_FLAGS] = 0;
3707 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3708 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3709 values [MONO_TYPEDEF_EXTENDS] = 0;
3710 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3711 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3714 * handle global methods
3715 * FIXME: test what to do when global methods are defined in multiple modules.
3717 if (moduleb->global_methods) {
3718 table = &assembly->tables [MONO_TABLE_METHOD];
3719 table->rows += mono_array_length (moduleb->global_methods);
3720 alloc_table (table, table->rows);
3721 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3722 mono_image_get_method_info (
3723 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3725 if (moduleb->global_fields) {
3726 table = &assembly->tables [MONO_TABLE_FIELD];
3727 table->rows += mono_array_length (moduleb->global_fields);
3728 alloc_table (table, table->rows);
3729 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3730 mono_image_get_field_info (
3731 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3734 table = &assembly->tables [MONO_TABLE_MODULE];
3735 alloc_table (table, 1);
3736 mono_image_fill_module_table (domain, moduleb, assembly);
3740 /* Collect all types into a list sorted by their table_idx */
3741 GPtrArray *types = g_ptr_array_new ();
3744 for (i = 0; i < moduleb->num_types; ++i) {
3745 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3746 collect_types (types, type);
3749 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3750 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3751 table->rows += types->len;
3752 alloc_table (table, table->rows);
3754 for (i = 0; i < types->len; ++i) {
3755 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3756 mono_image_get_type_info (domain, type, assembly);
3758 g_ptr_array_free (types, TRUE);
3762 * table->rows is already set above and in mono_image_fill_module_table.
3764 /* add all the custom attributes at the end, once all the indexes are stable */
3765 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3767 module_add_cattrs (assembly, moduleb);
3770 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3771 fixup_cattrs (assembly);
3775 * mono_image_insert_string:
3776 * @module: module builder object
3779 * Insert @str into the user string stream of @module.
3782 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3784 MonoDynamicImage *assembly;
3789 MONO_ARCH_SAVE_REGS;
3791 if (!module->dynamic_image)
3792 mono_image_module_basic_init (module);
3794 assembly = module->dynamic_image;
3796 if (assembly->save) {
3797 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3798 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3799 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3801 char *swapped = g_malloc (2 * mono_string_length (str));
3802 const char *p = (const char*)mono_string_chars (str);
3804 swap_with_size (swapped, p, 2, mono_string_length (str));
3805 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3809 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3811 mono_image_add_stream_data (&assembly->us, "", 1);
3814 idx = assembly->us.index ++;
3816 mono_g_hash_table_insert (assembly->tokens,
3817 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3819 return MONO_TOKEN_STRING | idx;
3823 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj,
3824 MonoArray *opt_param_types)
3829 klass = obj->vtable->klass;
3830 if (strcmp (klass->name, "MonoMethod") == 0) {
3831 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3832 MonoMethodSignature *sig, *old;
3833 guint32 sig_token, parent;
3836 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3838 nargs = mono_array_length (opt_param_types);
3839 old = method->signature;
3840 sig = mono_metadata_signature_alloc (
3841 &assembly->image, old->param_count + nargs);
3843 sig->hasthis = old->hasthis;
3844 sig->explicit_this = old->explicit_this;
3845 sig->call_convention = old->call_convention;
3846 sig->generic_param_count = old->generic_param_count;
3847 sig->param_count = old->param_count + nargs;
3848 sig->sentinelpos = old->param_count;
3849 sig->ret = old->ret;
3851 for (i = 0; i < old->param_count; i++)
3852 sig->params [i] = old->params [i];
3854 for (i = 0; i < nargs; i++) {
3855 MonoReflectionType *rt = mono_array_get (
3856 opt_param_types, MonoReflectionType *, i);
3857 sig->params [old->param_count + i] = rt->type;
3860 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
3861 g_assert ((parent & TYPEDEFORREF_MASK) == MEMBERREF_PARENT_TYPEREF);
3862 parent >>= TYPEDEFORREF_BITS;
3864 parent <<= MEMBERREF_PARENT_BITS;
3865 parent |= MEMBERREF_PARENT_TYPEREF;
3867 sig_token = method_encode_signature (assembly, sig);
3868 token = mono_image_get_varargs_method_token (
3869 assembly, parent, method->name, sig_token);
3870 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
3871 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3872 ReflectionMethodBuilder rmb;
3873 guint32 parent, sig;
3875 reflection_methodbuilder_from_method_builder (&rmb, mb);
3876 rmb.opt_types = opt_param_types;
3878 sig = method_builder_encode_signature (assembly, &rmb);
3880 parent = mono_image_create_token (assembly, obj);
3881 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
3883 parent = mono_metadata_token_index (parent) << MEMBERREF_PARENT_BITS;
3884 parent |= MEMBERREF_PARENT_METHODDEF;
3886 token = mono_image_get_varargs_method_token (
3887 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
3889 g_error ("requested method token for %s\n", klass->name);
3895 * mono_image_create_token:
3896 * @assembly: a dynamic assembly
3899 * Get a token to insert in the IL code stream for the given MemberInfo.
3900 * @obj can be one of:
3901 * ConstructorBuilder
3911 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3916 klass = obj->vtable->klass;
3917 if (strcmp (klass->name, "MethodBuilder") == 0) {
3918 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3920 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3921 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3923 token = mono_image_get_methodbuilder_token (assembly, mb);
3924 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3926 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3927 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3929 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3930 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3932 token = mono_image_get_ctorbuilder_token (assembly, mb);
3933 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3935 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3936 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3937 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3938 if (tb->generic_params) {
3939 token = mono_image_get_generic_field_token (assembly, fb);
3941 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3944 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3945 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3946 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3948 else if (strcmp (klass->name, "MonoType") == 0 ||
3949 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
3950 MonoReflectionType *tb = (MonoReflectionType *)obj;
3951 token = mono_metadata_token_from_dor (
3952 mono_image_typedef_or_ref (assembly, tb->type));
3954 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
3955 MonoReflectionType *tb = (MonoReflectionType *)obj;
3956 token = mono_metadata_token_from_dor (
3957 mono_image_typedef_or_ref (assembly, tb->type));
3959 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3960 strcmp (klass->name, "MonoMethod") == 0) {
3961 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3962 if (m->method->signature->is_inflated) {
3963 token = mono_image_get_methodspec_token (assembly, m->method);
3964 } else if (m->method->signature->generic_param_count) {
3965 g_assert_not_reached ();
3966 } else if ((m->method->klass->image == &assembly->image) &&
3967 !m->method->klass->generic_inst) {
3968 static guint32 method_table_idx = 0xffffff;
3969 if (m->method->klass->wastypebuilder) {
3970 /* we use the same token as the one that was assigned
3971 * to the Methodbuilder.
3972 * FIXME: do the equivalent for Fields.
3974 token = m->method->token;
3977 * Each token should have a unique index, but the indexes are
3978 * assigned by managed code, so we don't know about them. An
3979 * easy solution is to count backwards...
3981 method_table_idx --;
3982 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3985 token = mono_image_get_methodref_token (assembly, m->method);
3986 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3988 else if (strcmp (klass->name, "MonoField") == 0) {
3989 MonoReflectionField *f = (MonoReflectionField *)obj;
3990 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
3991 static guint32 field_table_idx = 0xffffff;
3993 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3995 token = mono_image_get_fieldref_token (assembly, f);
3996 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3998 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
3999 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4000 token = mono_image_get_array_token (assembly, m);
4002 else if (strcmp (klass->name, "SignatureHelper") == 0) {
4003 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4004 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4007 g_error ("requested token for %s\n", klass->name);
4009 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
4016 guint32 import_lookup_table;
4020 guint32 import_address_table_rva;
4028 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4030 static MonoDynamicImage*
4031 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
4032 char *assembly_name, char *module_name)
4034 static const guchar entrycode [16] = {0xff, 0x25, 0};
4035 MonoDynamicImage *image;
4039 * We need to use the current ms version or the ms runtime it won't find
4040 * the support dlls. D'oh!
4041 * const char *version = "mono-" VERSION;
4043 const char *version = "v1.0.3705";
4046 image = GC_MALLOC (sizeof (MonoDynamicImage));
4048 image = g_new0 (MonoDynamicImage, 1);
4051 /* keep in sync with image.c */
4052 image->image.name = assembly_name;
4053 image->image.assembly_name = image->image.name; /* they may be different */
4054 image->image.module_name = module_name;
4055 image->image.version = g_strdup (version);
4056 image->image.dynamic = TRUE;
4058 image->image.references = g_new0 (MonoAssembly*, 1);
4059 image->image.references [0] = NULL;
4061 mono_image_init (&image->image);
4063 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4064 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4065 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4066 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4067 image->handleref = g_hash_table_new (NULL, NULL);
4068 image->tokens = mono_g_hash_table_new (NULL, NULL);
4069 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4070 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4071 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4073 string_heap_init (&image->sheap);
4074 mono_image_add_stream_data (&image->us, "", 1);
4075 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4076 /* import tables... */
4077 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4078 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4079 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4080 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4081 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4082 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4083 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4084 stream_data_align (&image->code);
4086 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4088 for (i=0; i < 64; ++i) {
4089 image->tables [i].next_idx = 1;
4090 image->tables [i].columns = table_sizes [i];
4093 image->image.assembly = (MonoAssembly*)assembly;
4094 image->run = assembly->run;
4095 image->save = assembly->save;
4101 * mono_image_basic_init:
4102 * @assembly: an assembly builder object
4104 * Create the MonoImage that represents the assembly builder and setup some
4105 * of the helper hash table and the basic metadata streams.
4108 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4110 MonoDynamicAssembly *assembly;
4111 MonoDynamicImage *image;
4113 MONO_ARCH_SAVE_REGS;
4115 if (assemblyb->dynamic_assembly)
4119 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4121 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4124 assembly->assembly.dynamic = TRUE;
4125 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4126 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4127 if (assemblyb->culture)
4128 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4130 assembly->assembly.aname.culture = g_strdup ("");
4132 assembly->run = assemblyb->access != 2;
4133 assembly->save = assemblyb->access != 1;
4135 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4136 assembly->assembly.aname.name = image->image.name;
4137 assembly->assembly.image = &image->image;
4139 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4140 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4144 calc_section_size (MonoDynamicImage *assembly)
4148 /* alignment constraints */
4149 assembly->code.index += 3;
4150 assembly->code.index &= ~3;
4151 assembly->meta_size += 3;
4152 assembly->meta_size &= ~3;
4153 assembly->resources.index += 3;
4154 assembly->resources.index &= ~3;
4156 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4157 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4160 if (assembly->win32_res) {
4161 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4163 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4164 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4168 assembly->sections [MONO_SECTION_RELOC].size = 12;
4169 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4179 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4183 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4185 ResTreeNode *t1 = (ResTreeNode*)a;
4186 ResTreeNode *t2 = (ResTreeNode*)b;
4188 return t1->id - t2->id;
4192 * resource_tree_create:
4194 * Organize the resources into a resource tree.
4196 static ResTreeNode *
4197 resource_tree_create (MonoArray *win32_resources)
4199 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4203 tree = g_new0 (ResTreeNode, 1);
4205 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4206 MonoReflectionWin32Resource *win32_res =
4207 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4211 lang_node = g_new0 (ResTreeNode, 1);
4212 lang_node->id = win32_res->lang_id;
4213 lang_node->win32_res = win32_res;
4215 /* Create type node if neccesary */
4217 for (l = tree->children; l; l = l->next)
4218 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4219 type_node = (ResTreeNode*)l->data;
4224 type_node = g_new0 (ResTreeNode, 1);
4225 type_node->id = win32_res->res_type;
4228 * The resource types have to be sorted otherwise
4229 * Windows Explorer can't display the version information.
4231 tree->children = g_slist_insert_sorted (tree->children, type_node,
4232 resource_tree_compare_by_id);
4235 /* Create res node if neccesary */
4237 for (l = type_node->children; l; l = l->next)
4238 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4239 res_node = (ResTreeNode*)l->data;
4244 res_node = g_new0 (ResTreeNode, 1);
4245 res_node->id = win32_res->res_id;
4246 type_node->children = g_slist_append (type_node->children, res_node);
4249 res_node->children = g_slist_append (res_node->children, lang_node);
4256 * resource_tree_encode:
4258 * Encode the resource tree into the format used in the PE file.
4261 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4264 MonoPEResourceDir dir;
4265 MonoPEResourceDirEntry dir_entry;
4266 MonoPEResourceDataEntry data_entry;
4270 * For the format of the resource directory, see the article
4271 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4275 memset (&dir, 0, sizeof (dir));
4276 memset (&dir_entry, 0, sizeof (dir_entry));
4277 memset (&data_entry, 0, sizeof (data_entry));
4279 g_assert (sizeof (dir) == 16);
4280 g_assert (sizeof (dir_entry) == 8);
4281 g_assert (sizeof (data_entry) == 16);
4283 node->offset = p - begin;
4285 /* IMAGE_RESOURCE_DIRECTORY */
4286 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4288 memcpy (p, &dir, sizeof (dir));
4291 /* Reserve space for entries */
4293 p += sizeof (dir_entry) * dir.res_id_entries;
4295 /* Write children */
4296 for (l = node->children; l; l = l->next) {
4297 ResTreeNode *child = (ResTreeNode*)l->data;
4299 if (child->win32_res) {
4301 child->offset = p - begin;
4303 /* IMAGE_RESOURCE_DATA_ENTRY */
4304 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4305 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4307 memcpy (p, &data_entry, sizeof (data_entry));
4308 p += sizeof (data_entry);
4310 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4311 p += data_entry.rde_size;
4314 resource_tree_encode (child, begin, p, &p);
4317 /* IMAGE_RESOURCE_ENTRY */
4318 for (l = node->children; l; l = l->next) {
4319 ResTreeNode *child = (ResTreeNode*)l->data;
4320 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4322 dir_entry.is_dir = child->win32_res ? 0 : 1;
4323 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4325 memcpy (entries, &dir_entry, sizeof (dir_entry));
4326 entries += sizeof (dir_entry);
4333 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4338 MonoReflectionWin32Resource *win32_res;
4341 if (!assemblyb->win32_resources)
4345 * Resources are stored in a three level tree inside the PE file.
4346 * - level one contains a node for each type of resource
4347 * - level two contains a node for each resource
4348 * - level three contains a node for each instance of a resource for a
4349 * specific language.
4352 tree = resource_tree_create (assemblyb->win32_resources);
4354 /* Estimate the size of the encoded tree */
4356 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4357 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4358 size += mono_array_length (win32_res->res_data);
4360 /* Directory structure */
4361 size += mono_array_length (assemblyb->win32_resources) * 256;
4362 p = buf = g_malloc (size);
4364 resource_tree_encode (tree, p, p, &p);
4366 g_assert (p - buf < size);
4368 assembly->win32_res = g_malloc (p - buf);
4369 assembly->win32_res_size = p - buf;
4370 memcpy (assembly->win32_res, buf, p - buf);
4376 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4378 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4381 p += sizeof (MonoPEResourceDir);
4382 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4383 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4384 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4385 if (dir_entry->is_dir)
4386 fixup_resource_directory (res_section, child, rva);
4388 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4389 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4392 p += sizeof (MonoPEResourceDirEntry);
4397 * mono_image_create_pefile:
4398 * @mb: a module builder object
4400 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4401 * assembly->pefile where it can be easily retrieved later in chunks.
4404 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4405 MonoMSDOSHeader *msdos;
4406 MonoDotNetHeader *header;
4407 MonoSectionTable *section;
4408 MonoCLIHeader *cli_header;
4409 guint32 size, image_size, virtual_base, text_offset;
4410 guint32 header_start, section_start, file_offset, virtual_offset;
4411 MonoDynamicImage *assembly;
4412 MonoReflectionAssemblyBuilder *assemblyb;
4413 MonoDynamicStream *pefile;
4415 guint32 *rva, value;
4418 static const unsigned char msheader[] = {
4419 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4420 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4423 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4424 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4425 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4426 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4429 assemblyb = mb->assemblyb;
4431 mono_image_basic_init (assemblyb);
4432 assembly = mb->dynamic_image;
4434 /* already created */
4435 if (assembly->pefile.index)
4438 mono_image_build_metadata (mb);
4440 if (mb->is_main && assemblyb->resources) {
4441 int len = mono_array_length (assemblyb->resources);
4442 for (i = 0; i < len; ++i)
4443 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4446 if (mb->resources) {
4447 int len = mono_array_length (mb->resources);
4448 for (i = 0; i < len; ++i)
4449 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4452 build_compressed_metadata (assembly);
4455 assembly_add_win32_resources (assembly, assemblyb);
4457 nsections = calc_section_size (assembly);
4459 pefile = &assembly->pefile;
4461 /* The DOS header and stub */
4462 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4463 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4465 /* the dotnet header */
4466 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4468 /* the section tables */
4469 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4471 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4472 virtual_offset = VIRT_ALIGN;
4475 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4476 if (!assembly->sections [i].size)
4479 file_offset += FILE_ALIGN - 1;
4480 file_offset &= ~(FILE_ALIGN - 1);
4481 virtual_offset += VIRT_ALIGN - 1;
4482 virtual_offset &= ~(VIRT_ALIGN - 1);
4484 assembly->sections [i].offset = file_offset;
4485 assembly->sections [i].rva = virtual_offset;
4487 file_offset += assembly->sections [i].size;
4488 virtual_offset += assembly->sections [i].size;
4489 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4492 file_offset += FILE_ALIGN - 1;
4493 file_offset &= ~(FILE_ALIGN - 1);
4494 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4496 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4498 /* back-patch info */
4499 msdos = (MonoMSDOSHeader*)pefile->data;
4500 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4501 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4502 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4504 header = (MonoDotNetHeader*)(pefile->data + header_start);
4505 header->pesig [0] = 'P';
4506 header->pesig [1] = 'E';
4508 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4509 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4510 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4511 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4512 if (assemblyb->pekind == 1) {
4514 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4517 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4520 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4522 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4523 header->pe.pe_major = 6;
4524 header->pe.pe_minor = 0;
4525 size = assembly->sections [MONO_SECTION_TEXT].size;
4526 size += FILE_ALIGN - 1;
4527 size &= ~(FILE_ALIGN - 1);
4528 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4529 size = assembly->sections [MONO_SECTION_RSRC].size;
4530 size += FILE_ALIGN - 1;
4531 size &= ~(FILE_ALIGN - 1);
4532 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4533 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4534 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4535 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4536 /* pe_rva_entry_point always at the beginning of the text section */
4537 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4539 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4540 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4541 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4542 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4543 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4544 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4545 size = section_start;
4546 size += FILE_ALIGN - 1;
4547 size &= ~(FILE_ALIGN - 1);
4548 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4550 size += VIRT_ALIGN - 1;
4551 size &= ~(VIRT_ALIGN - 1);
4552 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4555 // Translate the PEFileKind value to the value expected by the Windows loader
4558 short kind = assemblyb->pekind;
4561 // PEFileKinds.ConsoleApplication == 2
4562 // PEFileKinds.WindowApplication == 3
4565 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4566 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4572 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4574 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4575 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4576 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4577 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4578 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4579 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4581 /* fill data directory entries */
4583 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4584 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4586 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4587 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4589 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4590 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4591 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4592 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4593 /* patch imported function RVA name */
4594 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4595 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4597 /* the import table */
4598 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4599 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4600 /* patch imported dll RVA name and other entries in the dir */
4601 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4602 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4603 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4604 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4605 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4606 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4608 p = (assembly->code.data + assembly->ilt_offset);
4609 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4610 *p++ = (value) & 0xff;
4611 *p++ = (value >> 8) & (0xff);
4612 *p++ = (value >> 16) & (0xff);
4613 *p++ = (value >> 24) & (0xff);
4615 /* the CLI header info */
4616 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4617 cli_header->ch_size = GUINT32_FROM_LE (72);
4618 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4619 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4620 if (assemblyb->entry_point) {
4621 guint32 table_idx = 0;
4622 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4623 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4624 table_idx = methodb->table_idx;
4627 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4628 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4631 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4632 /* The embedded managed resources */
4633 text_offset = assembly->text_rva + assembly->code.index;
4634 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4635 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4636 text_offset += assembly->resources.index;
4637 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4638 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4639 text_offset += assembly->meta_size;
4640 if (assembly->strong_name_size) {
4641 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4642 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4643 text_offset += assembly->strong_name_size;
4646 /* write the section tables and section content */
4647 section = (MonoSectionTable*)(pefile->data + section_start);
4648 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4649 static const char *section_names [] = {
4650 ".text", ".rsrc", ".reloc"
4652 if (!assembly->sections [i].size)
4654 strcpy (section->st_name, section_names [i]);
4655 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4656 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4657 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4658 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4659 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4660 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4661 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4663 case MONO_SECTION_TEXT:
4664 /* patch entry point */
4665 p = (assembly->code.data + 2);
4666 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4667 *p++ = (value) & 0xff;
4668 *p++ = (value >> 8) & 0xff;
4669 *p++ = (value >> 16) & 0xff;
4670 *p++ = (value >> 24) & 0xff;
4672 text_offset = assembly->sections [i].offset;
4673 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4674 text_offset += assembly->code.index;
4675 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4676 text_offset += assembly->resources.index;
4677 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4678 text_offset += assembly->meta_size;
4679 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4681 g_free (assembly->image.raw_metadata);
4683 case MONO_SECTION_RELOC:
4684 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4685 *rva = GUINT32_FROM_LE (assembly->text_rva);
4687 *rva = GUINT32_FROM_LE (12);
4689 data16 = (guint16*)rva;
4691 * the entrypoint is always at the start of the text section
4692 * 3 is IMAGE_REL_BASED_HIGHLOW
4693 * 2 is patch_size_rva - text_rva
4695 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4697 *data16 = 0; /* terminate */
4699 case MONO_SECTION_RSRC:
4700 if (assembly->win32_res) {
4701 text_offset = assembly->sections [i].offset;
4703 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4704 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4706 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4710 g_assert_not_reached ();
4715 /* check that the file is properly padded */
4718 FILE *f = fopen ("mypetest.exe", "w");
4719 fwrite (pefile->data, pefile->index, 1, f);
4725 MonoReflectionModule *
4726 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4730 MonoImageOpenStatus status;
4731 MonoDynamicAssembly *assembly;
4733 name = mono_string_to_utf8 (fileName);
4735 image = mono_image_open (name, &status);
4738 if (status == MONO_IMAGE_ERROR_ERRNO)
4739 exc = mono_get_exception_file_not_found (fileName);
4741 exc = mono_get_exception_bad_image_format (name);
4743 mono_raise_exception (exc);
4748 assembly = ab->dynamic_assembly;
4749 image->assembly = (MonoAssembly*)assembly;
4751 mono_assembly_load_references (image, &status);
4753 mono_image_close (image);
4754 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4757 return mono_module_get_object (mono_domain_get (), image);
4761 * We need to return always the same object for MethodInfo, FieldInfo etc..
4762 * but we need to consider the reflected type.
4763 * type uses a different hash, since it uses custom hash/equal functions.
4768 MonoClass *refclass;
4772 reflected_equal (gconstpointer a, gconstpointer b) {
4773 const ReflectedEntry *ea = a;
4774 const ReflectedEntry *eb = b;
4776 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4780 reflected_hash (gconstpointer a) {
4781 const ReflectedEntry *ea = a;
4782 return GPOINTER_TO_UINT (ea->item);
4785 #define CHECK_OBJECT(t,p,k) \
4791 mono_domain_lock (domain); \
4792 if (!domain->refobject_hash) \
4793 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4794 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4795 mono_domain_unlock (domain); \
4801 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4803 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4806 #define CACHE_OBJECT(p,o,k) \
4808 ReflectedEntry *e = ALLOC_REFENTRY; \
4810 e->refclass = (k); \
4811 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4812 mono_domain_unlock (domain); \
4816 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4818 /* this is done only once */
4819 mono_domain_lock (domain);
4820 CACHE_OBJECT (assembly, res, NULL);
4824 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4826 /* this is done only once */
4827 mono_domain_lock (domain);
4828 CACHE_OBJECT (module, res, NULL);
4832 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4834 MonoDynamicImage *image = moduleb->dynamic_image;
4835 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4838 * FIXME: we already created an image in mono_image_basic_init (), but
4839 * we don't know which module it belongs to, since that is only
4840 * determined at assembly save time.
4842 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4843 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4845 moduleb->module.image = &image->image;
4846 moduleb->dynamic_image = image;
4847 register_module (mono_object_domain (moduleb), moduleb, image);
4852 * mono_assembly_get_object:
4853 * @domain: an app domain
4854 * @assembly: an assembly
4856 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4858 MonoReflectionAssembly*
4859 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4861 static MonoClass *System_Reflection_Assembly;
4862 MonoReflectionAssembly *res;
4864 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4865 if (!System_Reflection_Assembly)
4866 System_Reflection_Assembly = mono_class_from_name (
4867 mono_defaults.corlib, "System.Reflection", "Assembly");
4868 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4869 res->assembly = assembly;
4870 CACHE_OBJECT (assembly, res, NULL);
4876 MonoReflectionModule*
4877 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4879 static MonoClass *System_Reflection_Module;
4880 MonoReflectionModule *res;
4882 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4883 if (!System_Reflection_Module)
4884 System_Reflection_Module = mono_class_from_name (
4885 mono_defaults.corlib, "System.Reflection", "Module");
4886 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4889 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4891 res->fqname = mono_string_new (domain, image->name);
4892 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4893 res->scopename = mono_string_new (domain, image->module_name);
4895 mono_image_addref (image);
4897 CACHE_OBJECT (image, res, NULL);
4901 MonoReflectionModule*
4902 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4904 static MonoClass *System_Reflection_Module;
4905 MonoReflectionModule *res;
4906 MonoTableInfo *table;
4907 guint32 cols [MONO_FILE_SIZE];
4909 guint32 i, name_idx;
4912 if (!System_Reflection_Module)
4913 System_Reflection_Module = mono_class_from_name (
4914 mono_defaults.corlib, "System.Reflection", "Module");
4915 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4917 table = &image->tables [MONO_TABLE_FILE];
4918 g_assert (table_index < table->rows);
4919 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4922 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4923 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4925 // Check whenever the row has a corresponding row in the moduleref table
4926 table = &image->tables [MONO_TABLE_MODULEREF];
4927 for (i = 0; i < table->rows; ++i) {
4928 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4929 val = mono_metadata_string_heap (image, name_idx);
4930 if (strcmp (val, name) == 0)
4931 res->image = image->modules [i];
4934 res->fqname = mono_string_new (domain, name);
4935 res->name = mono_string_new (domain, name);
4936 res->scopename = mono_string_new (domain, name);
4937 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4943 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4945 if ((t1->type != t2->type) ||
4946 (t1->byref != t2->byref))
4950 case MONO_TYPE_VOID:
4951 case MONO_TYPE_BOOLEAN:
4952 case MONO_TYPE_CHAR:
4963 case MONO_TYPE_STRING:
4966 case MONO_TYPE_OBJECT:
4967 case MONO_TYPE_TYPEDBYREF:
4969 case MONO_TYPE_VALUETYPE:
4970 case MONO_TYPE_CLASS:
4971 case MONO_TYPE_SZARRAY:
4972 return t1->data.klass == t2->data.klass;
4974 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4975 case MONO_TYPE_ARRAY:
4976 if (t1->data.array->rank != t2->data.array->rank)
4978 return t1->data.array->eklass == t2->data.array->eklass;
4979 case MONO_TYPE_GENERICINST: {
4981 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4983 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4985 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4986 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4992 case MONO_TYPE_MVAR:
4993 return t1->data.generic_param == t2->data.generic_param;
4995 g_error ("implement type compare for %0x!", t1->type);
5003 mymono_metadata_type_hash (MonoType *t1)
5009 hash |= t1->byref << 6; /* do not collide with t1->type values */
5011 case MONO_TYPE_VALUETYPE:
5012 case MONO_TYPE_CLASS:
5013 case MONO_TYPE_SZARRAY:
5014 /* check if the distribution is good enough */
5015 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5017 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5022 static MonoReflectionGenericInst*
5023 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5025 static MonoClass *System_Reflection_MonoGenericInst;
5026 MonoReflectionGenericInst *res;
5027 MonoGenericInst *ginst;
5030 if (!System_Reflection_MonoGenericInst) {
5031 System_Reflection_MonoGenericInst = mono_class_from_name (
5032 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5033 g_assert (System_Reflection_MonoGenericInst);
5036 ginst = geninst->data.generic_inst;
5037 gklass = mono_class_from_mono_type (ginst->generic_type);
5039 mono_class_init (ginst->klass);
5041 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5043 res->type.type = geninst;
5044 if (gklass->wastypebuilder && gklass->reflection_info)
5045 res->generic_type = gklass->reflection_info;
5047 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5053 * mono_type_get_object:
5054 * @domain: an app domain
5057 * Return an System.MonoType object representing the type @type.
5060 mono_type_get_object (MonoDomain *domain, MonoType *type)
5062 MonoReflectionType *res;
5063 MonoClass *klass = mono_class_from_mono_type (type);
5065 mono_domain_lock (domain);
5066 if (!domain->type_hash)
5067 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5068 (GCompareFunc)mymono_metadata_type_equal);
5069 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5070 mono_domain_unlock (domain);
5073 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5074 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5075 mono_g_hash_table_insert (domain->type_hash, type, res);
5076 mono_domain_unlock (domain);
5079 if (klass->reflection_info && !klass->wastypebuilder) {
5080 //g_assert_not_reached ();
5081 /* should this be considered an error condition? */
5083 mono_domain_unlock (domain);
5084 return klass->reflection_info;
5087 mono_class_init (klass);
5088 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5090 mono_g_hash_table_insert (domain->type_hash, type, res);
5091 mono_domain_unlock (domain);
5096 * mono_method_get_object:
5097 * @domain: an app domain
5099 * @refclass: the reflected type (can be NULL)
5101 * Return an System.Reflection.MonoMethod object representing the method @method.
5103 MonoReflectionMethod*
5104 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5107 * We use the same C representation for methods and constructors, but the type
5108 * name in C# is different.
5112 MonoReflectionMethod *ret;
5115 refclass = method->klass;
5117 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5118 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5119 cname = "MonoCMethod";
5121 cname = "MonoMethod";
5122 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5124 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5125 ret->method = method;
5126 ret->name = mono_string_new (domain, method->name);
5127 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5128 CACHE_OBJECT (method, ret, refclass);
5133 * mono_field_get_object:
5134 * @domain: an app domain
5138 * Return an System.Reflection.MonoField object representing the field @field
5141 MonoReflectionField*
5142 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5144 MonoReflectionField *res;
5147 CHECK_OBJECT (MonoReflectionField *, field, klass);
5148 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5149 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5152 res->name = mono_string_new (domain, field->name);
5153 res->attrs = field->type->attrs;
5154 res->type = mono_type_get_object (domain, field->type);
5155 CACHE_OBJECT (field, res, klass);
5160 * mono_property_get_object:
5161 * @domain: an app domain
5163 * @property: a property
5165 * Return an System.Reflection.MonoProperty object representing the property @property
5168 MonoReflectionProperty*
5169 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5171 MonoReflectionProperty *res;
5174 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5175 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5176 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5178 res->property = property;
5179 CACHE_OBJECT (property, res, klass);
5184 * mono_event_get_object:
5185 * @domain: an app domain
5189 * Return an System.Reflection.MonoEvent object representing the event @event
5192 MonoReflectionEvent*
5193 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5195 MonoReflectionEvent *res;
5198 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5199 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5200 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5203 CACHE_OBJECT (event, res, klass);
5208 * mono_param_get_objects:
5209 * @domain: an app domain
5212 * Return an System.Reflection.ParameterInfo array object representing the parameters
5213 * in the method @method.
5216 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5218 static MonoClass *System_Reflection_ParameterInfo;
5219 MonoArray *res = NULL;
5220 MonoReflectionMethod *member = NULL;
5221 MonoReflectionParameter *param = NULL;
5225 if (!System_Reflection_ParameterInfo)
5226 System_Reflection_ParameterInfo = mono_class_from_name (
5227 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5229 if (!method->signature->param_count)
5230 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5232 /* Note: the cache is based on the address of the signature into the method
5233 * since we already cache MethodInfos with the method as keys.
5235 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5237 member = mono_method_get_object (domain, method, NULL);
5238 names = g_new (char *, method->signature->param_count);
5239 mono_method_get_param_names (method, (const char **) names);
5241 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5242 for (i = 0; i < method->signature->param_count; ++i) {
5243 param = (MonoReflectionParameter *)mono_object_new (domain,
5244 System_Reflection_ParameterInfo);
5245 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5246 param->DefaultValueImpl = NULL; /* FIXME */
5247 param->MemberImpl = (MonoObject*)member;
5248 param->NameImpl = mono_string_new (domain, names [i]);
5249 param->PositionImpl = i;
5250 param->AttrsImpl = method->signature->params [i]->attrs;
5251 mono_array_set (res, gpointer, i, param);
5254 CACHE_OBJECT (&(method->signature), res, NULL);
5259 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5263 memset (assembly, 0, sizeof (MonoAssemblyName));
5265 assembly->culture = "";
5266 assembly->public_tok_value = NULL;
5268 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5271 while (*p == ' ' || *p == ',') {
5280 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5282 assembly->major = strtoul (p, &s, 10);
5283 if (s == p || *s != '.')
5286 assembly->minor = strtoul (p, &s, 10);
5287 if (s == p || *s != '.')
5290 assembly->build = strtoul (p, &s, 10);
5291 if (s == p || *s != '.')
5294 assembly->revision = strtoul (p, &s, 10);
5298 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5300 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5301 assembly->culture = "";
5304 assembly->culture = p;
5305 while (*p && *p != ',') {
5309 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5311 if (strncmp (p, "null", 4) == 0) {
5314 assembly->public_tok_value = p;
5315 while (*p && *p != ',') {
5320 while (*p && *p != ',')
5324 while (*p == ' ' || *p == ',') {
5338 * mono_reflection_parse_type:
5341 * Parse a type name as accepted by the GetType () method and output the info
5342 * extracted in the info structure.
5343 * the name param will be mangled, so, make a copy before passing it to this function.
5344 * The fields in info will be valid until the memory pointed to by name is valid.
5345 * Returns 0 on parse error.
5346 * See also mono_type_get_name () below.
5349 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5351 char *start, *p, *w, *last_point, *startn;
5352 int in_modifiers = 0;
5353 int isbyref = 0, rank;
5355 start = p = w = name;
5357 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5358 info->name = info->name_space = NULL;
5359 info->nested = NULL;
5360 info->modifiers = NULL;
5362 /* last_point separates the namespace from the name */
5368 *p = 0; /* NULL terminate the name */
5370 info->nested = g_list_append (info->nested, startn);
5371 /* we have parsed the nesting namespace + name */
5375 info->name_space = start;
5377 info->name = last_point + 1;
5379 info->name_space = (char *)"";
5405 info->name_space = start;
5407 info->name = last_point + 1;
5409 info->name_space = (char *)"";
5416 if (isbyref) /* only one level allowed by the spec */
5419 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5423 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5434 else if (*p != '*') /* '*' means unknown lower bound */
5440 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5452 return 0; /* missing assembly name */
5453 if (!assembly_name_to_aname (&info->assembly, p))
5460 if (info->assembly.name)
5463 *w = 0; /* terminate class name */
5464 if (!info->name || !*info->name)
5466 /* add other consistency checks */
5471 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5478 image = mono_defaults.corlib;
5481 klass = mono_class_from_name_case (image, info->name_space, info->name);
5483 klass = mono_class_from_name (image, info->name_space, info->name);
5486 for (mod = info->nested; mod; mod = mod->next) {
5489 mono_class_init (klass);
5490 nested = klass->nested_classes;
5493 klass = nested->data;
5495 if (g_strcasecmp (klass->name, mod->data) == 0)
5498 if (strcmp (klass->name, mod->data) == 0)
5502 nested = nested->next;
5509 mono_class_init (klass);
5510 for (mod = info->modifiers; mod; mod = mod->next) {
5511 modval = GPOINTER_TO_UINT (mod->data);
5512 if (!modval) { /* byref: must be last modifier */
5513 return &klass->this_arg;
5514 } else if (modval == -1) {
5515 klass = mono_ptr_class_get (&klass->byval_arg);
5516 } else { /* array rank */
5517 klass = mono_array_class_get (klass, modval);
5519 mono_class_init (klass);
5522 return &klass->byval_arg;
5526 * mono_reflection_get_type:
5527 * @image: a metadata context
5528 * @info: type description structure
5529 * @ignorecase: flag for case-insensitive string compares
5531 * Build a MonoType from the type description in @info.
5536 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5539 MonoReflectionAssembly *assembly;
5543 type = mono_reflection_get_type_internal (image, info, ignorecase);
5546 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5549 // Reconstruct the type name
5550 fullName = g_string_new ("");
5551 if (info->name_space && (info->name_space [0] != '\0'))
5552 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5554 g_string_printf (fullName, info->name);
5555 for (mod = info->nested; mod; mod = mod->next)
5556 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5559 mono_domain_try_type_resolve (
5560 mono_domain_get (), fullName->str, NULL);
5561 if (assembly && (!image || (assembly->assembly->image == image))) {
5563 if (assembly->assembly->dynamic) {
5564 /* Enumerate all modules */
5565 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5569 if (abuilder->modules) {
5570 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5571 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5572 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5578 if (!type && abuilder->loaded_modules) {
5579 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5580 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5581 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5588 type = mono_reflection_get_type_internal (assembly->assembly->image,
5591 g_string_free (fullName, TRUE);
5596 * mono_reflection_type_from_name:
5598 * @image: a metadata context (can be NULL).
5600 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5601 * it defaults to get the type from @image or, if @image is NULL or loading
5602 * from it fails, uses corlib.
5606 mono_reflection_type_from_name (char *name, MonoImage *image)
5609 MonoTypeNameParse info;
5610 MonoAssembly *assembly;
5613 /* Make a copy since parse_type modifies its argument */
5614 tmp = g_strdup (name);
5616 /*g_print ("requested type %s\n", str);*/
5617 if (!mono_reflection_parse_type (tmp, &info)) {
5619 g_list_free (info.modifiers);
5620 g_list_free (info.nested);
5624 if (info.assembly.name) {
5625 assembly = mono_assembly_loaded (&info.assembly);
5626 /* do we need to load if it's not already loaded? */
5629 g_list_free (info.modifiers);
5630 g_list_free (info.nested);
5634 image = assembly->image;
5635 } else if (image == NULL) {
5636 image = mono_defaults.corlib;
5639 type = mono_reflection_get_type (image, &info, FALSE);
5640 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5641 image = mono_defaults.corlib;
5642 type = mono_reflection_get_type (image, &info, FALSE);
5646 g_list_free (info.modifiers);
5647 g_list_free (info.nested);
5652 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5654 int slen, type = t->type;
5659 case MONO_TYPE_BOOLEAN: {
5660 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5665 case MONO_TYPE_CHAR:
5667 case MONO_TYPE_I2: {
5668 guint16 *val = g_malloc (sizeof (guint16));
5673 #if SIZEOF_VOID_P == 4
5679 case MONO_TYPE_I4: {
5680 guint32 *val = g_malloc (sizeof (guint32));
5685 #if SIZEOF_VOID_P == 8
5686 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5691 case MONO_TYPE_I8: {
5692 guint64 *val = g_malloc (sizeof (guint64));
5697 case MONO_TYPE_VALUETYPE:
5698 if (t->data.klass->enumtype) {
5699 type = t->data.klass->enum_basetype->type;
5702 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5705 case MONO_TYPE_STRING:
5706 if (*p == (char)0xFF) {
5710 slen = mono_metadata_decode_value (p, &p);
5712 return mono_string_new_len (mono_domain_get (), p, slen);
5713 case MONO_TYPE_CLASS: {
5716 if (*p == (char)0xFF) {
5721 slen = mono_metadata_decode_value (p, &p);
5722 n = g_memdup (p, slen + 1);
5724 t = mono_reflection_type_from_name (n, image);
5726 g_warning ("Cannot load type '%s'", n);
5730 return mono_type_get_object (mono_domain_get (), t);
5734 case MONO_TYPE_OBJECT: {
5737 MonoClass *subc = NULL;
5742 } else if (subt == 0x0E) {
5743 type = MONO_TYPE_STRING;
5745 } else if (subt == 0x55) {
5748 slen = mono_metadata_decode_value (p, &p);
5749 n = g_memdup (p, slen + 1);
5751 t = mono_reflection_type_from_name (n, image);
5753 g_warning ("Cannot load type '%s'", n);
5756 subc = mono_class_from_mono_type (t);
5757 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5758 MonoType simple_type = {{0}};
5759 simple_type.type = subt;
5760 subc = mono_class_from_mono_type (&simple_type);
5762 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5764 val = load_cattr_value (image, &subc->byval_arg, p, end);
5765 obj = mono_object_new (mono_domain_get (), subc);
5766 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5770 case MONO_TYPE_SZARRAY:
5773 guint32 i, alen, basetype;
5776 if (alen == 0xffffffff) {
5780 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5781 basetype = t->data.klass->byval_arg.type;
5786 case MONO_TYPE_BOOLEAN:
5787 for (i=0;i<alen;i++)
5789 MonoBoolean val=*p++;
5790 mono_array_set(arr,MonoBoolean,i,val);
5793 case MONO_TYPE_CHAR:
5796 for (i=0;i<alen;i++)
5798 guint16 val=read16(p);
5799 mono_array_set(arr,guint16,i,val);
5806 for (i=0;i<alen;i++)
5808 guint32 val=read32(p);
5809 mono_array_set(arr,guint32,i,val);
5816 for (i=0;i<alen;i++)
5818 guint64 val=read64(p);
5819 mono_array_set(arr,guint64,i,val);
5823 case MONO_TYPE_CLASS:
5824 case MONO_TYPE_STRING:
5825 for (i = 0; i < alen; i++) {
5826 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5827 mono_array_set (arr, gpointer, i, item);
5831 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5837 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5843 type_is_reference (MonoType *type)
5845 switch (type->type) {
5846 case MONO_TYPE_BOOLEAN:
5847 case MONO_TYPE_CHAR:
5860 case MONO_TYPE_VALUETYPE:
5868 free_param_data (MonoMethodSignature *sig, void **params) {
5870 for (i = 0; i < sig->param_count; ++i) {
5871 if (!type_is_reference (sig->params [i]))
5872 g_free (params [i]);
5877 * Find the method index in the metadata methodDef table.
5878 * Later put these three helper methods in metadata and export them.
5881 find_method_index (MonoMethod *method) {
5882 MonoClass *klass = method->klass;
5885 for (i = 0; i < klass->method.count; ++i) {
5886 if (method == klass->methods [i])
5887 return klass->method.first + 1 + i;
5893 * Find the field index in the metadata FieldDef table.
5896 find_field_index (MonoClass *klass, MonoClassField *field) {
5899 for (i = 0; i < klass->field.count; ++i) {
5900 if (field == &klass->fields [i])
5901 return klass->field.first + 1 + i;
5907 * Find the property index in the metadata Property table.
5910 find_property_index (MonoClass *klass, MonoProperty *property) {
5913 for (i = 0; i < klass->property.count; ++i) {
5914 if (property == &klass->properties [i])
5915 return klass->property.first + 1 + i;
5921 * Find the event index in the metadata Event table.
5924 find_event_index (MonoClass *klass, MonoEvent *event) {
5927 for (i = 0; i < klass->event.count; ++i) {
5928 if (event == &klass->events [i])
5929 return klass->event.first + 1 + i;
5935 create_custom_attr (MonoImage *image, MonoMethod *method,
5936 const char *data, guint32 len)
5938 const char *p = data;
5940 guint32 i, j, num_named;
5944 mono_class_init (method->klass);
5947 attr = mono_object_new (mono_domain_get (), method->klass);
5948 mono_runtime_invoke (method, attr, NULL, NULL);
5952 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5955 /*g_print ("got attr %s\n", method->klass->name);*/
5957 params = g_new (void*, method->signature->param_count);
5961 for (i = 0; i < method->signature->param_count; ++i) {
5962 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5966 attr = mono_object_new (mono_domain_get (), method->klass);
5967 mono_runtime_invoke (method, attr, params, NULL);
5968 free_param_data (method->signature, params);
5970 num_named = read16 (named);
5972 for (j = 0; j < num_named; j++) {
5974 char *name, named_type, data_type;
5975 named_type = *named++;
5976 data_type = *named++; /* type of data */
5977 if (data_type == 0x55) {
5980 type_len = mono_metadata_decode_blob_size (named, &named);
5981 type_name = g_malloc (type_len + 1);
5982 memcpy (type_name, named, type_len);
5983 type_name [type_len] = 0;
5985 /* FIXME: lookup the type and check type consistency */
5988 if (data_type == MONO_TYPE_SZARRAY)
5989 /* The spec does not mention this */
5991 name_len = mono_metadata_decode_blob_size (named, &named);
5992 name = g_malloc (name_len + 1);
5993 memcpy (name, named, name_len);
5994 name [name_len] = 0;
5996 if (named_type == 0x53) {
5997 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
5998 void *val = load_cattr_value (image, field->type, named, &named);
5999 mono_field_set_value (attr, field, val);
6000 if (!type_is_reference (field->type))
6002 } else if (named_type == 0x54) {
6005 MonoType *prop_type;
6007 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6008 /* can we have more that 1 arg in a custom attr named property? */
6009 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6010 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6011 mono_property_set_value (prop, attr, pparams, NULL);
6012 if (!type_is_reference (prop_type))
6013 g_free (pparams [0]);
6022 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6029 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6030 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6031 for (i = 0; i < cinfo->num_attrs; ++i) {
6032 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6033 mono_array_set (result, gpointer, i, attr);
6039 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6041 guint32 mtoken, i, len;
6042 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6044 MonoCustomAttrInfo *ainfo;
6045 GList *tmp, *list = NULL;
6048 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6050 i = mono_metadata_custom_attrs_from_index (image, idx);
6054 while (i < ca->rows) {
6055 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6057 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6060 len = g_list_length (list);
6063 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6064 ainfo->num_attrs = len;
6065 ainfo->image = image;
6066 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6067 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6068 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
6069 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
6070 case CUSTOM_ATTR_TYPE_METHODDEF:
6071 mtoken |= MONO_TOKEN_METHOD_DEF;
6073 case CUSTOM_ATTR_TYPE_MEMBERREF:
6074 mtoken |= MONO_TOKEN_MEMBER_REF;
6077 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6080 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6081 if (!ainfo->attrs [i].ctor)
6082 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6083 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6084 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6085 ainfo->attrs [i].data = data;
6093 mono_custom_attrs_from_method (MonoMethod *method)
6095 MonoCustomAttrInfo *cinfo;
6098 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6100 idx = find_method_index (method);
6101 idx <<= CUSTOM_ATTR_BITS;
6102 idx |= CUSTOM_ATTR_METHODDEF;
6103 return mono_custom_attrs_from_index (method->klass->image, idx);
6107 mono_custom_attrs_from_class (MonoClass *klass)
6109 MonoCustomAttrInfo *cinfo;
6112 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6114 idx = mono_metadata_token_index (klass->type_token);
6115 idx <<= CUSTOM_ATTR_BITS;
6116 idx |= CUSTOM_ATTR_TYPEDEF;
6117 return mono_custom_attrs_from_index (klass->image, idx);
6121 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6123 MonoCustomAttrInfo *cinfo;
6126 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6128 idx = 1; /* there is only one assembly */
6129 idx <<= CUSTOM_ATTR_BITS;
6130 idx |= CUSTOM_ATTR_ASSEMBLY;
6131 return mono_custom_attrs_from_index (assembly->image, idx);
6134 static MonoCustomAttrInfo*
6135 mono_custom_attrs_from_module (MonoImage *image)
6137 MonoCustomAttrInfo *cinfo;
6140 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6142 idx = 1; /* there is only one module */
6143 idx <<= CUSTOM_ATTR_BITS;
6144 idx |= CUSTOM_ATTR_MODULE;
6145 return mono_custom_attrs_from_index (image, idx);
6149 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6151 MonoCustomAttrInfo *cinfo;
6154 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6156 idx = find_property_index (klass, property);
6157 idx <<= CUSTOM_ATTR_BITS;
6158 idx |= CUSTOM_ATTR_PROPERTY;
6159 return mono_custom_attrs_from_index (klass->image, idx);
6163 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6165 MonoCustomAttrInfo *cinfo;
6168 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6170 idx = find_event_index (klass, event);
6171 idx <<= CUSTOM_ATTR_BITS;
6172 idx |= CUSTOM_ATTR_EVENT;
6173 return mono_custom_attrs_from_index (klass->image, idx);
6177 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6179 MonoCustomAttrInfo *cinfo;
6182 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6184 idx = find_field_index (klass, field);
6185 idx <<= CUSTOM_ATTR_BITS;
6186 idx |= CUSTOM_ATTR_FIELDDEF;
6187 return mono_custom_attrs_from_index (klass->image, idx);
6191 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6194 guint32 i, idx, method_index;
6195 guint32 param_list, param_last, param_pos, found;
6197 MonoReflectionMethodAux *aux;
6199 if (method->klass->image->dynamic) {
6200 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6201 if (!aux || !aux->param_cattr)
6203 return aux->param_cattr [param];
6206 image = method->klass->image;
6207 method_index = find_method_index (method);
6208 ca = &image->tables [MONO_TABLE_METHOD];
6210 if (method->klass->generic_inst || method->klass->gen_params ||
6211 method->signature->generic_param_count) {
6212 // FIXME FIXME FIXME
6216 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6217 if (method_index == ca->rows) {
6218 ca = &image->tables [MONO_TABLE_PARAM];
6219 param_last = ca->rows + 1;
6221 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6222 ca = &image->tables [MONO_TABLE_PARAM];
6225 for (i = param_list; i < param_last; ++i) {
6226 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6227 if (param_pos == param) {
6235 idx <<= CUSTOM_ATTR_BITS;
6236 idx |= CUSTOM_ATTR_PARAMDEF;
6237 return mono_custom_attrs_from_index (image, idx);
6241 * mono_reflection_get_custom_attrs:
6242 * @obj: a reflection object handle
6244 * Return an array with all the custom attributes defined of the
6245 * reflection handle @obj. The objects are fully build.
6248 mono_reflection_get_custom_attrs (MonoObject *obj)
6252 MonoCustomAttrInfo *cinfo = NULL;
6254 MONO_ARCH_SAVE_REGS;
6256 klass = obj->vtable->klass;
6257 /* FIXME: need to handle: Module */
6258 if (klass == mono_defaults.monotype_class) {
6259 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6260 klass = mono_class_from_mono_type (rtype->type);
6261 cinfo = mono_custom_attrs_from_class (klass);
6262 } else if (strcmp ("Assembly", klass->name) == 0) {
6263 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6264 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6265 } else if (strcmp ("Module", klass->name) == 0) {
6266 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6267 cinfo = mono_custom_attrs_from_module (module->image);
6268 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6269 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6270 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6271 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6272 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6273 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6274 } else if (strcmp ("MonoField", klass->name) == 0) {
6275 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6276 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6277 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6278 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6279 cinfo = mono_custom_attrs_from_method (rmethod->method);
6280 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6281 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6282 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6283 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6284 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6285 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6286 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6287 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6288 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6289 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6290 } else { /* handle other types here... */
6291 g_error ("get custom attrs not yet supported for %s", klass->name);
6295 result = mono_custom_attrs_construct (cinfo);
6297 mono_custom_attrs_free (cinfo);
6299 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6300 result = mono_array_new (mono_domain_get (), klass, 0);
6306 static MonoMethodSignature*
6307 parameters_to_signature (MonoArray *parameters) {
6308 MonoMethodSignature *sig;
6311 count = parameters? mono_array_length (parameters): 0;
6313 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6314 sig->param_count = count;
6315 sig->sentinelpos = -1; /* FIXME */
6316 for (i = 0; i < count; ++i) {
6317 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6318 sig->params [i] = pt->type;
6323 static MonoMethodSignature*
6324 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6325 MonoMethodSignature *sig;
6327 sig = parameters_to_signature (ctor->parameters);
6328 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6329 sig->ret = &mono_defaults.void_class->byval_arg;
6333 static MonoMethodSignature*
6334 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6335 MonoMethodSignature *sig;
6337 sig = parameters_to_signature (method->parameters);
6338 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6339 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6340 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6344 static MonoMethodSignature*
6345 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6346 MonoMethodSignature *sig;
6348 sig = parameters_to_signature (method->parameters);
6349 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6350 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6351 sig->generic_param_count = 0;
6356 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6358 MonoClass *klass = mono_object_class (prop);
6359 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6360 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6361 *name = mono_string_to_utf8 (pb->name);
6362 *type = pb->type->type;
6364 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6365 *name = g_strdup (p->property->name);
6366 if (p->property->get)
6367 *type = p->property->get->signature->ret;
6369 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6374 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6376 MonoClass *klass = mono_object_class (field);
6377 if (strcmp (klass->name, "FieldBuilder") == 0) {
6378 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6379 *name = mono_string_to_utf8 (fb->name);
6380 *type = fb->type->type;
6382 MonoReflectionField *f = (MonoReflectionField *)field;
6383 *name = g_strdup (f->field->name);
6384 *type = f->field->type;
6389 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6392 MonoTypeEnum simple_type;
6394 if ((p-buffer) + 10 >= *buflen) {
6397 newbuf = g_realloc (buffer, *buflen);
6398 p = newbuf + (p-buffer);
6401 argval = ((char*)arg + sizeof (MonoObject));
6402 simple_type = type->type;
6404 switch (simple_type) {
6405 case MONO_TYPE_BOOLEAN:
6410 case MONO_TYPE_CHAR:
6413 swap_with_size (p, argval, 2, 1);
6419 swap_with_size (p, argval, 4, 1);
6425 swap_with_size (p, argval, 8, 1);
6428 case MONO_TYPE_VALUETYPE:
6429 if (type->data.klass->enumtype) {
6430 simple_type = type->data.klass->enum_basetype->type;
6433 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6436 case MONO_TYPE_STRING: {
6443 str = mono_string_to_utf8 ((MonoString*)arg);
6444 slen = strlen (str);
6445 if ((p-buffer) + 10 + slen >= *buflen) {
6449 newbuf = g_realloc (buffer, *buflen);
6450 p = newbuf + (p-buffer);
6453 mono_metadata_encode_value (slen, p, &p);
6454 memcpy (p, str, slen);
6459 case MONO_TYPE_CLASS: {
6467 k = mono_object_class (arg);
6468 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6469 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6470 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6472 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6473 slen = strlen (str);
6474 if ((p-buffer) + 10 + slen >= *buflen) {
6478 newbuf = g_realloc (buffer, *buflen);
6479 p = newbuf + (p-buffer);
6482 mono_metadata_encode_value (slen, p, &p);
6483 memcpy (p, str, slen);
6488 case MONO_TYPE_SZARRAY: {
6493 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6496 len = mono_array_length ((MonoArray*)arg);
6498 *p++ = (len >> 8) & 0xff;
6499 *p++ = (len >> 16) & 0xff;
6500 *p++ = (len >> 24) & 0xff;
6502 *retbuffer = buffer;
6503 eclass = type->data.klass;
6504 for (i = 0; i < len; ++i) {
6505 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6509 /* it may be a boxed value or a Type */
6510 case MONO_TYPE_OBJECT: {
6511 MonoClass *klass = mono_object_class (arg);
6515 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6518 } else if (klass->enumtype) {
6520 } else if (klass == mono_defaults.string_class) {
6521 simple_type = MONO_TYPE_STRING;
6524 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6525 *p++ = simple_type = klass->byval_arg.type;
6528 g_error ("unhandled type in custom attr");
6530 str = type_get_qualified_name (klass->enum_basetype, NULL);
6531 slen = strlen (str);
6532 if ((p-buffer) + 10 + slen >= *buflen) {
6536 newbuf = g_realloc (buffer, *buflen);
6537 p = newbuf + (p-buffer);
6540 mono_metadata_encode_value (slen, p, &p);
6541 memcpy (p, str, slen);
6544 simple_type = klass->enum_basetype->type;
6548 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6551 *retbuffer = buffer;
6555 * mono_reflection_get_custom_attrs_blob:
6556 * @ctor: custom attribute constructor
6557 * @ctorArgs: arguments o the constructor
6563 * Creates the blob of data that needs to be saved in the metadata and that represents
6564 * the custom attributed described by @ctor, @ctorArgs etc.
6565 * Returns: a Byte array representing the blob of data.
6568 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6571 MonoMethodSignature *sig;
6576 MONO_ARCH_SAVE_REGS;
6578 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6579 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6581 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6583 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6585 p = buffer = g_malloc (buflen);
6586 /* write the prolog */
6589 for (i = 0; i < sig->param_count; ++i) {
6590 arg = mono_array_get (ctorArgs, MonoObject*, i);
6591 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6595 i += mono_array_length (properties);
6597 i += mono_array_length (fields);
6599 *p++ = (i >> 8) & 0xff;
6602 for (i = 0; i < mono_array_length (properties); ++i) {
6607 prop = mono_array_get (properties, gpointer, i);
6608 get_prop_name_and_type (prop, &pname, &ptype);
6609 *p++ = 0x54; /* PROPERTY signature */
6611 /* Preallocate a large enough buffer */
6612 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6613 char *str = type_get_qualified_name (ptype, NULL);
6619 len += strlen (pname);
6621 if ((p-buffer) + 20 + len >= buflen) {
6625 newbuf = g_realloc (buffer, buflen);
6626 p = newbuf + (p-buffer);
6630 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6631 char *str = type_get_qualified_name (ptype, NULL);
6632 int slen = strlen (str);
6636 * This seems to be optional...
6639 mono_metadata_encode_value (slen, p, &p);
6640 memcpy (p, str, slen);
6644 mono_metadata_encode_value (ptype->type, p, &p);
6645 if (ptype->type == MONO_TYPE_SZARRAY)
6646 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6648 len = strlen (pname);
6649 mono_metadata_encode_value (len, p, &p);
6650 memcpy (p, pname, len);
6652 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6659 for (i = 0; i < mono_array_length (fields); ++i) {
6664 field = mono_array_get (fields, gpointer, i);
6665 get_field_name_and_type (field, &fname, &ftype);
6666 *p++ = 0x53; /* FIELD signature */
6667 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6668 char *str = type_get_qualified_name (ftype, NULL);
6669 int slen = strlen (str);
6670 if ((p-buffer) + 10 + slen >= buflen) {
6674 newbuf = g_realloc (buffer, buflen);
6675 p = newbuf + (p-buffer);
6680 * This seems to be optional...
6683 mono_metadata_encode_value (slen, p, &p);
6684 memcpy (p, str, slen);
6688 mono_metadata_encode_value (ftype->type, p, &p);
6690 len = strlen (fname);
6691 mono_metadata_encode_value (len, p, &p);
6692 memcpy (p, fname, len);
6694 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6699 g_assert (p - buffer <= buflen);
6700 buflen = p - buffer;
6701 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6702 p = mono_array_addr (result, char, 0);
6703 memcpy (p, buffer, buflen);
6705 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6711 * mono_reflection_setup_internal_class:
6712 * @tb: a TypeBuilder object
6714 * Creates a MonoClass that represents the TypeBuilder.
6715 * This is a trick that lets us simplify a lot of reflection code
6716 * (and will allow us to support Build and Run assemblies easier).
6719 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6721 MonoClass *klass, *parent;
6723 MONO_ARCH_SAVE_REGS;
6725 klass = g_new0 (MonoClass, 1);
6727 klass->image = &tb->module->dynamic_image->image;
6730 /* check so we can compile corlib correctly */
6731 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6732 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6733 parent = tb->parent->type->data.klass;
6735 parent = my_mono_class_from_mono_type (tb->parent->type);
6739 klass->inited = 1; /* we lie to the runtime */
6740 klass->name = mono_string_to_utf8 (tb->name);
6741 klass->name_space = mono_string_to_utf8 (tb->nspace);
6742 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6743 klass->flags = tb->attrs;
6745 klass->element_class = klass;
6746 klass->reflection_info = tb; /* need to pin. */
6748 /* Put into cache so mono_class_get () will find it */
6749 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6752 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6753 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6757 mono_class_setup_parent (klass, parent);
6758 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6759 const char *old_n = klass->name;
6760 /* trick to get relative numbering right when compiling corlib */
6761 klass->name = "BuildingObject";
6762 mono_class_setup_parent (klass, mono_defaults.object_class);
6763 klass->name = old_n;
6765 mono_class_setup_mono_type (klass);
6767 mono_class_setup_supertypes (klass);
6770 * FIXME: handle interfaces.
6773 tb->type.type = &klass->byval_arg;
6775 if (tb->nesting_type) {
6776 g_assert (tb->nesting_type->type);
6777 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6780 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6784 * mono_reflection_setup_generic_class:
6785 * @tb: a TypeBuilder object
6787 * Setup the generic class after all generic parameters have been added.
6790 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6795 MONO_ARCH_SAVE_REGS;
6797 klass = my_mono_class_from_mono_type (tb->type.type);
6799 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6801 if (klass->gen_params || (count == 0))
6804 klass->num_gen_params = count;
6805 klass->gen_params = g_new0 (MonoGenericParam, count);
6807 for (i = 0; i < count; i++) {
6808 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6809 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6814 * mono_reflection_create_internal_class:
6815 * @tb: a TypeBuilder object
6817 * Actually create the MonoClass that is associated with the TypeBuilder.
6820 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6824 MONO_ARCH_SAVE_REGS;
6826 klass = my_mono_class_from_mono_type (tb->type.type);
6828 if (klass->enumtype && klass->enum_basetype == NULL) {
6829 MonoReflectionFieldBuilder *fb;
6831 g_assert (tb->fields != NULL);
6832 g_assert (mono_array_length (tb->fields) >= 1);
6834 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6836 klass->enum_basetype = fb->type->type;
6837 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6838 if (!klass->element_class)
6839 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6840 klass->instance_size = klass->element_class->instance_size;
6841 klass->size_inited = 1;
6843 * this is almost safe to do with enums and it's needed to be able
6844 * to create objects of the enum type (for use in SetConstant).
6846 /* FIXME: Does this mean enums can't have method overrides ? */
6847 mono_class_setup_vtable (klass, NULL, 0);
6851 static MonoMarshalSpec*
6852 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6853 MonoReflectionMarshal *minfo)
6855 MonoMarshalSpec *res;
6857 res = g_new0 (MonoMarshalSpec, 1);
6858 res->native = minfo->type;
6860 switch (minfo->type) {
6861 case MONO_NATIVE_LPARRAY:
6862 res->data.array_data.elem_type = minfo->eltype;
6863 res->data.array_data.param_num = 0; /* Not yet */
6864 res->data.array_data.num_elem = minfo->count;
6867 case MONO_NATIVE_BYVALTSTR:
6868 case MONO_NATIVE_BYVALARRAY:
6869 res->data.array_data.num_elem = minfo->count;
6872 case MONO_NATIVE_CUSTOM:
6873 if (minfo->marshaltyperef)
6874 res->data.custom_data.custom_name =
6875 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6877 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6888 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6889 ReflectionMethodBuilder *rmb,
6890 MonoMethodSignature *sig)
6893 MonoMethodNormal *pm;
6894 MonoMarshalSpec **specs;
6895 MonoReflectionMethodAux *method_aux;
6898 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6899 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6900 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6903 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6905 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6907 pm = (MonoMethodNormal*)m;
6910 m->flags = rmb->attrs;
6911 m->iflags = rmb->iattrs;
6912 m->name = mono_string_to_utf8 (rmb->name);
6916 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6918 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6919 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6922 m->signature->pinvoke = 1;
6923 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6925 m->signature->pinvoke = 1;
6927 } else if (!m->klass->dummy &&
6928 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6929 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6930 MonoMethodHeader *header;
6932 gint32 max_stack, i;
6933 gint32 num_locals = 0;
6934 gint32 num_clauses = 0;
6938 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6939 code_size = rmb->ilgen->code_len;
6940 max_stack = rmb->ilgen->max_stack;
6941 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6942 if (rmb->ilgen->ex_handlers)
6943 num_clauses = method_count_clauses (rmb->ilgen);
6946 code = mono_array_addr (rmb->code, guint8, 0);
6947 code_size = mono_array_length (rmb->code);
6948 /* we probably need to run a verifier on the code... */
6958 header = g_malloc0 (sizeof (MonoMethodHeader) +
6959 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6960 header->code_size = code_size;
6961 header->code = g_malloc (code_size);
6962 memcpy ((char*)header->code, code, code_size);
6963 header->max_stack = max_stack;
6964 header->init_locals = rmb->init_locals;
6965 header->num_locals = num_locals;
6967 for (i = 0; i < num_locals; ++i) {
6968 MonoReflectionLocalBuilder *lb =
6969 mono_array_get (rmb->ilgen->locals,
6970 MonoReflectionLocalBuilder*, i);
6972 header->locals [i] = g_new0 (MonoType, 1);
6973 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6976 header->num_clauses = num_clauses;
6978 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6983 if (rmb->generic_params) {
6984 int count = mono_array_length (rmb->generic_params);
6985 header->gen_params = g_new0 (MonoGenericParam, count);
6986 for (i = 0; i < count; i++) {
6987 MonoReflectionGenericParam *gp =
6988 mono_array_get (rmb->generic_params,
6989 MonoReflectionGenericParam*, i);
6991 header->gen_params [i] = *gp->type.type->data.generic_param;
6995 pm->header = header;
6999 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7002 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7004 for (i = 0; i < rmb->nrefs; ++i)
7005 mw->data = g_list_append (mw->data, rmb->refs [i]);
7010 /* Parameter names */
7013 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7014 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7015 for (i = 0; i <= m->signature->param_count; ++i) {
7016 MonoReflectionParamBuilder *pb;
7017 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7019 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7021 if (!method_aux->param_cattr)
7022 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7023 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7029 /* Parameter marshalling */
7032 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7033 MonoReflectionParamBuilder *pb;
7034 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7035 if (pb->marshal_info) {
7037 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7038 specs [pb->position] =
7039 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7043 if (specs != NULL) {
7045 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7046 method_aux->param_marshall = specs;
7049 if (klass->image->dynamic && method_aux)
7050 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7056 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7058 ReflectionMethodBuilder rmb;
7059 MonoMethodSignature *sig;
7061 sig = ctor_builder_to_signature (mb);
7063 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7065 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7066 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7068 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7069 /* ilgen is no longer needed */
7077 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7079 ReflectionMethodBuilder rmb;
7080 MonoMethodSignature *sig;
7082 sig = method_builder_to_signature (mb);
7084 reflection_methodbuilder_from_method_builder (&rmb, mb);
7086 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7087 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7089 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7090 /* ilgen is no longer needed */
7096 static MonoClassField*
7097 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7099 MonoClassField *field;
7106 field = g_new0 (MonoClassField, 1);
7108 field->name = mono_string_to_utf8 (fb->name);
7110 /* FIXME: handle type modifiers */
7111 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7112 field->type->attrs = fb->attrs;
7114 field->type = fb->type->type;
7116 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7117 field->data = mono_array_addr (fb->rva_data, char, 0);
7118 if (fb->offset != -1)
7119 field->offset = fb->offset;
7120 field->parent = klass;
7122 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7124 if (fb->def_value) {
7125 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7126 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7127 field->def_value = g_new0 (MonoConstant, 1);
7128 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7129 /* Copy the data from the blob since it might get realloc-ed */
7130 p = assembly->blob.data + idx;
7131 len = mono_metadata_decode_blob_size (p, &p2);
7133 field->def_value->value = g_malloc (len);
7134 memcpy (field->def_value->value, p, len);
7141 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7145 MonoReflectionTypeBuilder *tb = NULL;
7146 MonoGenericInst *ginst;
7151 klass = mono_class_from_mono_type (type->type);
7152 if (!klass->gen_params && !klass->generic_inst &&
7153 !(klass->nested_in && klass->nested_in->gen_params))
7156 mono_loader_lock ();
7158 domain = mono_object_domain (type);
7160 ginst = g_new0 (MonoGenericInst, 1);
7162 if (!klass->generic_inst) {
7163 ginst->type_argc = type_argc;
7164 ginst->type_argv = types;
7166 for (i = 0; i < ginst->type_argc; ++i) {
7167 if (!ginst->is_open)
7168 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7171 ginst->generic_type = &klass->byval_arg;
7173 MonoGenericInst *kginst = klass->generic_inst;
7175 ginst->type_argc = kginst->type_argc;
7176 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7178 for (i = 0; i < ginst->type_argc; i++) {
7179 MonoType *t = kginst->type_argv [i];
7181 if (t->type == MONO_TYPE_VAR)
7182 t = types [t->data.generic_param->num];
7184 if (!ginst->is_open)
7185 ginst->is_open = mono_class_is_open_constructed_type (t);
7187 ginst->type_argv [i] = t;
7190 ginst->generic_type = kginst->generic_type;
7193 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7196 mono_loader_unlock ();
7200 ginst->context = g_new0 (MonoGenericContext, 1);
7201 ginst->context->ginst = ginst;
7203 geninst = g_new0 (MonoType, 1);
7204 geninst->type = MONO_TYPE_GENERICINST;
7205 geninst->data.generic_inst = ginst;
7207 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7208 tb = (MonoReflectionTypeBuilder *) type;
7210 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7211 ginst->is_dynamic = TRUE;
7212 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7213 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7214 MonoReflectionType *rgt = rgi->generic_type;
7216 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7217 tb = (MonoReflectionTypeBuilder *) rgt;
7219 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7220 ginst->is_dynamic = TRUE;
7222 icount = klass->interface_count;
7224 ginst->ifaces = g_new0 (MonoType *, icount);
7225 ginst->count_ifaces = icount;
7227 for (i = 0; i < icount; i++) {
7228 MonoReflectionType *itype;
7231 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7233 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7234 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7235 if (!ginst->ifaces [i])
7236 ginst->ifaces [i] = itype->type;
7239 mono_class_create_generic (ginst);
7241 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7243 mono_loader_unlock ();
7249 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7251 MonoClass *klass, *pklass = NULL;
7252 MonoReflectionType *parent = NULL;
7254 MonoReflectionTypeBuilder *tb = NULL;
7255 MonoGenericInst *ginst;
7258 domain = mono_object_domain (type);
7259 klass = mono_class_from_mono_type (type->type);
7261 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7262 tb = (MonoReflectionTypeBuilder *) type;
7265 parent = tb->parent;
7266 pklass = mono_class_from_mono_type (parent->type);
7269 pklass = klass->parent;
7271 parent = mono_type_get_object (domain, &pklass->byval_arg);
7274 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7278 ginst = geninst->data.generic_inst;
7280 if (pklass && pklass->generic_inst)
7281 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7286 MonoReflectionMethod*
7287 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7289 MonoMethod *method, *inflated;
7290 MonoReflectionMethodBuilder *mb = NULL;
7291 MonoGenericMethod *gmethod;
7292 MonoGenericContext *context;
7295 MONO_ARCH_SAVE_REGS;
7296 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7297 MonoReflectionTypeBuilder *tb;
7300 mb = (MonoReflectionMethodBuilder *) rmethod;
7301 tb = (MonoReflectionTypeBuilder *) mb->type;
7302 klass = mono_class_from_mono_type (tb->type.type);
7304 method = methodbuilder_to_mono_method (klass, mb);
7306 method = rmethod->method;
7308 count = method->signature->generic_param_count;
7309 if (count != mono_array_length (types))
7312 gmethod = g_new0 (MonoGenericMethod, 1);
7313 gmethod->mtype_argc = count;
7314 gmethod->mtype_argv = g_new0 (MonoType *, count);
7315 for (i = 0; i < count; i++) {
7316 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7317 gmethod->mtype_argv [i] = garg->type;
7320 context = g_new0 (MonoGenericContext, 1);
7321 context->ginst = method->klass->generic_inst;
7322 context->gmethod = gmethod;
7324 inflated = mono_class_inflate_generic_method (method, context, NULL);
7326 return mono_method_get_object (
7327 mono_object_domain (rmethod), inflated, NULL);
7331 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7333 MonoGenericMethod *gmethod;
7334 MonoGenericInst *ginst;
7335 MonoGenericContext *context;
7338 ginst = type->type.type->data.generic_inst;
7340 gmethod = g_new0 (MonoGenericMethod, 1);
7341 gmethod->reflection_info = obj;
7343 gmethod->mtype_argc = method->signature->generic_param_count;
7344 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7346 for (i = 0; i < gmethod->mtype_argc; i++) {
7347 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7348 MonoGenericParam *gparam = &mn->header->gen_params [i];
7350 g_assert (gparam->pklass);
7351 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7354 context = g_new0 (MonoGenericContext, 1);
7355 context->ginst = ginst;
7356 context->gmethod = gmethod;
7358 return mono_class_inflate_generic_method (method, context, ginst->klass);
7362 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7367 klass = mono_class_from_mono_type (type->type.type);
7369 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7370 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7371 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7372 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7373 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7374 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7375 method = ((MonoReflectionMethod *) obj)->method;
7377 method = NULL; /* prevent compiler warning */
7378 g_assert_not_reached ();
7381 return inflate_mono_method (type, method, obj);
7385 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7386 MonoArray *methods, MonoArray *ctors,
7387 MonoArray *fields, MonoArray *properties,
7390 MonoGenericInst *ginst;
7391 MonoDynamicGenericInst *dginst;
7392 MonoClass *klass, *gklass, *pklass;
7395 MONO_ARCH_SAVE_REGS;
7397 klass = mono_class_from_mono_type (type->type.type);
7398 ginst = type->type.type->data.generic_inst;
7400 if (ginst->initialized)
7403 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7405 gklass = mono_class_from_mono_type (ginst->generic_type);
7406 mono_class_init (gklass);
7409 pklass = mono_class_from_mono_type (ginst->parent);
7411 pklass = gklass->parent;
7413 mono_class_setup_parent (klass, pklass);
7415 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7416 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7417 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7418 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7419 dginst->count_events = events ? mono_array_length (events) : 0;
7421 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7422 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7423 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7424 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7425 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7427 for (i = 0; i < dginst->count_methods; i++) {
7428 MonoObject *obj = mono_array_get (methods, gpointer, i);
7430 dginst->methods [i] = inflate_method (type, obj);
7433 for (i = 0; i < dginst->count_ctors; i++) {
7434 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7436 dginst->ctors [i] = inflate_method (type, obj);
7439 for (i = 0; i < dginst->count_fields; i++) {
7440 MonoObject *obj = mono_array_get (fields, gpointer, i);
7441 MonoClassField *field;
7442 MonoInflatedField *ifield;
7444 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7445 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7446 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7447 field = ((MonoReflectionField *) obj)->field;
7449 field = NULL; /* prevent compiler warning */
7450 g_assert_not_reached ();
7453 ifield = g_new0 (MonoInflatedField, 1);
7454 ifield->generic_type = field->type;
7455 ifield->reflection_info = obj;
7457 dginst->fields [i] = *field;
7458 dginst->fields [i].generic_info = ifield;
7459 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7462 for (i = 0; i < dginst->count_properties; i++) {
7463 MonoObject *obj = mono_array_get (properties, gpointer, i);
7464 MonoProperty *property = &dginst->properties [i];
7466 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7467 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7469 property->parent = klass;
7470 property->attrs = pb->attrs;
7471 property->name = mono_string_to_utf8 (pb->name);
7473 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7475 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7476 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7477 *property = *((MonoReflectionProperty *) obj)->property;
7480 property->get = inflate_mono_method (type, property->get, NULL);
7482 property->set = inflate_mono_method (type, property->set, NULL);
7484 g_assert_not_reached ();
7487 for (i = 0; i < dginst->count_events; i++) {
7488 MonoObject *obj = mono_array_get (events, gpointer, i);
7489 MonoEvent *event = &dginst->events [i];
7491 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7492 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7494 event->parent = klass;
7495 event->attrs = eb->attrs;
7496 event->name = mono_string_to_utf8 (eb->name);
7498 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7499 if (eb->remove_method)
7500 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7501 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7502 *event = *((MonoReflectionEvent *) obj)->event;
7505 event->add = inflate_mono_method (type, event->add, NULL);
7507 event->remove = inflate_mono_method (type, event->remove, NULL);
7509 g_assert_not_reached ();
7512 ginst->initialized = TRUE;
7516 ensure_runtime_vtable (MonoClass *klass)
7518 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7519 int i, num, j, onum;
7520 MonoMethod **overrides;
7522 if (!tb || klass->wastypebuilder)
7525 ensure_runtime_vtable (klass->parent);
7527 num = tb->ctors? mono_array_length (tb->ctors): 0;
7528 num += tb->num_methods;
7529 klass->method.count = num;
7530 klass->methods = g_new (MonoMethod*, num);
7531 num = tb->ctors? mono_array_length (tb->ctors): 0;
7532 for (i = 0; i < num; ++i)
7533 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7534 num = tb->num_methods;
7536 for (i = 0; i < num; ++i)
7537 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7539 klass->wastypebuilder = TRUE;
7540 if (tb->interfaces) {
7541 klass->interface_count = mono_array_length (tb->interfaces);
7542 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7543 for (i = 0; i < klass->interface_count; ++i) {
7544 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7545 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7549 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7550 for (i = 0; i < klass->method.count; ++i)
7551 klass->methods [i]->slot = i;
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)
7564 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7568 for (i = 0; i < tb->num_methods; ++i) {
7569 MonoReflectionMethodBuilder *mb =
7570 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7571 if (mb->override_method) {
7572 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7573 overrides [onum * 2] =
7574 mb->override_method->method;
7575 overrides [onum * 2 + 1] =
7578 g_assert (mb->mhandle);
7585 mono_class_setup_vtable (klass, overrides, onum);
7589 typebuilder_setup_fields (MonoClass *klass)
7591 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7592 MonoReflectionFieldBuilder *fb;
7593 MonoClassField *field;
7598 klass->field.count = tb->num_fields;
7599 klass->field.first = 0;
7600 klass->field.last = klass->field.count;
7602 if (!klass->field.count)
7605 klass->fields = g_new0 (MonoClassField, klass->field.count);
7607 for (i = 0; i < klass->field.count; ++i) {
7608 fb = mono_array_get (tb->fields, gpointer, i);
7609 field = &klass->fields [i];
7610 field->name = mono_string_to_utf8 (fb->name);
7612 /* FIXME: handle type modifiers */
7613 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7614 field->type->attrs = fb->attrs;
7616 field->type = fb->type->type;
7618 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7619 field->data = mono_array_addr (fb->rva_data, char, 0);
7620 if (fb->offset != -1)
7621 field->offset = fb->offset;
7622 field->parent = klass;
7624 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7626 if (fb->def_value) {
7627 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7628 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7629 field->def_value = g_new0 (MonoConstant, 1);
7630 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7631 /* Copy the data from the blob since it might get realloc-ed */
7632 p = assembly->blob.data + idx;
7633 len = mono_metadata_decode_blob_size (p, &p2);
7635 field->def_value->value = g_malloc (len);
7636 memcpy (field->def_value->value, p, len);
7639 mono_class_layout_fields (klass);
7643 typebuilder_setup_properties (MonoClass *klass)
7645 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7646 MonoReflectionPropertyBuilder *pb;
7649 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7650 klass->property.first = 0;
7651 klass->property.last = klass->property.count;
7653 klass->properties = g_new0 (MonoProperty, klass->property.count);
7654 for (i = 0; i < klass->property.count; ++i) {
7655 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7656 klass->properties [i].parent = klass;
7657 klass->properties [i].attrs = pb->attrs;
7658 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7660 klass->properties [i].get = pb->get_method->mhandle;
7662 klass->properties [i].set = pb->set_method->mhandle;
7666 MonoReflectionEvent *
7667 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7669 MonoEvent *event = g_new0 (MonoEvent, 1);
7673 klass = my_mono_class_from_mono_type (tb->type.type);
7675 event->parent = klass;
7676 event->attrs = eb->attrs;
7677 event->name = mono_string_to_utf8 (eb->name);
7679 event->add = eb->add_method->mhandle;
7680 if (eb->remove_method)
7681 event->remove = eb->remove_method->mhandle;
7682 if (eb->raise_method)
7683 event->raise = eb->raise_method->mhandle;
7685 if (eb->other_methods) {
7686 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7687 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7688 MonoReflectionMethodBuilder *mb =
7689 mono_array_get (eb->other_methods,
7690 MonoReflectionMethodBuilder*, j);
7691 event->other [j] = mb->mhandle;
7695 return mono_event_get_object (mono_object_domain (tb), klass, event);
7699 typebuilder_setup_events (MonoClass *klass)
7701 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7702 MonoReflectionEventBuilder *eb;
7705 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7706 klass->event.first = 0;
7707 klass->event.last = klass->event.count;
7709 klass->events = g_new0 (MonoEvent, klass->event.count);
7710 for (i = 0; i < klass->event.count; ++i) {
7711 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7712 klass->events [i].parent = klass;
7713 klass->events [i].attrs = eb->attrs;
7714 klass->events [i].name = mono_string_to_utf8 (eb->name);
7716 klass->events [i].add = eb->add_method->mhandle;
7717 if (eb->remove_method)
7718 klass->events [i].remove = eb->remove_method->mhandle;
7719 if (eb->raise_method)
7720 klass->events [i].raise = eb->raise_method->mhandle;
7722 if (eb->other_methods) {
7723 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7724 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7725 MonoReflectionMethodBuilder *mb =
7726 mono_array_get (eb->other_methods,
7727 MonoReflectionMethodBuilder*, j);
7728 klass->events [i].other [j] = mb->mhandle;
7735 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7738 MonoReflectionType* res;
7740 MONO_ARCH_SAVE_REGS;
7742 klass = my_mono_class_from_mono_type (tb->type.type);
7744 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7747 * Fields to set in klass:
7748 * the various flags: delegate/unicode/contextbound etc.
7751 klass->flags = tb->attrs;
7753 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7754 /* No need to fully construct the type */
7755 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7757 /* enums are done right away */
7758 if (!klass->enumtype)
7759 ensure_runtime_vtable (klass);
7761 /* fields and object layout */
7762 if (klass->parent) {
7763 if (!klass->parent->size_inited)
7764 mono_class_init (klass->parent);
7765 klass->instance_size += klass->parent->instance_size;
7766 klass->class_size += klass->parent->class_size;
7767 klass->min_align = klass->parent->min_align;
7769 klass->instance_size = sizeof (MonoObject);
7770 klass->min_align = 1;
7773 /* FIXME: handle packing_size and instance_size */
7774 typebuilder_setup_fields (klass);
7776 typebuilder_setup_properties (klass);
7778 typebuilder_setup_events (klass);
7780 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7781 /* with enums res == tb: need to fix that. */
7782 if (!klass->enumtype)
7783 g_assert (res != (MonoReflectionType*)tb);
7788 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7790 MonoGenericParam *param;
7793 MONO_ARCH_SAVE_REGS;
7795 param = g_new0 (MonoGenericParam, 1);
7797 param->method = NULL;
7798 param->name = mono_string_to_utf8 (gparam->name);
7799 param->num = gparam->index;
7801 image = &gparam->tbuilder->module->dynamic_image->image;
7802 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7804 param->pklass->reflection_info = gparam;
7806 gparam->type.type = g_new0 (MonoType, 1);
7807 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7808 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7809 gparam->type.type->data.generic_param = param;
7813 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7815 MonoDynamicImage *assembly = sig->module->dynamic_image;
7816 guint32 na = mono_array_length (sig->arguments);
7821 MONO_ARCH_SAVE_REGS;
7823 p = buf = g_malloc (10 + na * 10);
7825 mono_metadata_encode_value (0x07, p, &p);
7826 mono_metadata_encode_value (na, p, &p);
7827 for (i = 0; i < na; ++i) {
7828 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7829 encode_reflection_type (assembly, type, p, &p);
7833 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7834 p = mono_array_addr (result, char, 0);
7835 memcpy (p, buf, buflen);
7842 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7844 MonoDynamicImage *assembly = sig->module->dynamic_image;
7845 guint32 na = mono_array_length (sig->arguments);
7850 MONO_ARCH_SAVE_REGS;
7852 p = buf = g_malloc (10 + na * 10);
7854 mono_metadata_encode_value (0x06, p, &p);
7855 for (i = 0; i < na; ++i) {
7856 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7857 encode_reflection_type (assembly, type, p, &p);
7861 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7862 p = mono_array_addr (result, char, 0);
7863 memcpy (p, buf, buflen);
7870 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7872 ReflectionMethodBuilder rmb;
7873 MonoMethodSignature *sig;
7876 sig = dynamic_method_to_signature (mb);
7878 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7881 * Resolve references.
7883 rmb.nrefs = mb->nrefs;
7884 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7885 for (i = 0; i < mb->nrefs; ++i) {
7886 gpointer ref = resolve_object (mb->module->image,
7887 mono_array_get (mb->refs, MonoObject*, i));
7890 mono_raise_exception (mono_get_exception_type_load (NULL));
7897 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7901 /* ilgen is no longer needed */
7906 * mono_reflection_lookup_dynamic_token:
7908 * Finish the Builder object pointed to by TOKEN and return the corresponding
7909 * runtime structure.
7912 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7914 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7917 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7920 return resolve_object (image, obj);
7924 resolve_object (MonoImage *image, MonoObject *obj)
7926 gpointer result = NULL;
7928 if (strcmp (obj->vtable->klass->name, "String") == 0) {
7929 result = mono_string_intern ((MonoString*)obj);
7932 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7933 MonoReflectionType *tb = (MonoReflectionType*)obj;
7934 result = mono_class_from_mono_type (tb->type);
7937 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7938 result = ((MonoReflectionMethod*)obj)->method;
7941 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7942 result = ((MonoReflectionMethod*)obj)->method;
7945 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7946 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7947 result = mb->mhandle;
7949 /* Type is not yet created */
7950 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7952 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7955 * Hopefully this has been filled in by calling CreateType() on the
7959 * TODO: This won't work if the application finishes another
7960 * TypeBuilder instance instead of this one.
7962 result = mb->mhandle;
7965 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7966 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7968 result = cb->mhandle;
7970 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7972 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7973 result = cb->mhandle;
7976 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7977 result = ((MonoReflectionField*)obj)->field;
7980 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7981 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7982 result = fb->handle;
7985 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7987 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7988 result = fb->handle;
7991 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7992 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7995 klass = tb->type.type->data.klass;
7996 if (klass->wastypebuilder) {
7997 /* Already created */
8001 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8002 result = tb->type.type->data.klass;
8006 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8007 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8008 MonoMethodSignature *sig;
8011 if (helper->arguments)
8012 nargs = mono_array_length (helper->arguments);
8016 sig = mono_metadata_signature_alloc (image, nargs);
8017 sig->explicit_this = helper->call_conv & 64;
8018 sig->hasthis = helper->call_conv & 32;
8020 if (helper->call_conv == 0) /* unmanaged */
8021 sig->call_convention = helper->unmanaged_call_conv - 1;
8023 if (helper->call_conv & 0x02)
8024 sig->call_convention = MONO_CALL_VARARG;
8026 sig->call_convention = MONO_CALL_DEFAULT;
8028 sig->param_count = nargs;
8029 /* TODO: Copy type ? */
8030 sig->ret = helper->return_type->type;
8031 for (i = 0; i < nargs; ++i) {
8032 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8033 sig->params [i] = rt->type;
8039 g_print (obj->vtable->klass->name);
8040 g_assert_not_reached ();