2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/tokentype.h"
17 #include "mono/metadata/domain-internals.h"
18 #include "mono/metadata/opcodes.h"
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/object-internals.h"
21 #include <mono/metadata/exception.h>
30 #include "rawbuffer.h"
31 #include "mono-endian.h"
33 #include <mono/os/gc_wrapper.h>
35 #define TEXT_OFFSET 512
36 #define CLI_H_SIZE 136
37 #define FILE_ALIGN 512
38 #define VIRT_ALIGN 8192
39 #define START_TEXT_RVA 0x00002000
42 MonoReflectionILGen *ilgen;
43 MonoReflectionType *rtype;
44 MonoArray *parameters;
45 MonoArray *generic_params;
51 guint32 *table_idx; /* note: it's a pointer */
55 MonoBoolean init_locals;
56 MonoArray *return_modreq;
57 MonoArray *return_modopt;
58 MonoArray *param_modreq;
59 MonoArray *param_modopt;
60 MonoArray *permissions;
64 } ReflectionMethodBuilder;
68 MonoReflectionGenericParam *gparam;
69 } GenericParamTableEntry;
71 const unsigned char table_sizes [64] = {
81 MONO_INTERFACEIMPL_SIZE,
82 MONO_MEMBERREF_SIZE, /* 0x0A */
84 MONO_CUSTOM_ATTR_SIZE,
85 MONO_FIELD_MARSHAL_SIZE,
86 MONO_DECL_SECURITY_SIZE,
87 MONO_CLASS_LAYOUT_SIZE,
88 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
89 MONO_STAND_ALONE_SIGNATURE_SIZE,
93 MONO_PROPERTY_MAP_SIZE,
96 MONO_METHOD_SEMA_SIZE,
98 MONO_MODULEREF_SIZE, /* 0x1A */
104 MONO_ASSEMBLY_SIZE, /* 0x20 */
105 MONO_ASSEMBLY_PROCESSOR_SIZE,
106 MONO_ASSEMBLYOS_SIZE,
107 MONO_ASSEMBLYREF_SIZE,
108 MONO_ASSEMBLYREFPROC_SIZE,
109 MONO_ASSEMBLYREFOS_SIZE,
113 MONO_NESTED_CLASS_SIZE,
115 MONO_GENERICPARAM_SIZE, /* 0x2A */
116 MONO_METHODSPEC_SIZE,
117 MONO_GENPARCONSTRAINT_SIZE,
123 * These macros can be used to allocate long living atomic data so it won't be
124 * tracked by the garbage collector. We use libgc because it's apparently faster
128 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
129 #define FREE_ATOMIC(ptr)
130 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
132 #define ALLOC_ATOMIC(size) g_malloc (size)
133 #define FREE_ATOMIC(ptr) g_free (ptr)
134 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
137 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
138 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
139 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
140 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
141 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
142 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
143 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
144 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
145 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
146 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
147 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
148 static void ensure_runtime_vtable (MonoClass *klass);
149 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
150 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
151 static guint32 type_get_signature_size (MonoType *type);
155 alloc_table (MonoDynamicTable *table, guint nrows)
158 g_assert (table->columns);
159 if (nrows + 1 >= table->alloc_rows) {
160 while (nrows + 1 >= table->alloc_rows)
161 if (table->alloc_rows == 0)
162 table->alloc_rows = 16;
164 table->alloc_rows *= 2;
167 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
169 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
174 make_room_in_stream (MonoDynamicStream *stream, int size)
176 while (stream->alloc_size <= size) {
177 if (stream->alloc_size < 4096)
178 stream->alloc_size = 4096;
180 stream->alloc_size *= 2;
183 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
185 stream->data = ALLOC_ATOMIC (stream->alloc_size);
189 string_heap_insert (MonoDynamicStream *sh, const char *str)
193 gpointer oldkey, oldval;
195 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
196 return GPOINTER_TO_UINT (oldval);
198 len = strlen (str) + 1;
200 if (idx + len > sh->alloc_size)
201 make_room_in_stream (sh, idx + len);
204 * We strdup the string even if we already copy them in sh->data
205 * so that the string pointers in the hash remain valid even if
206 * we need to realloc sh->data. We may want to avoid that later.
208 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
209 memcpy (sh->data + idx, str, len);
215 string_heap_init (MonoDynamicStream *sh)
218 sh->alloc_size = 4096;
219 sh->data = ALLOC_ATOMIC (4096);
220 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
221 string_heap_insert (sh, "");
224 #if 0 /* never used */
226 string_heap_free (MonoDynamicStream *sh)
228 FREE_ATOMIC (sh->data);
229 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
230 g_hash_table_destroy (sh->hash);
235 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
238 if (stream->alloc_size < stream->index + len)
239 make_room_in_stream (stream, stream->index + len);
240 memcpy (stream->data + stream->index, data, len);
242 stream->index += len;
244 * align index? Not without adding an additional param that controls it since
245 * we may store a blob value in pieces.
251 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
254 if (stream->alloc_size < stream->index + len)
255 make_room_in_stream (stream, stream->index + len);
256 memset (stream->data + stream->index, 0, len);
258 stream->index += len;
263 stream_data_align (MonoDynamicStream *stream)
266 guint32 count = stream->index % 4;
268 /* we assume the stream data will be aligned */
270 mono_image_add_stream_data (stream, buf, 4 - count);
274 mono_blob_entry_hash (const char* str)
278 len = mono_metadata_decode_blob_size (str, &str);
282 for (str += 1; str < end; str++)
283 h = (h << 5) - h + *str;
291 mono_blob_entry_equal (const char *str1, const char *str2) {
295 len = mono_metadata_decode_blob_size (str1, &end1);
296 len2 = mono_metadata_decode_blob_size (str2, &end2);
299 return memcmp (end1, end2, len) == 0;
303 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
307 gpointer oldkey, oldval;
309 copy = ALLOC_ATOMIC (s1+s2);
310 memcpy (copy, b1, s1);
311 memcpy (copy + s1, b2, s2);
312 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
314 idx = GPOINTER_TO_UINT (oldval);
316 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
317 mono_image_add_stream_data (&assembly->blob, b2, s2);
318 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
324 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
325 * dest may be misaligned.
328 swap_with_size (char *dest, const char* val, int len, int nelem) {
329 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
332 for (elem = 0; elem < nelem; ++elem) {
358 g_assert_not_reached ();
364 memcpy (dest, val, len * nelem);
369 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
373 guint32 idx = 0, len;
375 len = str->length * 2;
376 mono_metadata_encode_value (len, b, &b);
377 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
379 char *swapped = g_malloc (2 * mono_string_length (str));
380 const char *p = (const char*)mono_string_chars (str);
382 swap_with_size (swapped, p, 2, mono_string_length (str));
383 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
387 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
392 /* modified version needed to handle building corlib */
394 my_mono_class_from_mono_type (MonoType *type) {
395 switch (type->type) {
396 case MONO_TYPE_ARRAY:
398 case MONO_TYPE_SZARRAY:
399 case MONO_TYPE_GENERICINST:
400 return mono_class_from_mono_type (type);
403 g_assert (type->data.generic_param->pklass);
404 return type->data.generic_param->pklass;
406 /* should be always valid when we reach this case... */
407 return type->data.klass;
412 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
417 g_assert_not_reached ();
421 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
422 encode_type (assembly, ginst->generic_type, p, &p);
423 mono_metadata_encode_value (ginst->type_argc, p, &p);
424 for (i = 0; i < ginst->type_argc; ++i)
425 encode_type (assembly, ginst->type_argv [i], p, &p);
431 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
434 g_assert_not_reached ();
439 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
443 case MONO_TYPE_BOOLEAN:
457 case MONO_TYPE_STRING:
458 case MONO_TYPE_OBJECT:
459 case MONO_TYPE_TYPEDBYREF:
460 mono_metadata_encode_value (type->type, p, &p);
463 mono_metadata_encode_value (type->type, p, &p);
464 encode_type (assembly, type->data.type, p, &p);
466 case MONO_TYPE_SZARRAY:
467 mono_metadata_encode_value (type->type, p, &p);
468 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
471 case MONO_TYPE_VALUETYPE:
472 case MONO_TYPE_CLASS: {
473 MonoClass *k = mono_class_from_mono_type (type);
474 mono_metadata_encode_value (type->type, p, &p);
476 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
477 * otherwise two typerefs could point to the same type, leading to
478 * verification errors.
480 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
484 case MONO_TYPE_ARRAY:
485 mono_metadata_encode_value (type->type, p, &p);
486 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
487 mono_metadata_encode_value (type->data.array->rank, p, &p);
488 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
489 mono_metadata_encode_value (0, p, &p);
491 case MONO_TYPE_GENERICINST:
492 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
496 mono_metadata_encode_value (type->type, p, &p);
497 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
501 g_error ("need to encode type %x", type->type);
507 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
510 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
514 encode_type (assembly, type->type, p, endbuf);
518 g_assert_not_reached ();
523 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
528 for (i = 0; i < mono_array_length (modreq); ++i) {
529 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
530 *p = MONO_TYPE_CMOD_REQD;
532 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
536 for (i = 0; i < mono_array_length (modopt); ++i) {
537 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
538 *p = MONO_TYPE_CMOD_OPT;
540 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
547 generic_inst_get_signature_size (MonoGenericInst *ginst)
553 g_assert_not_reached ();
556 size += 1 + type_get_signature_size (ginst->generic_type);
558 for (i = 0; i < ginst->type_argc; ++i)
559 size += type_get_signature_size (ginst->type_argv [i]);
565 type_get_signature_size (MonoType *type)
570 g_assert_not_reached ();
578 case MONO_TYPE_BOOLEAN:
592 case MONO_TYPE_STRING:
593 case MONO_TYPE_OBJECT:
594 case MONO_TYPE_TYPEDBYREF:
597 return size + 1 + type_get_signature_size (type->data.type);
598 case MONO_TYPE_SZARRAY:
599 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
601 case MONO_TYPE_VALUETYPE:
602 case MONO_TYPE_CLASS:
605 case MONO_TYPE_ARRAY:
606 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
607 case MONO_TYPE_GENERICINST:
608 return size + generic_inst_get_signature_size (type->data.generic_inst);
614 g_error ("need to encode type %x", type->type);
620 method_get_signature_size (MonoMethodSignature *sig)
625 size = type_get_signature_size (sig->ret);
626 for (i = 0; i < sig->param_count; i++)
627 size += type_get_signature_size (sig->params [i]);
629 if (sig->generic_param_count)
631 if (sig->sentinelpos >= 0)
638 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
643 guint32 nparams = sig->param_count;
644 guint32 size = 11 + method_get_signature_size (sig);
652 p = buf = g_malloc (size);
654 * FIXME: vararg, explicit_this, differenc call_conv values...
656 *p = sig->call_convention;
658 *p |= 0x20; /* hasthis */
659 if (sig->generic_param_count)
660 *p |= 0x10; /* generic */
662 if (sig->generic_param_count)
663 mono_metadata_encode_value (sig->generic_param_count, p, &p);
664 mono_metadata_encode_value (nparams, p, &p);
665 encode_type (assembly, sig->ret, p, &p);
666 for (i = 0; i < nparams; ++i) {
667 if (i == sig->sentinelpos)
668 *p++ = MONO_TYPE_SENTINEL;
669 encode_type (assembly, sig->params [i], p, &p);
672 g_assert (p - buf < size);
673 mono_metadata_encode_value (p-buf, b, &b);
674 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
680 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
683 * FIXME: reuse code from method_encode_signature().
688 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
689 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
690 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
691 guint32 size = 21 + nparams * 20 + notypes * 20;
696 p = buf = g_malloc (size);
697 /* LAMESPEC: all the call conv spec is foobared */
698 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
699 if (mb->call_conv & 2)
700 *p |= 0x5; /* vararg */
701 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
702 *p |= 0x20; /* hasthis */
704 *p |= 0x10; /* generic */
707 mono_metadata_encode_value (ngparams, p, &p);
708 mono_metadata_encode_value (nparams + notypes, p, &p);
709 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
710 encode_reflection_type (assembly, mb->rtype, p, &p);
711 for (i = 0; i < nparams; ++i) {
712 MonoArray *modreq = NULL;
713 MonoArray *modopt = NULL;
714 MonoReflectionType *pt;
716 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
717 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
718 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
719 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
720 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
721 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
722 encode_reflection_type (assembly, pt, p, &p);
725 *p++ = MONO_TYPE_SENTINEL;
726 for (i = 0; i < notypes; ++i) {
727 MonoReflectionType *pt;
729 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
730 encode_reflection_type (assembly, pt, p, &p);
734 g_assert (p - buf < size);
735 mono_metadata_encode_value (p-buf, b, &b);
736 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
742 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
744 MonoDynamicTable *table;
747 guint32 idx, sig_idx, size;
748 guint nl = mono_array_length (ilgen->locals);
755 p = buf = g_malloc (size);
756 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
757 idx = table->next_idx ++;
759 alloc_table (table, table->rows);
760 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
762 mono_metadata_encode_value (0x07, p, &p);
763 mono_metadata_encode_value (nl, p, &p);
764 for (i = 0; i < nl; ++i) {
765 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
768 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
770 encode_reflection_type (assembly, lb->type, p, &p);
772 g_assert (p - buf < size);
773 mono_metadata_encode_value (p-buf, b, &b);
774 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
777 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
783 method_count_clauses (MonoReflectionILGen *ilgen)
785 guint32 num_clauses = 0;
788 MonoILExceptionInfo *ex_info;
789 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
790 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
791 if (ex_info->handlers)
792 num_clauses += mono_array_length (ex_info->handlers);
800 static MonoExceptionClause*
801 method_encode_clauses (MonoDynamicImage *assembly,
802 MonoReflectionILGen *ilgen, guint32 num_clauses)
804 MonoExceptionClause *clauses;
805 MonoExceptionClause *clause;
806 MonoILExceptionInfo *ex_info;
807 MonoILExceptionBlock *ex_block;
808 guint32 finally_start;
809 int i, j, clause_index;;
811 clauses = g_new0 (MonoExceptionClause, num_clauses);
814 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
815 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
816 finally_start = ex_info->start + ex_info->len;
817 g_assert (ex_info->handlers);
818 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
819 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
820 clause = &(clauses [clause_index]);
822 clause->flags = ex_block->type;
823 clause->try_offset = ex_info->start;
825 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
826 clause->try_len = finally_start - ex_info->start;
828 clause->try_len = ex_info->len;
829 clause->handler_offset = ex_block->start;
830 clause->handler_len = ex_block->len;
831 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
832 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
833 if (ex_block->extype) {
834 mono_g_hash_table_insert (assembly->tokens,
835 GUINT_TO_POINTER (clause->token_or_filter),
838 finally_start = ex_block->start + ex_block->len;
848 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
854 gint32 num_locals = 0;
855 gint32 num_exception = 0;
858 char fat_header [12];
861 guint32 local_sig = 0;
862 guint32 header_size = 12;
865 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
866 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
867 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
868 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
872 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
874 code = mb->ilgen->code;
875 code_size = mb->ilgen->code_len;
876 max_stack = mb->ilgen->max_stack;
877 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
878 if (mb->ilgen->ex_handlers)
879 num_exception = method_count_clauses (mb->ilgen);
883 char *name = mono_string_to_utf8 (mb->name);
884 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
885 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
888 mono_raise_exception (exception);
891 code_size = mono_array_length (code);
892 max_stack = 8; /* we probably need to run a verifier on the code... */
895 /* check for exceptions, maxstack, locals */
896 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
898 if (code_size < 64 && !(code_size & 1)) {
899 flags = (code_size << 2) | 0x2;
900 } else if (code_size < 32 && (code_size & 1)) {
901 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
905 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
906 /* add to the fixup todo list */
907 if (mb->ilgen && mb->ilgen->num_token_fixups)
908 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
909 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
910 return assembly->text_rva + idx;
914 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
916 * FIXME: need to set also the header size in fat_flags.
917 * (and more sects and init locals flags)
921 fat_flags |= METHOD_HEADER_MORE_SECTS;
923 fat_flags |= METHOD_HEADER_INIT_LOCALS;
924 fat_header [0] = fat_flags;
925 fat_header [1] = (header_size / 4 ) << 4;
926 shortp = (guint16*)(fat_header + 2);
927 *shortp = GUINT16_TO_LE (max_stack);
928 intp = (guint32*)(fat_header + 4);
929 *intp = GUINT32_TO_LE (code_size);
930 intp = (guint32*)(fat_header + 8);
931 *intp = GUINT32_TO_LE (local_sig);
932 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
933 /* add to the fixup todo list */
934 if (mb->ilgen && mb->ilgen->num_token_fixups)
935 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
937 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
939 unsigned char sheader [4];
940 MonoExceptionClause clause;
941 MonoILExceptionInfo * ex_info;
942 MonoILExceptionBlock * ex_block;
945 stream_data_align (&assembly->code);
946 /* always use fat format for now */
947 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
948 num_exception *= sizeof (MonoExceptionClause);
949 num_exception += 4; /* include the size of the header */
950 sheader [1] = num_exception & 0xff;
951 sheader [2] = (num_exception >> 8) & 0xff;
952 sheader [3] = (num_exception >> 16) & 0xff;
953 mono_image_add_stream_data (&assembly->code, sheader, 4);
954 /* fat header, so we are already aligned */
956 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
957 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
958 if (ex_info->handlers) {
959 int finally_start = ex_info->start + ex_info->len;
960 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
961 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
962 clause.flags = GUINT32_TO_LE (ex_block->type);
963 clause.try_offset = GUINT32_TO_LE (ex_info->start);
964 /* need fault, too, probably */
965 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
966 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
968 clause.try_len = GUINT32_TO_LE (ex_info->len);
969 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
970 clause.handler_len = GUINT32_TO_LE (ex_block->len);
971 finally_start = ex_block->start + ex_block->len;
972 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
973 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
974 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
975 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
976 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
977 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
980 g_error ("No clauses for ex info block %d", i);
984 return assembly->text_rva + idx;
988 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
991 MonoDynamicTable *table;
994 table = &assembly->tables [table_idx];
996 g_assert (col < table->columns);
998 values = table->values + table->columns;
999 for (i = 1; i <= table->rows; ++i) {
1000 if (values [col] == token)
1002 values += table->columns;
1007 static GHashTable *dynamic_custom_attrs = NULL;
1009 static MonoCustomAttrInfo*
1010 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1013 MonoCustomAttrInfo *ainfo;
1014 MonoReflectionCustomAttr *cattr;
1018 /* FIXME: check in assembly the Run flag is set */
1020 count = mono_array_length (cattrs);
1022 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1024 ainfo->image = image;
1025 ainfo->num_attrs = count;
1026 for (i = 0; i < count; ++i) {
1027 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1028 ainfo->attrs [i].ctor = cattr->ctor->method;
1029 /* FIXME: might want to memdup the data here */
1030 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1031 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1038 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1040 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1045 if (!dynamic_custom_attrs)
1046 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1048 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1049 ainfo->cached = TRUE;
1053 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1055 /* they are cached, so we don't free them */
1056 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1062 * idx is the table index of the object
1063 * type is one of MONO_CUSTOM_ATTR_*
1066 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1068 MonoDynamicTable *table;
1069 MonoReflectionCustomAttr *cattr;
1071 guint32 count, i, token;
1073 char *p = blob_size;
1075 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1078 count = mono_array_length (cattrs);
1079 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1080 table->rows += count;
1081 alloc_table (table, table->rows);
1082 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1083 idx <<= MONO_CUSTOM_ATTR_BITS;
1085 for (i = 0; i < count; ++i) {
1086 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1087 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1088 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1089 type = mono_metadata_token_index (token);
1090 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1091 switch (mono_metadata_token_table (token)) {
1092 case MONO_TABLE_METHOD:
1093 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1095 case MONO_TABLE_MEMBERREF:
1096 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1099 g_warning ("got wrong token in custom attr");
1102 values [MONO_CUSTOM_ATTR_TYPE] = type;
1104 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1105 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1106 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1107 values += MONO_CUSTOM_ATTR_SIZE;
1113 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
1114 MonoArray *permissions)
1116 MonoDynamicTable *table;
1118 guint32 count, i, idx;
1119 MonoReflectionPermissionSet *perm;
1124 count = mono_array_length (permissions);
1125 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1126 table->rows += count;
1127 alloc_table (table, table->rows);
1129 for (i = 0; i < mono_array_length (permissions); ++i) {
1130 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1132 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1134 idx = mono_metadata_token_index (parent_token);
1135 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1136 switch (mono_metadata_token_table (parent_token)) {
1137 case MONO_TABLE_TYPEDEF:
1138 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1140 case MONO_TABLE_METHOD:
1141 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1143 case MONO_TABLE_ASSEMBLY:
1144 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1147 g_assert_not_reached ();
1150 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1151 values [MONO_DECL_SECURITY_PARENT] = idx;
1152 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1159 * Fill in the MethodDef and ParamDef tables for a method.
1160 * This is used for both normal methods and constructors.
1163 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1165 MonoDynamicTable *table;
1170 /* room in this table is already allocated */
1171 table = &assembly->tables [MONO_TABLE_METHOD];
1172 *mb->table_idx = table->next_idx ++;
1173 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1174 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1175 name = mono_string_to_utf8 (mb->name);
1176 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1178 values [MONO_METHOD_FLAGS] = mb->attrs;
1179 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1180 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1181 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1183 table = &assembly->tables [MONO_TABLE_PARAM];
1184 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1186 mono_image_add_decl_security (assembly,
1187 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1191 MonoDynamicTable *mtable;
1194 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1195 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1198 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1199 if (mono_array_get (mb->pinfo, gpointer, i))
1202 table->rows += count;
1203 alloc_table (table, table->rows);
1204 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1205 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1206 MonoReflectionParamBuilder *pb;
1207 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1208 values [MONO_PARAM_FLAGS] = pb->attrs;
1209 values [MONO_PARAM_SEQUENCE] = i;
1210 if (pb->name != NULL) {
1211 name = mono_string_to_utf8 (pb->name);
1212 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1215 values [MONO_PARAM_NAME] = 0;
1217 values += MONO_PARAM_SIZE;
1218 if (pb->marshal_info) {
1220 alloc_table (mtable, mtable->rows);
1221 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1222 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1223 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1225 pb->table_idx = table->next_idx++;
1226 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1227 guint32 field_type = 0;
1228 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1230 alloc_table (mtable, mtable->rows);
1231 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1232 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1233 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1234 mvalues [MONO_CONSTANT_TYPE] = field_type;
1235 mvalues [MONO_CONSTANT_PADDING] = 0;
1243 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1244 MonoReflectionMethodBuilder *mb)
1246 rmb->ilgen = mb->ilgen;
1247 rmb->rtype = mb->rtype;
1248 rmb->parameters = mb->parameters;
1249 rmb->generic_params = mb->generic_params;
1250 rmb->opt_types = NULL;
1251 rmb->pinfo = mb->pinfo;
1252 rmb->attrs = mb->attrs;
1253 rmb->iattrs = mb->iattrs;
1254 rmb->call_conv = mb->call_conv;
1255 rmb->code = mb->code;
1256 rmb->type = mb->type;
1257 rmb->name = mb->name;
1258 rmb->table_idx = &mb->table_idx;
1259 rmb->init_locals = mb->init_locals;
1260 rmb->return_modreq = mb->return_modreq;
1261 rmb->return_modopt = mb->return_modopt;
1262 rmb->param_modreq = mb->param_modreq;
1263 rmb->param_modopt = mb->param_modopt;
1264 rmb->permissions = mb->permissions;
1265 rmb->mhandle = mb->mhandle;
1271 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1272 MonoReflectionCtorBuilder *mb)
1274 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1276 rmb->ilgen = mb->ilgen;
1277 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1278 rmb->parameters = mb->parameters;
1279 rmb->generic_params = NULL;
1280 rmb->opt_types = NULL;
1281 rmb->pinfo = mb->pinfo;
1282 rmb->attrs = mb->attrs;
1283 rmb->iattrs = mb->iattrs;
1284 rmb->call_conv = mb->call_conv;
1286 rmb->type = mb->type;
1287 rmb->name = mono_string_new (mono_domain_get (), name);
1288 rmb->table_idx = &mb->table_idx;
1289 rmb->init_locals = mb->init_locals;
1290 rmb->return_modreq = NULL;
1291 rmb->return_modopt = NULL;
1292 rmb->param_modreq = mb->param_modreq;
1293 rmb->param_modopt = mb->param_modopt;
1294 rmb->permissions = mb->permissions;
1295 rmb->mhandle = mb->mhandle;
1301 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1302 MonoReflectionDynamicMethod *mb)
1304 rmb->ilgen = mb->ilgen;
1305 rmb->rtype = mb->rtype;
1306 rmb->parameters = mb->parameters;
1307 rmb->generic_params = NULL;
1308 rmb->opt_types = NULL;
1310 rmb->attrs = mb->attrs;
1312 rmb->call_conv = mb->call_conv;
1315 rmb->name = mb->name;
1316 rmb->table_idx = NULL;
1317 rmb->init_locals = mb->init_locals;
1318 rmb->return_modreq = NULL;
1319 rmb->return_modopt = NULL;
1320 rmb->param_modreq = NULL;
1321 rmb->param_modopt = NULL;
1322 rmb->permissions = NULL;
1323 rmb->mhandle = mb->mhandle;
1329 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1331 MonoDynamicTable *table;
1334 ReflectionMethodBuilder rmb;
1337 reflection_methodbuilder_from_method_builder (&rmb, mb);
1339 mono_image_basic_method (&rmb, assembly);
1341 if (mb->dll) { /* It's a P/Invoke method */
1343 int charset = mb->charset & 0xf;
1344 int lasterr = mb->charset & 0x40;
1345 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1347 alloc_table (table, table->rows);
1348 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1349 /* map CharSet values to on-disk values */
1351 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1352 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1353 name = mono_string_to_utf8 (mb->dllentry);
1354 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1356 name = mono_string_to_utf8 (mb->dll);
1357 moduleref = string_heap_insert (&assembly->sheap, name);
1359 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1360 table = &assembly->tables [MONO_TABLE_MODULEREF];
1362 alloc_table (table, table->rows);
1363 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1364 values [MONO_IMPLMAP_SCOPE] = table->rows;
1368 if (mb->override_method) {
1369 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1371 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1373 alloc_table (table, table->rows);
1374 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1375 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1376 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1378 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1379 switch (mono_metadata_token_table (tok)) {
1380 case MONO_TABLE_MEMBERREF:
1381 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1383 case MONO_TABLE_METHOD:
1384 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1387 g_assert_not_reached ();
1389 values [MONO_METHODIMPL_DECLARATION] = tok;
1392 if (mb->generic_params) {
1393 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1394 table->rows += mono_array_length (mb->generic_params);
1395 alloc_table (table, table->rows);
1396 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1397 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1399 mono_image_get_generic_param_info (
1400 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1407 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1409 ReflectionMethodBuilder rmb;
1411 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1413 mono_image_basic_method (&rmb, assembly);
1417 type_get_fully_qualified_name (MonoType *type) {
1418 char *name, *result;
1422 name = mono_type_get_name (type);
1423 klass = my_mono_class_from_mono_type (type);
1424 ta = klass->image->assembly;
1426 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1427 name, ta->aname.name,
1428 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1429 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1430 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1436 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1440 klass = my_mono_class_from_mono_type (type);
1441 ta = klass->image->assembly;
1442 if (ta == ass || klass->image == mono_defaults.corlib)
1443 return mono_type_get_name (type);
1445 return type_get_fully_qualified_name (type);
1449 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1451 char blob_size [64];
1452 char *b = blob_size;
1457 if (!assembly->save)
1460 p = buf = g_malloc (64);
1462 mono_metadata_encode_value (0x06, p, &p);
1463 /* encode custom attributes before the type */
1464 encode_type (assembly, type, p, &p);
1465 g_assert (p-buf < 64);
1466 mono_metadata_encode_value (p-buf, b, &b);
1467 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1473 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1475 char blob_size [64];
1476 char *b = blob_size;
1481 p = buf = g_malloc (64);
1483 mono_metadata_encode_value (0x06, p, &p);
1484 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1485 /* encode custom attributes before the type */
1486 encode_reflection_type (assembly, fb->type, p, &p);
1487 g_assert (p-buf < 64);
1488 mono_metadata_encode_value (p-buf, b, &b);
1489 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1495 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1496 char blob_size [64];
1497 char *b = blob_size;
1500 guint32 idx = 0, len = 0, dummy = 0;
1502 p = buf = g_malloc (64);
1504 *ret_type = MONO_TYPE_CLASS;
1506 box_val = (char*)&dummy;
1508 box_val = ((char*)val) + sizeof (MonoObject);
1509 *ret_type = val->vtable->klass->byval_arg.type;
1512 switch (*ret_type) {
1513 case MONO_TYPE_BOOLEAN:
1518 case MONO_TYPE_CHAR:
1533 case MONO_TYPE_VALUETYPE:
1534 if (val->vtable->klass->enumtype) {
1535 *ret_type = val->vtable->klass->enum_basetype->type;
1538 g_error ("we can't encode valuetypes");
1539 case MONO_TYPE_CLASS:
1541 case MONO_TYPE_STRING: {
1542 MonoString *str = (MonoString*)val;
1543 /* there is no signature */
1544 len = str->length * 2;
1545 mono_metadata_encode_value (len, b, &b);
1546 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1548 char *swapped = g_malloc (2 * mono_string_length (str));
1549 const char *p = (const char*)mono_string_chars (str);
1551 swap_with_size (swapped, p, 2, mono_string_length (str));
1552 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1556 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1563 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1566 /* there is no signature */
1567 mono_metadata_encode_value (len, b, &b);
1568 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1569 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1570 swap_with_size (blob_size, box_val, len, 1);
1571 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1573 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1581 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1582 char blob_size [64];
1583 char *b = blob_size;
1584 char *p, *buf, *str;
1585 guint32 idx, len, bufsize = 256;
1587 p = buf = g_malloc (bufsize);
1589 switch (minfo->type) {
1590 case MONO_NATIVE_BYVALTSTR:
1591 case MONO_NATIVE_BYVALARRAY:
1592 mono_metadata_encode_value (minfo->type, p, &p);
1593 mono_metadata_encode_value (minfo->count, p, &p);
1595 case MONO_NATIVE_LPARRAY:
1596 mono_metadata_encode_value (minfo->type, p, &p);
1597 if (minfo->eltype || (minfo->count > 0)) {
1598 mono_metadata_encode_value (minfo->eltype, p, &p);
1599 if (minfo->count > 0) {
1600 mono_metadata_encode_value (0, p, &p);
1601 mono_metadata_encode_value (minfo->count, p, &p);
1605 case MONO_NATIVE_CUSTOM:
1606 mono_metadata_encode_value (minfo->type, p, &p);
1608 str = mono_string_to_utf8 (minfo->guid);
1610 mono_metadata_encode_value (len, p, &p);
1611 memcpy (p, str, len);
1615 mono_metadata_encode_value (0, p, &p);
1617 if (minfo->marshaltype) {
1618 str = mono_string_to_utf8 (minfo->marshaltype);
1620 mono_metadata_encode_value (len, p, &p);
1621 if (p + len >= buf + bufsize) {
1624 buf = g_realloc (buf, bufsize);
1627 memcpy (p, str, len);
1631 mono_metadata_encode_value (0, p, &p);
1633 if (minfo->marshaltyperef) {
1634 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1636 mono_metadata_encode_value (len, p, &p);
1637 if (p + len >= buf + bufsize) {
1640 buf = g_realloc (buf, bufsize);
1643 memcpy (p, str, len);
1647 mono_metadata_encode_value (0, p, &p);
1649 if (minfo->mcookie) {
1650 str = mono_string_to_utf8 (minfo->mcookie);
1652 mono_metadata_encode_value (len, p, &p);
1653 if (p + len >= buf + bufsize) {
1656 buf = g_realloc (buf, bufsize);
1659 memcpy (p, str, len);
1663 mono_metadata_encode_value (0, p, &p);
1667 mono_metadata_encode_value (minfo->type, p, &p);
1671 mono_metadata_encode_value (len, b, &b);
1672 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1678 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1680 MonoDynamicTable *table;
1684 /* maybe this fixup should be done in the C# code */
1685 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1686 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1687 table = &assembly->tables [MONO_TABLE_FIELD];
1688 fb->table_idx = table->next_idx ++;
1689 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1690 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1691 name = mono_string_to_utf8 (fb->name);
1692 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1694 values [MONO_FIELD_FLAGS] = fb->attrs;
1695 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1697 if (fb->offset != -1) {
1698 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1700 alloc_table (table, table->rows);
1701 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1702 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1703 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1705 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1706 guint32 field_type = 0;
1707 table = &assembly->tables [MONO_TABLE_CONSTANT];
1709 alloc_table (table, table->rows);
1710 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1711 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1712 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1713 values [MONO_CONSTANT_TYPE] = field_type;
1714 values [MONO_CONSTANT_PADDING] = 0;
1716 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1718 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1720 alloc_table (table, table->rows);
1721 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1722 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1724 * We store it in the code section because it's simpler for now.
1727 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1729 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1730 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1732 if (fb->marshal_info) {
1733 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1735 alloc_table (table, table->rows);
1736 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1737 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1738 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1743 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1747 char *b = blob_size;
1748 guint32 nparams = 0;
1749 MonoReflectionMethodBuilder *mb = fb->get_method;
1750 MonoReflectionMethodBuilder *smb = fb->set_method;
1751 guint32 idx, i, size;
1753 if (mb && mb->parameters)
1754 nparams = mono_array_length (mb->parameters);
1755 if (!mb && smb && smb->parameters)
1756 nparams = mono_array_length (smb->parameters) - 1;
1757 size = 24 + nparams * 10;
1758 buf = p = g_malloc (size);
1761 mono_metadata_encode_value (nparams, p, &p);
1763 encode_reflection_type (assembly, mb->rtype, p, &p);
1764 for (i = 0; i < nparams; ++i) {
1765 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1766 encode_reflection_type (assembly, pt, p, &p);
1769 /* the property type is the last param */
1770 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1771 for (i = 0; i < nparams; ++i) {
1772 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1773 encode_reflection_type (assembly, pt, p, &p);
1777 g_assert (p - buf < size);
1778 mono_metadata_encode_value (p-buf, b, &b);
1779 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1785 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1787 MonoDynamicTable *table;
1790 guint num_methods = 0;
1794 * we need to set things in the following tables:
1795 * PROPERTYMAP (info already filled in _get_type_info ())
1796 * PROPERTY (rows already preallocated in _get_type_info ())
1797 * METHOD (method info already done with the generic method code)
1800 table = &assembly->tables [MONO_TABLE_PROPERTY];
1801 pb->table_idx = table->next_idx ++;
1802 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1803 name = mono_string_to_utf8 (pb->name);
1804 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1806 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1807 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1809 /* FIXME: we still don't handle 'other' methods */
1810 if (pb->get_method) num_methods ++;
1811 if (pb->set_method) num_methods ++;
1813 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1814 table->rows += num_methods;
1815 alloc_table (table, table->rows);
1817 if (pb->get_method) {
1818 semaidx = table->next_idx ++;
1819 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1820 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1821 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1822 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1824 if (pb->set_method) {
1825 semaidx = table->next_idx ++;
1826 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1827 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1828 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1829 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1834 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1836 MonoDynamicTable *table;
1839 guint num_methods = 0;
1843 * we need to set things in the following tables:
1844 * EVENTMAP (info already filled in _get_type_info ())
1845 * EVENT (rows already preallocated in _get_type_info ())
1846 * METHOD (method info already done with the generic method code)
1849 table = &assembly->tables [MONO_TABLE_EVENT];
1850 eb->table_idx = table->next_idx ++;
1851 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1852 name = mono_string_to_utf8 (eb->name);
1853 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1855 values [MONO_EVENT_FLAGS] = eb->attrs;
1856 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1859 * FIXME: we still don't handle 'other' methods
1861 if (eb->add_method) num_methods ++;
1862 if (eb->remove_method) num_methods ++;
1863 if (eb->raise_method) num_methods ++;
1865 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1866 table->rows += num_methods;
1867 alloc_table (table, table->rows);
1869 if (eb->add_method) {
1870 semaidx = table->next_idx ++;
1871 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1872 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1873 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1874 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1876 if (eb->remove_method) {
1877 semaidx = table->next_idx ++;
1878 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1879 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1880 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1881 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1883 if (eb->raise_method) {
1884 semaidx = table->next_idx ++;
1885 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1886 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1887 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1888 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1893 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1895 static MonoClass *NewConstraintAttr;
1896 static MonoMethod *NewConstraintAttr_ctor;
1897 MonoDynamicTable *table;
1899 guint32 token, type;
1900 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1903 if (!NewConstraintAttr)
1904 NewConstraintAttr = mono_class_from_name (
1905 mono_defaults.corlib, "System.Runtime.CompilerServices",
1906 "NewConstraintAttribute");
1907 g_assert (NewConstraintAttr);
1909 if (!NewConstraintAttr_ctor) {
1912 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1913 MonoMethod *m = NewConstraintAttr->methods [i];
1915 if (strcmp (m->name, ".ctor"))
1918 NewConstraintAttr_ctor = m;
1922 g_assert (NewConstraintAttr_ctor);
1925 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1927 alloc_table (table, table->rows);
1929 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1930 owner <<= MONO_CUSTOM_ATTR_BITS;
1931 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1932 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1934 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1936 type = mono_metadata_token_index (token);
1937 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1938 switch (mono_metadata_token_table (token)) {
1939 case MONO_TABLE_METHOD:
1940 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1942 case MONO_TABLE_MEMBERREF:
1943 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1946 g_warning ("got wrong token in custom attr");
1949 values [MONO_CUSTOM_ATTR_TYPE] = type;
1951 buf = p = g_malloc (1);
1952 mono_metadata_encode_value (4, p, &p);
1953 g_assert (p-buf == 1);
1955 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1957 values += MONO_CUSTOM_ATTR_SIZE;
1962 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1964 MonoDynamicTable *table;
1965 guint32 num_constraints, i;
1969 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1970 num_constraints = gparam->iface_constraints ?
1971 mono_array_length (gparam->iface_constraints) : 0;
1972 table->rows += num_constraints;
1973 if (gparam->base_type)
1975 alloc_table (table, table->rows);
1977 if (gparam->base_type) {
1978 table_idx = table->next_idx ++;
1979 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1981 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1982 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1983 assembly, gparam->base_type->type);
1986 for (i = 0; i < num_constraints; i++) {
1987 MonoReflectionType *constraint = mono_array_get (
1988 gparam->iface_constraints, gpointer, i);
1990 table_idx = table->next_idx ++;
1991 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1993 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1994 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1995 assembly, constraint->type);
1998 if (gparam->has_ctor_constraint)
1999 encode_new_constraint (assembly, owner);
2003 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2005 GenericParamTableEntry *entry;
2008 * The GenericParam table must be sorted according to the `owner' field.
2009 * We need to do this sorting prior to writing the GenericParamConstraint
2010 * table, since we have to use the final GenericParam table indices there
2011 * and they must also be sorted.
2014 entry = g_new0 (GenericParamTableEntry, 1);
2015 entry->owner = owner;
2016 entry->gparam = gparam;
2018 g_ptr_array_add (assembly->gen_params, entry);
2022 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2024 MonoDynamicTable *table;
2025 MonoGenericParam *param;
2029 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2030 table_idx = table->next_idx ++;
2031 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2033 param = entry->gparam->type.type->data.generic_param;
2035 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2036 if (entry->gparam->has_value_type)
2037 values [MONO_GENERICPARAM_FLAGS] = 0x18;
2038 else if (entry->gparam->has_reference_type)
2039 values [MONO_GENERICPARAM_FLAGS] = 0x04;
2041 values [MONO_GENERICPARAM_FLAGS] = 0x00;
2042 values [MONO_GENERICPARAM_NUMBER] = param->num;
2043 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2044 values [MONO_GENERICPARAM_KIND] = 0;
2046 encode_constraints (entry->gparam, table_idx, assembly);
2050 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2052 MonoDynamicTable *table;
2055 guint32 cols [MONO_ASSEMBLY_SIZE];
2059 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2062 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2063 table = &assembly->tables [MONO_TABLE_MODULEREF];
2064 token = table->next_idx ++;
2066 alloc_table (table, table->rows);
2067 values = table->values + token * MONO_MODULEREF_SIZE;
2068 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2070 token <<= MONO_RESOLTION_SCOPE_BITS;
2071 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2072 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2077 if (image->assembly->dynamic)
2079 memset (cols, 0, sizeof (cols));
2081 /* image->assembly->image is the manifest module */
2082 image = image->assembly->image;
2083 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2086 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2087 token = table->next_idx ++;
2089 alloc_table (table, table->rows);
2090 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2091 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2092 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2093 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2094 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2095 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2096 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2097 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2098 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2100 if (strcmp ("", image->assembly->aname.culture)) {
2101 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2102 image->assembly->aname.culture);
2105 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2106 guchar pubtoken [9];
2108 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2109 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2111 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2113 token <<= MONO_RESOLTION_SCOPE_BITS;
2114 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2115 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2120 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2122 MonoDynamicTable *table;
2128 char *b = blob_size;
2130 switch (type->type) {
2131 case MONO_TYPE_FNPTR:
2133 case MONO_TYPE_SZARRAY:
2134 case MONO_TYPE_ARRAY:
2136 case MONO_TYPE_MVAR:
2137 case MONO_TYPE_GENERICINST:
2138 encode_type (assembly, type, p, &p);
2140 case MONO_TYPE_CLASS:
2141 case MONO_TYPE_VALUETYPE: {
2142 MonoClass *k = mono_class_from_mono_type (type);
2143 if (!k || !k->generic_inst)
2145 encode_generic_inst (assembly, k->generic_inst, p, &p);
2152 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2153 if (assembly->save) {
2154 g_assert (p-sig < 128);
2155 mono_metadata_encode_value (p-sig, b, &b);
2156 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2157 alloc_table (table, table->rows + 1);
2158 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2159 values [MONO_TYPESPEC_SIGNATURE] = token;
2162 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2163 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2169 * Despite the name, we handle also TypeSpec (with the above helper).
2172 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2174 MonoDynamicTable *table;
2176 guint32 token, scope, enclosing;
2179 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2182 token = create_typespec (assembly, type);
2185 klass = my_mono_class_from_mono_type (type);
2187 klass = mono_class_from_mono_type (type);
2190 * If it's in the same module and not a generic type parameter:
2192 if ((klass->image == &assembly->image) &&
2193 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2194 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2195 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2196 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2200 if (klass->nested_in) {
2201 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2202 /* get the typeref idx of the enclosing type */
2203 enclosing >>= MONO_TYPEDEFORREF_BITS;
2204 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2206 scope = resolution_scope_from_image (assembly, klass->image);
2208 table = &assembly->tables [MONO_TABLE_TYPEREF];
2209 if (assembly->save) {
2210 alloc_table (table, table->rows + 1);
2211 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2212 values [MONO_TYPEREF_SCOPE] = scope;
2213 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2214 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2216 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2217 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2219 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2224 * Insert a memberef row into the metadata: the token that point to the memberref
2225 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2226 * mono_image_get_fieldref_token()).
2227 * The sig param is an index to an already built signature.
2230 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2232 MonoDynamicTable *table;
2234 guint32 token, pclass;
2237 parent = mono_image_typedef_or_ref (assembly, type);
2238 switch (parent & MONO_TYPEDEFORREF_MASK) {
2239 case MONO_TYPEDEFORREF_TYPEREF:
2240 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2242 case MONO_TYPEDEFORREF_TYPESPEC:
2243 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2245 case MONO_TYPEDEFORREF_TYPEDEF:
2246 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2249 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2252 /* extract the index */
2253 parent >>= MONO_TYPEDEFORREF_BITS;
2255 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2257 if (assembly->save) {
2258 alloc_table (table, table->rows + 1);
2259 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2260 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2261 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2262 values [MONO_MEMBERREF_SIGNATURE] = sig;
2265 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2272 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2275 MonoMethodSignature *sig;
2277 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2282 * A methodref signature can't contain an unmanaged calling convention.
2284 sig = mono_metadata_signature_dup (method->signature);
2285 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2286 sig->call_convention = MONO_CALL_DEFAULT;
2287 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2288 method->name, method_encode_signature (assembly, sig));
2290 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2295 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2296 const gchar *name, guint32 sig)
2298 MonoDynamicTable *table;
2302 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2304 if (assembly->save) {
2305 alloc_table (table, table->rows + 1);
2306 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2307 values [MONO_MEMBERREF_CLASS] = original;
2308 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2309 values [MONO_MEMBERREF_SIGNATURE] = sig;
2312 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2319 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2322 ReflectionMethodBuilder rmb;
2324 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2328 reflection_methodbuilder_from_method_builder (&rmb, mb);
2330 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2331 mono_string_to_utf8 (rmb.name),
2332 method_builder_encode_signature (assembly, &rmb));
2333 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2338 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2341 ReflectionMethodBuilder rmb;
2343 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2347 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2349 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2350 mono_string_to_utf8 (rmb.name),
2351 method_builder_encode_signature (assembly, &rmb));
2352 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2357 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2362 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2365 g_assert (f->field->parent);
2366 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2367 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2368 f->field->name, fieldref_encode_signature (assembly, type));
2369 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2374 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2379 guint32 nparams = gmethod->mtype_argc;
2380 guint32 size = 10 + nparams * 10;
2383 char *b = blob_size;
2385 if (!assembly->save)
2388 p = buf = g_malloc (size);
2390 * FIXME: vararg, explicit_this, differenc call_conv values...
2392 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2393 mono_metadata_encode_value (nparams, p, &p);
2395 for (i = 0; i < nparams; i++)
2396 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2399 g_assert (p - buf < size);
2400 mono_metadata_encode_value (p-buf, b, &b);
2401 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2407 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2409 MonoDynamicTable *table;
2411 guint32 token, mtoken = 0, sig;
2412 MonoMethodInflated *imethod;
2413 MonoMethod *declaring;
2415 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2417 g_assert (method->signature->is_inflated);
2418 imethod = (MonoMethodInflated *) method;
2419 declaring = imethod->declaring;
2421 sig = method_encode_signature (assembly, declaring->signature);
2422 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2423 declaring->name, sig);
2425 if (!declaring->signature->generic_param_count)
2428 switch (mono_metadata_token_table (mtoken)) {
2429 case MONO_TABLE_MEMBERREF:
2430 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2432 case MONO_TABLE_METHOD:
2433 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2436 g_assert_not_reached ();
2439 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2441 if (assembly->save) {
2442 alloc_table (table, table->rows + 1);
2443 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2444 values [MONO_METHODSPEC_METHOD] = mtoken;
2445 values [MONO_METHODSPEC_SIGNATURE] = sig;
2448 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2455 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2457 MonoMethodInflated *imethod;
2460 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2464 g_assert (m->signature->is_inflated);
2465 imethod = (MonoMethodInflated *) m;
2467 if (imethod->declaring->signature->generic_param_count)
2468 token = method_encode_methodspec (assembly, m);
2470 guint32 sig = method_encode_signature (
2471 assembly, imethod->declaring->signature);
2472 token = mono_image_get_memberref_token (
2473 assembly, &m->klass->byval_arg, m->name, sig);
2476 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2481 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2483 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2486 sig = method_encode_signature (assembly, imethod->declaring->signature);
2487 token = mono_image_get_memberref_token (
2488 assembly, &m->klass->byval_arg, m->name, sig);
2494 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2496 MonoDynamicTable *table;
2503 char *b = blob_size;
2507 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2508 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2509 * Because of this, we must not insert it into the `typeref' hash table.
2512 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2516 g_assert (tb->generic_params);
2517 klass = mono_class_from_mono_type (tb->type.type);
2519 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2520 encode_type (assembly, &klass->byval_arg, p, &p);
2522 count = mono_array_length (tb->generic_params);
2523 mono_metadata_encode_value (count, p, &p);
2524 for (i = 0; i < count; i++) {
2525 MonoReflectionGenericParam *gparam;
2527 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2529 encode_type (assembly, gparam->type.type, p, &p);
2532 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2533 if (assembly->save) {
2534 g_assert (p-sig < 128);
2535 mono_metadata_encode_value (p-sig, b, &b);
2536 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2537 alloc_table (table, table->rows + 1);
2538 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2539 values [MONO_TYPESPEC_SIGNATURE] = token;
2542 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2543 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2549 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2551 MonoDynamicTable *table;
2554 guint32 token, pclass, parent, sig;
2557 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2561 klass = mono_class_from_mono_type (fb->typeb->type);
2562 name = mono_string_to_utf8 (fb->name);
2564 sig = fieldref_encode_signature (assembly, fb->type->type);
2566 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2567 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2569 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2570 parent >>= MONO_TYPEDEFORREF_BITS;
2572 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2574 if (assembly->save) {
2575 alloc_table (table, table->rows + 1);
2576 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2577 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2578 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2579 values [MONO_MEMBERREF_SIGNATURE] = sig;
2582 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2584 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2589 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2597 char *b = blob_size;
2599 if (!assembly->save)
2603 g_assert (helper->type == 2);
2605 if (helper->arguments)
2606 nargs = mono_array_length (helper->arguments);
2610 size = 10 + (nargs * 10);
2612 p = buf = g_malloc (size);
2614 /* Encode calling convention */
2615 /* Change Any to Standard */
2616 if ((helper->call_conv & 0x03) == 0x03)
2617 helper->call_conv = 0x01;
2618 /* explicit_this implies has_this */
2619 if (helper->call_conv & 0x40)
2620 helper->call_conv &= 0x20;
2622 if (helper->call_conv == 0) /* Unmanaged */
2623 *p = helper->unmanaged_call_conv - 1;
2626 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2627 if (helper->call_conv & 0x02) /* varargs */
2632 mono_metadata_encode_value (nargs, p, &p);
2633 encode_reflection_type (assembly, helper->return_type, p, &p);
2634 for (i = 0; i < nargs; ++i) {
2635 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2636 encode_reflection_type (assembly, pt, p, &p);
2639 g_assert (p - buf < size);
2640 mono_metadata_encode_value (p-buf, b, &b);
2641 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2648 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2651 MonoDynamicTable *table;
2654 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2655 idx = table->next_idx ++;
2657 alloc_table (table, table->rows);
2658 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2660 values [MONO_STAND_ALONE_SIGNATURE] =
2661 mono_reflection_encode_sighelper (assembly, helper);
2667 reflection_cc_to_file (int call_conv) {
2668 switch (call_conv & 0x3) {
2670 case 1: return MONO_CALL_DEFAULT;
2671 case 2: return MONO_CALL_VARARG;
2673 g_assert_not_reached ();
2680 MonoMethodSignature *sig;
2686 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2691 MonoMethodSignature *sig;
2694 name = mono_string_to_utf8 (m->name);
2695 nparams = mono_array_length (m->parameters);
2696 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2698 sig->sentinelpos = -1;
2699 sig->call_convention = reflection_cc_to_file (m->call_conv);
2700 sig->param_count = nparams;
2701 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2702 for (i = 0; i < nparams; ++i) {
2703 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2704 sig->params [i] = t->type;
2707 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2709 if (strcmp (name, am->name) == 0 &&
2710 mono_metadata_type_equal (am->parent, m->parent->type) &&
2711 mono_metadata_signature_equal (am->sig, sig)) {
2714 m->table_idx = am->token & 0xffffff;
2718 am = g_new0 (ArrayMethod, 1);
2721 am->parent = m->parent->type;
2722 am->token = mono_image_get_memberref_token (assembly, am->parent,
2723 name, method_encode_signature (assembly, sig));
2724 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2725 m->table_idx = am->token & 0xffffff;
2730 * Insert into the metadata tables all the info about the TypeBuilder tb.
2731 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2734 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2736 MonoDynamicTable *table;
2738 int i, is_object = 0, is_system = 0;
2741 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2742 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2743 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2744 n = mono_string_to_utf8 (tb->name);
2745 if (strcmp (n, "Object") == 0)
2747 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2749 n = mono_string_to_utf8 (tb->nspace);
2750 if (strcmp (n, "System") == 0)
2752 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2754 if (tb->parent && !(is_system && is_object) &&
2755 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2756 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2758 values [MONO_TYPEDEF_EXTENDS] = 0;
2759 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2760 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2763 * if we have explicitlayout or sequentiallayouts, output data in the
2764 * ClassLayout table.
2766 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2767 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2768 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2770 alloc_table (table, table->rows);
2771 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2772 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2773 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2774 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2777 /* handle interfaces */
2778 if (tb->interfaces) {
2779 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2781 table->rows += mono_array_length (tb->interfaces);
2782 alloc_table (table, table->rows);
2783 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2784 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2785 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2786 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2787 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2788 values += MONO_INTERFACEIMPL_SIZE;
2794 table = &assembly->tables [MONO_TABLE_FIELD];
2795 table->rows += tb->num_fields;
2796 alloc_table (table, table->rows);
2797 for (i = 0; i < tb->num_fields; ++i)
2798 mono_image_get_field_info (
2799 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2802 /* handle constructors */
2804 table = &assembly->tables [MONO_TABLE_METHOD];
2805 table->rows += mono_array_length (tb->ctors);
2806 alloc_table (table, table->rows);
2807 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2808 mono_image_get_ctor_info (domain,
2809 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2812 /* handle methods */
2814 table = &assembly->tables [MONO_TABLE_METHOD];
2815 table->rows += tb->num_methods;
2816 alloc_table (table, table->rows);
2817 for (i = 0; i < tb->num_methods; ++i)
2818 mono_image_get_method_info (
2819 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2822 /* Do the same with properties etc.. */
2823 if (tb->events && mono_array_length (tb->events)) {
2824 table = &assembly->tables [MONO_TABLE_EVENT];
2825 table->rows += mono_array_length (tb->events);
2826 alloc_table (table, table->rows);
2827 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2829 alloc_table (table, table->rows);
2830 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2831 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2832 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2833 for (i = 0; i < mono_array_length (tb->events); ++i)
2834 mono_image_get_event_info (
2835 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2837 if (tb->properties && mono_array_length (tb->properties)) {
2838 table = &assembly->tables [MONO_TABLE_PROPERTY];
2839 table->rows += mono_array_length (tb->properties);
2840 alloc_table (table, table->rows);
2841 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2843 alloc_table (table, table->rows);
2844 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2845 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2846 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2847 for (i = 0; i < mono_array_length (tb->properties); ++i)
2848 mono_image_get_property_info (
2849 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2852 /* handle generic parameters */
2853 if (tb->generic_params) {
2854 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2855 table->rows += mono_array_length (tb->generic_params);
2856 alloc_table (table, table->rows);
2857 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2858 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2860 mono_image_get_generic_param_info (
2861 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2865 mono_image_add_decl_security (assembly,
2866 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2870 MonoDynamicTable *ntable;
2872 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2873 ntable->rows += mono_array_length (tb->subtypes);
2874 alloc_table (ntable, ntable->rows);
2875 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2877 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2878 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2880 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2881 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2882 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2883 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2884 mono_string_to_utf8 (tb->name), tb->table_idx,
2885 ntable->next_idx, ntable->rows);*/
2886 values += MONO_NESTED_CLASS_SIZE;
2893 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2897 g_ptr_array_add (types, type);
2899 if (!type->subtypes)
2902 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2903 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2904 collect_types (types, subtype);
2909 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2910 MonoReflectionTypeBuilder **type2)
2912 if ((*type1)->table_idx < (*type2)->table_idx)
2915 if ((*type1)->table_idx > (*type2)->table_idx)
2922 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2927 for (i = 0; i < mono_array_length (pinfo); ++i) {
2928 MonoReflectionParamBuilder *pb;
2929 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2932 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2937 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2940 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2942 for (i = 0; i < tb->num_fields; ++i) {
2943 MonoReflectionFieldBuilder* fb;
2944 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2945 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2949 for (i = 0; i < mono_array_length (tb->events); ++i) {
2950 MonoReflectionEventBuilder* eb;
2951 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2952 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2955 if (tb->properties) {
2956 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2957 MonoReflectionPropertyBuilder* pb;
2958 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2959 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2963 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2964 MonoReflectionCtorBuilder* cb;
2965 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2966 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2967 params_add_cattrs (assembly, cb->pinfo);
2972 for (i = 0; i < tb->num_methods; ++i) {
2973 MonoReflectionMethodBuilder* mb;
2974 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2975 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2976 params_add_cattrs (assembly, mb->pinfo);
2981 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2982 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2987 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2990 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
2992 /* no types in the module */
2996 for (i = 0; i < mb->num_types; ++i)
2997 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3001 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
3002 MonoDynamicImage *assembly)
3004 MonoDynamicTable *table;
3008 char *b = blob_size;
3011 table = &assembly->tables [MONO_TABLE_FILE];
3013 alloc_table (table, table->rows);
3014 values = table->values + table->next_idx * MONO_FILE_SIZE;
3015 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3016 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3017 if (module->image->dynamic) {
3018 /* This depends on the fact that the main module is emitted last */
3019 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3020 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3024 path = g_strdup (module->image->name);
3026 mono_sha1_get_digest_from_file (path, hash);
3029 mono_metadata_encode_value (20, b, &b);
3030 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3031 mono_image_add_stream_data (&assembly->blob, hash, 20);
3036 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3038 MonoDynamicTable *table;
3042 table = &assembly->tables [MONO_TABLE_MODULE];
3043 mb->table_idx = table->next_idx ++;
3044 name = mono_string_to_utf8 (mb->module.name);
3045 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3047 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3050 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3051 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3052 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3056 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3057 guint32 module_index, guint32 parent_index,
3058 MonoDynamicImage *assembly)
3060 MonoDynamicTable *table;
3064 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3065 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3068 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3070 alloc_table (table, table->rows);
3071 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3073 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3074 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3075 if (klass->nested_in)
3076 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3078 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3079 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3080 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3082 res = table->next_idx;
3086 /* Emit nested types */
3087 if (klass->nested_classes) {
3090 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3091 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3098 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3099 guint32 module_index, guint32 parent_index,
3100 MonoDynamicImage *assembly)
3105 klass = mono_class_from_mono_type (tb->type.type);
3107 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3109 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3110 parent_index, assembly);
3114 * We need to do this ourselves since klass->nested_classes is not set up.
3117 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3118 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3123 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3124 guint32 module_index,
3125 MonoDynamicImage *assembly)
3127 MonoImage *image = module->image;
3131 t = &image->tables [MONO_TABLE_TYPEDEF];
3133 for (i = 0; i < t->rows; ++i) {
3134 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3136 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3137 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3141 #define align_pointer(base,p)\
3143 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3145 (p) += 4 - (__diff & 3);\
3149 compare_semantics (const void *a, const void *b)
3151 const guint32 *a_values = a;
3152 const guint32 *b_values = b;
3153 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3156 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3160 compare_custom_attrs (const void *a, const void *b)
3162 const guint32 *a_values = a;
3163 const guint32 *b_values = b;
3165 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3169 compare_field_marshal (const void *a, const void *b)
3171 const guint32 *a_values = a;
3172 const guint32 *b_values = b;
3174 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3178 compare_nested (const void *a, const void *b)
3180 const guint32 *a_values = a;
3181 const guint32 *b_values = b;
3183 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3187 compare_genericparam (const void *a, const void *b)
3189 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3190 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3192 return (*a_entry)->owner - (*b_entry)->owner;
3196 pad_heap (MonoDynamicStream *sh)
3198 if (sh->index & 3) {
3199 int sz = 4 - (sh->index & 3);
3200 memset (sh->data + sh->index, 0, sz);
3207 MonoDynamicStream *stream;
3211 * build_compressed_metadata() fills in the blob of data that represents the
3212 * raw metadata as it will be saved in the PE file. The five streams are output
3213 * and the metadata tables are comnpressed from the guint32 array representation,
3214 * to the compressed on-disk format.
3217 build_compressed_metadata (MonoDynamicImage *assembly)
3219 MonoDynamicTable *table;
3221 guint64 valid_mask = 0;
3222 guint64 sorted_mask;
3223 guint32 heapt_size = 0;
3224 guint32 meta_size = 256; /* allow for header and other stuff */
3225 guint32 table_offset;
3226 guint32 ntables = 0;
3232 struct StreamDesc stream_desc [5];
3234 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3235 for (i = 0; i < assembly->gen_params->len; i++){
3236 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3237 write_generic_param_entry (assembly, entry);
3240 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3241 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3242 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3243 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3244 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3246 /* tables that are sorted */
3247 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3248 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3249 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3250 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3251 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3252 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3254 /* Compute table sizes */
3255 /* the MonoImage has already been created in mono_image_basic_init() */
3256 meta = &assembly->image;
3258 /* sizes should be multiple of 4 */
3259 pad_heap (&assembly->blob);
3260 pad_heap (&assembly->guid);
3261 pad_heap (&assembly->sheap);
3262 pad_heap (&assembly->us);
3264 /* Setup the info used by compute_sizes () */
3265 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3266 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3267 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3269 meta_size += assembly->blob.index;
3270 meta_size += assembly->guid.index;
3271 meta_size += assembly->sheap.index;
3272 meta_size += assembly->us.index;
3274 for (i=0; i < 64; ++i)
3275 meta->tables [i].rows = assembly->tables [i].rows;
3277 for (i = 0; i < 64; i++){
3278 if (meta->tables [i].rows == 0)
3280 valid_mask |= (guint64)1 << i;
3282 meta->tables [i].row_size = mono_metadata_compute_size (
3283 meta, i, &meta->tables [i].size_bitfield);
3284 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3286 heapt_size += 24; /* #~ header size */
3287 heapt_size += ntables * 4;
3288 /* make multiple of 4 */
3291 meta_size += heapt_size;
3292 meta->raw_metadata = g_malloc0 (meta_size);
3293 p = meta->raw_metadata;
3294 /* the metadata signature */
3295 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3296 /* version numbers and 4 bytes reserved */
3297 int16val = (guint16*)p;
3298 *int16val++ = GUINT16_TO_LE (1);
3299 *int16val = GUINT16_TO_LE (1);
3301 /* version string */
3302 int32val = (guint32*)p;
3303 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3305 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3306 p += GUINT32_FROM_LE (*int32val);
3307 align_pointer (meta->raw_metadata, p);
3308 int16val = (guint16*)p;
3309 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3310 *int16val = GUINT16_TO_LE (5); /* number of streams */
3314 * write the stream info.
3316 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3317 table_offset += 3; table_offset &= ~3;
3319 assembly->tstream.index = heapt_size;
3320 for (i = 0; i < 5; ++i) {
3321 int32val = (guint32*)p;
3322 stream_desc [i].stream->offset = table_offset;
3323 *int32val++ = GUINT32_TO_LE (table_offset);
3324 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3325 table_offset += GUINT32_FROM_LE (*int32val);
3326 table_offset += 3; table_offset &= ~3;
3328 strcpy (p, stream_desc [i].name);
3329 p += strlen (stream_desc [i].name) + 1;
3330 align_pointer (meta->raw_metadata, p);
3333 * now copy the data, the table stream header and contents goes first.
3335 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3336 p = meta->raw_metadata + assembly->tstream.offset;
3337 int32val = (guint32*)p;
3338 *int32val = GUINT32_TO_LE (0); /* reserved */
3341 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3342 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3343 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3344 *p++ = 1; /* version */
3347 *p++ = 1; /* version */
3351 if (meta->idx_string_wide)
3353 if (meta->idx_guid_wide)
3355 if (meta->idx_blob_wide)
3358 *p++ = 0; /* reserved */
3359 int64val = (guint64*)p;
3360 *int64val++ = GUINT64_TO_LE (valid_mask);
3361 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3363 int32val = (guint32*)p;
3364 for (i = 0; i < 64; i++){
3365 if (meta->tables [i].rows == 0)
3367 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3369 p = (unsigned char*)int32val;
3371 /* sort the tables that still need sorting */
3372 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3374 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3375 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3377 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3378 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3380 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3381 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3383 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3386 /* compress the tables */
3387 for (i = 0; i < 64; i++){
3390 guint32 bitfield = meta->tables [i].size_bitfield;
3391 if (!meta->tables [i].rows)
3393 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3394 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3395 meta->tables [i].base = p;
3396 for (row = 1; row <= meta->tables [i].rows; ++row) {
3397 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3398 for (col = 0; col < assembly->tables [i].columns; ++col) {
3399 switch (mono_metadata_table_size (bitfield, col)) {
3401 *p++ = values [col];
3404 *p++ = values [col] & 0xff;
3405 *p++ = (values [col] >> 8) & 0xff;
3408 *p++ = values [col] & 0xff;
3409 *p++ = (values [col] >> 8) & 0xff;
3410 *p++ = (values [col] >> 16) & 0xff;
3411 *p++ = (values [col] >> 24) & 0xff;
3414 g_assert_not_reached ();
3418 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3421 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3422 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3423 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3424 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3425 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3427 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3431 * Some tables in metadata need to be sorted according to some criteria, but
3432 * when methods and fields are first created with reflection, they may be assigned a token
3433 * that doesn't correspond to the final token they will get assigned after the sorting.
3434 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3435 * with the reflection objects that represent them. Once all the tables are set up, the
3436 * reflection objects will contains the correct table index. fixup_method() will fixup the
3437 * tokens for the method with ILGenerator @ilgen.
3440 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3441 guint32 code_idx = GPOINTER_TO_UINT (value);
3442 MonoReflectionILTokenInfo *iltoken;
3443 MonoReflectionFieldBuilder *field;
3444 MonoReflectionCtorBuilder *ctor;
3445 MonoReflectionMethodBuilder *method;
3446 MonoReflectionTypeBuilder *tb;
3447 MonoReflectionArrayMethod *am;
3449 unsigned char *target;
3451 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3452 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3453 target = assembly->code.data + code_idx + iltoken->code_pos;
3454 switch (target [3]) {
3455 case MONO_TABLE_FIELD:
3456 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3457 field = (MonoReflectionFieldBuilder *)iltoken->member;
3458 idx = field->table_idx;
3459 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3460 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3461 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3463 g_assert_not_reached ();
3466 case MONO_TABLE_METHOD:
3467 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3468 method = (MonoReflectionMethodBuilder *)iltoken->member;
3469 idx = method->table_idx;
3470 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3471 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3472 idx = ctor->table_idx;
3473 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3474 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3475 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3476 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3478 g_assert_not_reached ();
3481 case MONO_TABLE_TYPEDEF:
3482 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3483 g_assert_not_reached ();
3484 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3485 idx = tb->table_idx;
3487 case MONO_TABLE_MEMBERREF:
3488 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3489 am = (MonoReflectionArrayMethod*)iltoken->member;
3490 idx = am->table_idx;
3491 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3492 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3493 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3494 g_assert (m->klass->generic_inst);
3496 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3498 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3499 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3500 g_assert (f->generic_info);
3502 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3505 g_assert_not_reached ();
3508 case MONO_TABLE_METHODSPEC:
3509 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3510 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3511 g_assert (m->signature->generic_param_count);
3514 g_assert_not_reached ();
3518 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3520 target [0] = idx & 0xff;
3521 target [1] = (idx >> 8) & 0xff;
3522 target [2] = (idx >> 16) & 0xff;
3529 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3530 * value is not known when the table is emitted.
3533 fixup_cattrs (MonoDynamicImage *assembly)
3535 MonoDynamicTable *table;
3537 guint32 type, i, idx, token;
3540 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3542 for (i = 0; i < table->rows; ++i) {
3543 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3545 type = values [MONO_CUSTOM_ATTR_TYPE];
3546 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3547 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3548 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3549 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3552 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3553 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3554 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3555 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3562 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3564 MonoDynamicTable *table;
3568 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3570 alloc_table (table, table->rows);
3571 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3572 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3573 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3574 name = mono_string_to_utf8 (rsrc->name);
3575 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3577 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3582 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3584 MonoDynamicTable *table;
3588 char *b = blob_size;
3590 guint32 idx, offset;
3592 if (rsrc->filename) {
3593 name = mono_string_to_utf8 (rsrc->filename);
3594 sname = g_path_get_basename (name);
3596 table = &assembly->tables [MONO_TABLE_FILE];
3598 alloc_table (table, table->rows);
3599 values = table->values + table->next_idx * MONO_FILE_SIZE;
3600 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3601 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3604 mono_sha1_get_digest_from_file (name, hash);
3605 mono_metadata_encode_value (20, b, &b);
3606 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3607 mono_image_add_stream_data (&assembly->blob, hash, 20);
3609 idx = table->next_idx++;
3611 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3614 offset = mono_array_length (rsrc->data);
3615 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3616 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3617 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3618 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3622 * The entry should be emitted into the MANIFESTRESOURCE table of
3623 * the main module, but that needs to reference the FILE table
3624 * which isn't emitted yet.
3631 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3635 set_version_from_string (MonoString *version, guint32 *values)
3637 gchar *ver, *p, *str;
3640 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3641 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3642 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3643 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3646 ver = str = mono_string_to_utf8 (version);
3647 for (i = 0; i < 4; ++i) {
3648 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3654 /* handle Revision and Build */
3664 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3668 char *b = blob_size;
3673 len = mono_array_length (pkey);
3674 mono_metadata_encode_value (len, b, &b);
3675 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3676 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3678 /* need to get the actual value from the key type... */
3679 assembly->strong_name_size = 128;
3680 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3686 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3688 MonoDynamicTable *table;
3689 MonoDynamicImage *assembly;
3690 MonoReflectionAssemblyBuilder *assemblyb;
3695 guint32 module_index;
3697 assemblyb = moduleb->assemblyb;
3698 assembly = moduleb->dynamic_image;
3699 domain = mono_object_domain (assemblyb);
3701 /* Emit ASSEMBLY table */
3702 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3703 alloc_table (table, 1);
3704 values = table->values + MONO_ASSEMBLY_SIZE;
3705 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3706 name = mono_string_to_utf8 (assemblyb->name);
3707 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3709 if (assemblyb->culture) {
3710 name = mono_string_to_utf8 (assemblyb->culture);
3711 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3714 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3716 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3717 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3718 set_version_from_string (assemblyb->version, values);
3720 /* Emit FILE + EXPORTED_TYPE table */
3722 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3724 MonoReflectionModuleBuilder *file_module =
3725 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3726 if (file_module != moduleb) {
3727 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3729 if (file_module->types) {
3730 for (j = 0; j < file_module->num_types; ++j) {
3731 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3732 mono_image_fill_export_table (domain, tb, module_index, 0,
3738 if (assemblyb->loaded_modules) {
3739 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3740 MonoReflectionModule *file_module =
3741 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3742 mono_image_fill_file_table (domain, file_module, assembly);
3744 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3748 /* Emit MANIFESTRESOURCE table */
3750 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3752 MonoReflectionModuleBuilder *file_module =
3753 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3754 /* The table for the main module is emitted later */
3755 if (file_module != moduleb) {
3757 if (file_module->resources) {
3758 int len = mono_array_length (file_module->resources);
3759 for (j = 0; j < len; ++j) {
3760 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3761 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3769 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3770 * for the modulebuilder @moduleb.
3771 * At the end of the process, method and field tokens are fixed up and the
3772 * on-disk compressed metadata representation is created.
3775 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3777 MonoDynamicTable *table;
3778 MonoDynamicImage *assembly;
3779 MonoReflectionAssemblyBuilder *assemblyb;
3784 assemblyb = moduleb->assemblyb;
3785 assembly = moduleb->dynamic_image;
3786 domain = mono_object_domain (assemblyb);
3788 if (assembly->text_rva)
3791 assembly->text_rva = START_TEXT_RVA;
3793 if (moduleb->is_main) {
3794 mono_image_emit_manifest (moduleb);
3797 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3798 table->rows = 1; /* .<Module> */
3800 alloc_table (table, table->rows);
3802 * Set the first entry.
3804 values = table->values + table->columns;
3805 values [MONO_TYPEDEF_FLAGS] = 0;
3806 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3807 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3808 values [MONO_TYPEDEF_EXTENDS] = 0;
3809 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3810 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3813 * handle global methods
3814 * FIXME: test what to do when global methods are defined in multiple modules.
3816 if (moduleb->global_methods) {
3817 table = &assembly->tables [MONO_TABLE_METHOD];
3818 table->rows += mono_array_length (moduleb->global_methods);
3819 alloc_table (table, table->rows);
3820 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3821 mono_image_get_method_info (
3822 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3824 if (moduleb->global_fields) {
3825 table = &assembly->tables [MONO_TABLE_FIELD];
3826 table->rows += mono_array_length (moduleb->global_fields);
3827 alloc_table (table, table->rows);
3828 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3829 mono_image_get_field_info (
3830 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3833 table = &assembly->tables [MONO_TABLE_MODULE];
3834 alloc_table (table, 1);
3835 mono_image_fill_module_table (domain, moduleb, assembly);
3839 /* Collect all types into a list sorted by their table_idx */
3840 GPtrArray *types = g_ptr_array_new ();
3843 for (i = 0; i < moduleb->num_types; ++i) {
3844 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3845 collect_types (types, type);
3848 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3849 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3850 table->rows += types->len;
3851 alloc_table (table, table->rows);
3853 for (i = 0; i < types->len; ++i) {
3854 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3855 mono_image_get_type_info (domain, type, assembly);
3857 g_ptr_array_free (types, TRUE);
3861 * table->rows is already set above and in mono_image_fill_module_table.
3863 /* add all the custom attributes at the end, once all the indexes are stable */
3864 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3866 module_add_cattrs (assembly, moduleb);
3869 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3870 fixup_cattrs (assembly);
3874 * mono_image_insert_string:
3875 * @module: module builder object
3878 * Insert @str into the user string stream of @module.
3881 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3883 MonoDynamicImage *assembly;
3888 MONO_ARCH_SAVE_REGS;
3890 if (!module->dynamic_image)
3891 mono_image_module_basic_init (module);
3893 assembly = module->dynamic_image;
3895 if (assembly->save) {
3896 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3897 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3898 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3900 char *swapped = g_malloc (2 * mono_string_length (str));
3901 const char *p = (const char*)mono_string_chars (str);
3903 swap_with_size (swapped, p, 2, mono_string_length (str));
3904 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3908 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3910 mono_image_add_stream_data (&assembly->us, "", 1);
3913 idx = assembly->us.index ++;
3915 mono_g_hash_table_insert (assembly->tokens,
3916 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3918 return MONO_TOKEN_STRING | idx;
3922 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj,
3923 MonoArray *opt_param_types)
3928 klass = obj->vtable->klass;
3929 if (strcmp (klass->name, "MonoMethod") == 0) {
3930 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3931 MonoMethodSignature *sig, *old;
3932 guint32 sig_token, parent;
3935 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3937 nargs = mono_array_length (opt_param_types);
3938 old = method->signature;
3939 sig = mono_metadata_signature_alloc (
3940 &assembly->image, old->param_count + nargs);
3942 sig->hasthis = old->hasthis;
3943 sig->explicit_this = old->explicit_this;
3944 sig->call_convention = old->call_convention;
3945 sig->generic_param_count = old->generic_param_count;
3946 sig->param_count = old->param_count + nargs;
3947 sig->sentinelpos = old->param_count;
3948 sig->ret = old->ret;
3950 for (i = 0; i < old->param_count; i++)
3951 sig->params [i] = old->params [i];
3953 for (i = 0; i < nargs; i++) {
3954 MonoReflectionType *rt = mono_array_get (
3955 opt_param_types, MonoReflectionType *, i);
3956 sig->params [old->param_count + i] = rt->type;
3959 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
3960 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
3961 parent >>= MONO_TYPEDEFORREF_BITS;
3963 parent <<= MONO_MEMBERREF_PARENT_BITS;
3964 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
3966 sig_token = method_encode_signature (assembly, sig);
3967 token = mono_image_get_varargs_method_token (
3968 assembly, parent, method->name, sig_token);
3969 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
3970 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3971 ReflectionMethodBuilder rmb;
3972 guint32 parent, sig;
3974 reflection_methodbuilder_from_method_builder (&rmb, mb);
3975 rmb.opt_types = opt_param_types;
3977 sig = method_builder_encode_signature (assembly, &rmb);
3979 parent = mono_image_create_token (assembly, obj, TRUE);
3980 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
3982 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
3983 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
3985 token = mono_image_get_varargs_method_token (
3986 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
3988 g_error ("requested method token for %s\n", klass->name);
3994 * mono_image_create_token:
3995 * @assembly: a dynamic assembly
3998 * Get a token to insert in the IL code stream for the given MemberInfo.
3999 * @obj can be one of:
4000 * ConstructorBuilder
4010 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4011 gboolean create_methodspec)
4016 klass = obj->vtable->klass;
4017 if (strcmp (klass->name, "MethodBuilder") == 0) {
4018 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4020 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4021 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4023 token = mono_image_get_methodbuilder_token (assembly, mb);
4024 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4026 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4027 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4029 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4030 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4032 token = mono_image_get_ctorbuilder_token (assembly, mb);
4033 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4035 else if (strcmp (klass->name, "FieldBuilder") == 0) {
4036 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4037 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4038 if (tb->generic_params) {
4039 token = mono_image_get_generic_field_token (assembly, fb);
4041 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4044 else if (strcmp (klass->name, "TypeBuilder") == 0) {
4045 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4046 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4048 else if (strcmp (klass->name, "MonoType") == 0 ||
4049 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4050 MonoReflectionType *tb = (MonoReflectionType *)obj;
4051 token = mono_metadata_token_from_dor (
4052 mono_image_typedef_or_ref (assembly, tb->type));
4054 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
4055 MonoReflectionType *tb = (MonoReflectionType *)obj;
4056 token = mono_metadata_token_from_dor (
4057 mono_image_typedef_or_ref (assembly, tb->type));
4059 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4060 strcmp (klass->name, "MonoMethod") == 0) {
4061 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4062 if (m->method->signature->is_inflated) {
4063 if (create_methodspec)
4064 token = mono_image_get_methodspec_token (
4065 assembly, m->method);
4067 token = mono_image_get_inflated_method_token (
4068 assembly, m->method);
4069 } else if (m->method->signature->generic_param_count) {
4070 g_assert_not_reached ();
4071 } else if ((m->method->klass->image == &assembly->image) &&
4072 !m->method->klass->generic_inst) {
4073 static guint32 method_table_idx = 0xffffff;
4074 if (m->method->klass->wastypebuilder) {
4075 /* we use the same token as the one that was assigned
4076 * to the Methodbuilder.
4077 * FIXME: do the equivalent for Fields.
4079 token = m->method->token;
4082 * Each token should have a unique index, but the indexes are
4083 * assigned by managed code, so we don't know about them. An
4084 * easy solution is to count backwards...
4086 method_table_idx --;
4087 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4090 token = mono_image_get_methodref_token (assembly, m->method);
4091 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4093 else if (strcmp (klass->name, "MonoField") == 0) {
4094 MonoReflectionField *f = (MonoReflectionField *)obj;
4095 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4096 static guint32 field_table_idx = 0xffffff;
4098 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4100 token = mono_image_get_fieldref_token (assembly, f);
4101 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4103 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4104 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4105 token = mono_image_get_array_token (assembly, m);
4107 else if (strcmp (klass->name, "SignatureHelper") == 0) {
4108 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4109 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4112 g_error ("requested token for %s\n", klass->name);
4114 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
4121 guint32 import_lookup_table;
4125 guint32 import_address_table_rva;
4133 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4135 static MonoDynamicImage*
4136 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
4137 char *assembly_name, char *module_name)
4139 static const guchar entrycode [16] = {0xff, 0x25, 0};
4140 MonoDynamicImage *image;
4143 const char *version = mono_get_runtime_version ();
4146 image = GC_MALLOC (sizeof (MonoDynamicImage));
4148 image = g_new0 (MonoDynamicImage, 1);
4151 /* keep in sync with image.c */
4152 image->image.name = assembly_name;
4153 image->image.assembly_name = image->image.name; /* they may be different */
4154 image->image.module_name = module_name;
4155 image->image.version = g_strdup (version);
4156 image->image.dynamic = TRUE;
4158 image->image.references = g_new0 (MonoAssembly*, 1);
4159 image->image.references [0] = NULL;
4161 mono_image_init (&image->image);
4163 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4164 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4165 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4166 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4167 image->handleref = g_hash_table_new (NULL, NULL);
4168 image->tokens = mono_g_hash_table_new (NULL, NULL);
4169 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4170 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4171 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4172 image->gen_params = g_ptr_array_new ();
4174 string_heap_init (&image->sheap);
4175 mono_image_add_stream_data (&image->us, "", 1);
4176 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4177 /* import tables... */
4178 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4179 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4180 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4181 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4182 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4183 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4184 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4185 stream_data_align (&image->code);
4187 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4189 for (i=0; i < 64; ++i) {
4190 image->tables [i].next_idx = 1;
4191 image->tables [i].columns = table_sizes [i];
4194 image->image.assembly = (MonoAssembly*)assembly;
4195 image->run = assembly->run;
4196 image->save = assembly->save;
4202 * mono_image_basic_init:
4203 * @assembly: an assembly builder object
4205 * Create the MonoImage that represents the assembly builder and setup some
4206 * of the helper hash table and the basic metadata streams.
4209 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4211 MonoDynamicAssembly *assembly;
4212 MonoDynamicImage *image;
4214 MONO_ARCH_SAVE_REGS;
4216 if (assemblyb->dynamic_assembly)
4220 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4222 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4225 assembly->assembly.dynamic = TRUE;
4226 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4227 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4228 if (assemblyb->culture)
4229 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4231 assembly->assembly.aname.culture = g_strdup ("");
4233 assembly->run = assemblyb->access != 2;
4234 assembly->save = assemblyb->access != 1;
4236 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4237 assembly->assembly.aname.name = image->image.name;
4238 assembly->assembly.image = &image->image;
4240 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4241 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4245 calc_section_size (MonoDynamicImage *assembly)
4249 /* alignment constraints */
4250 assembly->code.index += 3;
4251 assembly->code.index &= ~3;
4252 assembly->meta_size += 3;
4253 assembly->meta_size &= ~3;
4254 assembly->resources.index += 3;
4255 assembly->resources.index &= ~3;
4257 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4258 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4261 if (assembly->win32_res) {
4262 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4264 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4265 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4269 assembly->sections [MONO_SECTION_RELOC].size = 12;
4270 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4280 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4284 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4286 ResTreeNode *t1 = (ResTreeNode*)a;
4287 ResTreeNode *t2 = (ResTreeNode*)b;
4289 return t1->id - t2->id;
4293 * resource_tree_create:
4295 * Organize the resources into a resource tree.
4297 static ResTreeNode *
4298 resource_tree_create (MonoArray *win32_resources)
4300 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4304 tree = g_new0 (ResTreeNode, 1);
4306 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4307 MonoReflectionWin32Resource *win32_res =
4308 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4312 lang_node = g_new0 (ResTreeNode, 1);
4313 lang_node->id = win32_res->lang_id;
4314 lang_node->win32_res = win32_res;
4316 /* Create type node if neccesary */
4318 for (l = tree->children; l; l = l->next)
4319 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4320 type_node = (ResTreeNode*)l->data;
4325 type_node = g_new0 (ResTreeNode, 1);
4326 type_node->id = win32_res->res_type;
4329 * The resource types have to be sorted otherwise
4330 * Windows Explorer can't display the version information.
4332 tree->children = g_slist_insert_sorted (tree->children, type_node,
4333 resource_tree_compare_by_id);
4336 /* Create res node if neccesary */
4338 for (l = type_node->children; l; l = l->next)
4339 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4340 res_node = (ResTreeNode*)l->data;
4345 res_node = g_new0 (ResTreeNode, 1);
4346 res_node->id = win32_res->res_id;
4347 type_node->children = g_slist_append (type_node->children, res_node);
4350 res_node->children = g_slist_append (res_node->children, lang_node);
4357 * resource_tree_encode:
4359 * Encode the resource tree into the format used in the PE file.
4362 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4365 MonoPEResourceDir dir;
4366 MonoPEResourceDirEntry dir_entry;
4367 MonoPEResourceDataEntry data_entry;
4371 * For the format of the resource directory, see the article
4372 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4376 memset (&dir, 0, sizeof (dir));
4377 memset (&dir_entry, 0, sizeof (dir_entry));
4378 memset (&data_entry, 0, sizeof (data_entry));
4380 g_assert (sizeof (dir) == 16);
4381 g_assert (sizeof (dir_entry) == 8);
4382 g_assert (sizeof (data_entry) == 16);
4384 node->offset = p - begin;
4386 /* IMAGE_RESOURCE_DIRECTORY */
4387 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4389 memcpy (p, &dir, sizeof (dir));
4392 /* Reserve space for entries */
4394 p += sizeof (dir_entry) * dir.res_id_entries;
4396 /* Write children */
4397 for (l = node->children; l; l = l->next) {
4398 ResTreeNode *child = (ResTreeNode*)l->data;
4400 if (child->win32_res) {
4402 child->offset = p - begin;
4404 /* IMAGE_RESOURCE_DATA_ENTRY */
4405 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4406 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4408 memcpy (p, &data_entry, sizeof (data_entry));
4409 p += sizeof (data_entry);
4411 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4412 p += data_entry.rde_size;
4415 resource_tree_encode (child, begin, p, &p);
4418 /* IMAGE_RESOURCE_ENTRY */
4419 for (l = node->children; l; l = l->next) {
4420 ResTreeNode *child = (ResTreeNode*)l->data;
4421 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4423 dir_entry.is_dir = child->win32_res ? 0 : 1;
4424 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4426 memcpy (entries, &dir_entry, sizeof (dir_entry));
4427 entries += sizeof (dir_entry);
4434 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4439 MonoReflectionWin32Resource *win32_res;
4442 if (!assemblyb->win32_resources)
4446 * Resources are stored in a three level tree inside the PE file.
4447 * - level one contains a node for each type of resource
4448 * - level two contains a node for each resource
4449 * - level three contains a node for each instance of a resource for a
4450 * specific language.
4453 tree = resource_tree_create (assemblyb->win32_resources);
4455 /* Estimate the size of the encoded tree */
4457 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4458 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4459 size += mono_array_length (win32_res->res_data);
4461 /* Directory structure */
4462 size += mono_array_length (assemblyb->win32_resources) * 256;
4463 p = buf = g_malloc (size);
4465 resource_tree_encode (tree, p, p, &p);
4467 g_assert (p - buf < size);
4469 assembly->win32_res = g_malloc (p - buf);
4470 assembly->win32_res_size = p - buf;
4471 memcpy (assembly->win32_res, buf, p - buf);
4477 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4479 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4482 p += sizeof (MonoPEResourceDir);
4483 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4484 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4485 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4486 if (dir_entry->is_dir)
4487 fixup_resource_directory (res_section, child, rva);
4489 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4490 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4493 p += sizeof (MonoPEResourceDirEntry);
4498 * mono_image_create_pefile:
4499 * @mb: a module builder object
4501 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4502 * assembly->pefile where it can be easily retrieved later in chunks.
4505 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4506 MonoMSDOSHeader *msdos;
4507 MonoDotNetHeader *header;
4508 MonoSectionTable *section;
4509 MonoCLIHeader *cli_header;
4510 guint32 size, image_size, virtual_base, text_offset;
4511 guint32 header_start, section_start, file_offset, virtual_offset;
4512 MonoDynamicImage *assembly;
4513 MonoReflectionAssemblyBuilder *assemblyb;
4514 MonoDynamicStream *pefile;
4516 guint32 *rva, value;
4519 static const unsigned char msheader[] = {
4520 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4521 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4524 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4525 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4526 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4527 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4530 assemblyb = mb->assemblyb;
4532 mono_image_basic_init (assemblyb);
4533 assembly = mb->dynamic_image;
4535 /* already created */
4536 if (assembly->pefile.index)
4539 mono_image_build_metadata (mb);
4541 if (mb->is_main && assemblyb->resources) {
4542 int len = mono_array_length (assemblyb->resources);
4543 for (i = 0; i < len; ++i)
4544 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4547 if (mb->resources) {
4548 int len = mono_array_length (mb->resources);
4549 for (i = 0; i < len; ++i)
4550 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4553 build_compressed_metadata (assembly);
4556 assembly_add_win32_resources (assembly, assemblyb);
4558 nsections = calc_section_size (assembly);
4560 pefile = &assembly->pefile;
4562 /* The DOS header and stub */
4563 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4564 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4566 /* the dotnet header */
4567 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4569 /* the section tables */
4570 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4572 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4573 virtual_offset = VIRT_ALIGN;
4576 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4577 if (!assembly->sections [i].size)
4580 file_offset += FILE_ALIGN - 1;
4581 file_offset &= ~(FILE_ALIGN - 1);
4582 virtual_offset += VIRT_ALIGN - 1;
4583 virtual_offset &= ~(VIRT_ALIGN - 1);
4585 assembly->sections [i].offset = file_offset;
4586 assembly->sections [i].rva = virtual_offset;
4588 file_offset += assembly->sections [i].size;
4589 virtual_offset += assembly->sections [i].size;
4590 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4593 file_offset += FILE_ALIGN - 1;
4594 file_offset &= ~(FILE_ALIGN - 1);
4595 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4597 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4599 /* back-patch info */
4600 msdos = (MonoMSDOSHeader*)pefile->data;
4601 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4602 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4603 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4605 header = (MonoDotNetHeader*)(pefile->data + header_start);
4606 header->pesig [0] = 'P';
4607 header->pesig [1] = 'E';
4609 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4610 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4611 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4612 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4613 if (assemblyb->pekind == 1) {
4615 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4618 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4621 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4623 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4624 header->pe.pe_major = 6;
4625 header->pe.pe_minor = 0;
4626 size = assembly->sections [MONO_SECTION_TEXT].size;
4627 size += FILE_ALIGN - 1;
4628 size &= ~(FILE_ALIGN - 1);
4629 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4630 size = assembly->sections [MONO_SECTION_RSRC].size;
4631 size += FILE_ALIGN - 1;
4632 size &= ~(FILE_ALIGN - 1);
4633 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4634 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4635 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4636 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4637 /* pe_rva_entry_point always at the beginning of the text section */
4638 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4640 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4641 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4642 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4643 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4644 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4645 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4646 size = section_start;
4647 size += FILE_ALIGN - 1;
4648 size &= ~(FILE_ALIGN - 1);
4649 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4651 size += VIRT_ALIGN - 1;
4652 size &= ~(VIRT_ALIGN - 1);
4653 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4656 // Translate the PEFileKind value to the value expected by the Windows loader
4662 // PEFileKinds.Dll == 1
4663 // PEFileKinds.ConsoleApplication == 2
4664 // PEFileKinds.WindowApplication == 3
4667 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4668 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4670 if (assemblyb->pekind == 3)
4675 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4677 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4678 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4679 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4680 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4681 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4682 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4684 /* fill data directory entries */
4686 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4687 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4689 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4690 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4692 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4693 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4694 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4695 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4696 /* patch imported function RVA name */
4697 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4698 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4700 /* the import table */
4701 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4702 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4703 /* patch imported dll RVA name and other entries in the dir */
4704 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4705 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4706 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4707 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4708 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4709 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4711 p = (assembly->code.data + assembly->ilt_offset);
4712 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4713 *p++ = (value) & 0xff;
4714 *p++ = (value >> 8) & (0xff);
4715 *p++ = (value >> 16) & (0xff);
4716 *p++ = (value >> 24) & (0xff);
4718 /* the CLI header info */
4719 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4720 cli_header->ch_size = GUINT32_FROM_LE (72);
4721 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4722 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4723 if (assemblyb->entry_point) {
4724 guint32 table_idx = 0;
4725 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4726 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4727 table_idx = methodb->table_idx;
4730 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4731 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4734 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4735 /* The embedded managed resources */
4736 text_offset = assembly->text_rva + assembly->code.index;
4737 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4738 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4739 text_offset += assembly->resources.index;
4740 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4741 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4742 text_offset += assembly->meta_size;
4743 if (assembly->strong_name_size) {
4744 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4745 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4746 text_offset += assembly->strong_name_size;
4749 /* write the section tables and section content */
4750 section = (MonoSectionTable*)(pefile->data + section_start);
4751 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4752 static const char *section_names [] = {
4753 ".text", ".rsrc", ".reloc"
4755 if (!assembly->sections [i].size)
4757 strcpy (section->st_name, section_names [i]);
4758 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4759 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4760 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4761 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4762 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4763 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4764 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4766 case MONO_SECTION_TEXT:
4767 /* patch entry point */
4768 p = (assembly->code.data + 2);
4769 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4770 *p++ = (value) & 0xff;
4771 *p++ = (value >> 8) & 0xff;
4772 *p++ = (value >> 16) & 0xff;
4773 *p++ = (value >> 24) & 0xff;
4775 text_offset = assembly->sections [i].offset;
4776 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4777 text_offset += assembly->code.index;
4778 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4779 text_offset += assembly->resources.index;
4780 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4781 text_offset += assembly->meta_size;
4782 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4784 g_free (assembly->image.raw_metadata);
4786 case MONO_SECTION_RELOC:
4787 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4788 *rva = GUINT32_FROM_LE (assembly->text_rva);
4790 *rva = GUINT32_FROM_LE (12);
4792 data16 = (guint16*)rva;
4794 * the entrypoint is always at the start of the text section
4795 * 3 is IMAGE_REL_BASED_HIGHLOW
4796 * 2 is patch_size_rva - text_rva
4798 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4800 *data16 = 0; /* terminate */
4802 case MONO_SECTION_RSRC:
4803 if (assembly->win32_res) {
4804 text_offset = assembly->sections [i].offset;
4806 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4807 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4809 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4813 g_assert_not_reached ();
4818 /* check that the file is properly padded */
4821 FILE *f = fopen ("mypetest.exe", "w");
4822 fwrite (pefile->data, pefile->index, 1, f);
4828 MonoReflectionModule *
4829 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4833 MonoImageOpenStatus status;
4834 MonoDynamicAssembly *assembly;
4836 name = mono_string_to_utf8 (fileName);
4838 image = mono_image_open (name, &status);
4841 if (status == MONO_IMAGE_ERROR_ERRNO)
4842 exc = mono_get_exception_file_not_found (fileName);
4844 exc = mono_get_exception_bad_image_format (name);
4846 mono_raise_exception (exc);
4851 assembly = ab->dynamic_assembly;
4852 image->assembly = (MonoAssembly*)assembly;
4854 mono_assembly_load_references (image, &status);
4856 mono_image_close (image);
4857 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4860 return mono_module_get_object (mono_domain_get (), image);
4864 * We need to return always the same object for MethodInfo, FieldInfo etc..
4865 * but we need to consider the reflected type.
4866 * type uses a different hash, since it uses custom hash/equal functions.
4871 MonoClass *refclass;
4875 reflected_equal (gconstpointer a, gconstpointer b) {
4876 const ReflectedEntry *ea = a;
4877 const ReflectedEntry *eb = b;
4879 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4883 reflected_hash (gconstpointer a) {
4884 const ReflectedEntry *ea = a;
4885 return GPOINTER_TO_UINT (ea->item);
4888 #define CHECK_OBJECT(t,p,k) \
4894 mono_domain_lock (domain); \
4895 if (!domain->refobject_hash) \
4896 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4897 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4898 mono_domain_unlock (domain); \
4904 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4906 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4909 #define CACHE_OBJECT(p,o,k) \
4911 ReflectedEntry *e = ALLOC_REFENTRY; \
4913 e->refclass = (k); \
4914 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4915 mono_domain_unlock (domain); \
4919 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4921 /* this is done only once */
4922 mono_domain_lock (domain);
4923 CACHE_OBJECT (assembly, res, NULL);
4927 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4929 /* this is done only once */
4930 mono_domain_lock (domain);
4931 CACHE_OBJECT (module, res, NULL);
4935 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4937 MonoDynamicImage *image = moduleb->dynamic_image;
4938 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4941 * FIXME: we already created an image in mono_image_basic_init (), but
4942 * we don't know which module it belongs to, since that is only
4943 * determined at assembly save time.
4945 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
4946 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4948 moduleb->module.image = &image->image;
4949 moduleb->dynamic_image = image;
4950 register_module (mono_object_domain (moduleb), moduleb, image);
4955 * mono_assembly_get_object:
4956 * @domain: an app domain
4957 * @assembly: an assembly
4959 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4961 MonoReflectionAssembly*
4962 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4964 static MonoClass *System_Reflection_Assembly;
4965 MonoReflectionAssembly *res;
4967 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4968 if (!System_Reflection_Assembly)
4969 System_Reflection_Assembly = mono_class_from_name (
4970 mono_defaults.corlib, "System.Reflection", "Assembly");
4971 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4972 res->assembly = assembly;
4973 CACHE_OBJECT (assembly, res, NULL);
4979 MonoReflectionModule*
4980 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4982 static MonoClass *System_Reflection_Module;
4983 MonoReflectionModule *res;
4985 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4986 if (!System_Reflection_Module)
4987 System_Reflection_Module = mono_class_from_name (
4988 mono_defaults.corlib, "System.Reflection", "Module");
4989 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4992 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4994 res->fqname = mono_string_new (domain, image->name);
4995 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4996 res->scopename = mono_string_new (domain, image->module_name);
4998 mono_image_addref (image);
5000 CACHE_OBJECT (image, res, NULL);
5004 MonoReflectionModule*
5005 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5007 static MonoClass *System_Reflection_Module;
5008 MonoReflectionModule *res;
5009 MonoTableInfo *table;
5010 guint32 cols [MONO_FILE_SIZE];
5012 guint32 i, name_idx;
5015 if (!System_Reflection_Module)
5016 System_Reflection_Module = mono_class_from_name (
5017 mono_defaults.corlib, "System.Reflection", "Module");
5018 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5020 table = &image->tables [MONO_TABLE_FILE];
5021 g_assert (table_index < table->rows);
5022 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5025 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5026 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5028 /* Check whenever the row has a corresponding row in the moduleref table */
5029 table = &image->tables [MONO_TABLE_MODULEREF];
5030 for (i = 0; i < table->rows; ++i) {
5031 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5032 val = mono_metadata_string_heap (image, name_idx);
5033 if (strcmp (val, name) == 0)
5034 res->image = image->modules [i];
5037 res->fqname = mono_string_new (domain, name);
5038 res->name = mono_string_new (domain, name);
5039 res->scopename = mono_string_new (domain, name);
5040 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5046 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5048 if ((t1->type != t2->type) ||
5049 (t1->byref != t2->byref))
5053 case MONO_TYPE_VOID:
5054 case MONO_TYPE_BOOLEAN:
5055 case MONO_TYPE_CHAR:
5066 case MONO_TYPE_STRING:
5069 case MONO_TYPE_OBJECT:
5070 case MONO_TYPE_TYPEDBYREF:
5072 case MONO_TYPE_VALUETYPE:
5073 case MONO_TYPE_CLASS:
5074 case MONO_TYPE_SZARRAY:
5075 return t1->data.klass == t2->data.klass;
5077 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5078 case MONO_TYPE_ARRAY:
5079 if (t1->data.array->rank != t2->data.array->rank)
5081 return t1->data.array->eklass == t2->data.array->eklass;
5082 case MONO_TYPE_GENERICINST: {
5084 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5086 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5088 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5089 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5095 case MONO_TYPE_MVAR:
5096 return t1->data.generic_param == t2->data.generic_param;
5098 g_error ("implement type compare for %0x!", t1->type);
5106 mymono_metadata_type_hash (MonoType *t1)
5112 hash |= t1->byref << 6; /* do not collide with t1->type values */
5114 case MONO_TYPE_VALUETYPE:
5115 case MONO_TYPE_CLASS:
5116 case MONO_TYPE_SZARRAY:
5117 /* check if the distribution is good enough */
5118 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5120 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5125 static MonoReflectionGenericInst*
5126 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5128 static MonoClass *System_Reflection_MonoGenericInst;
5129 MonoReflectionGenericInst *res;
5130 MonoGenericInst *ginst;
5133 if (!System_Reflection_MonoGenericInst) {
5134 System_Reflection_MonoGenericInst = mono_class_from_name (
5135 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5136 g_assert (System_Reflection_MonoGenericInst);
5139 ginst = geninst->data.generic_inst;
5140 gklass = mono_class_from_mono_type (ginst->generic_type);
5142 mono_class_init (ginst->klass);
5144 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5146 res->type.type = geninst;
5147 if (gklass->wastypebuilder && gklass->reflection_info)
5148 res->generic_type = gklass->reflection_info;
5150 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5156 * mono_type_get_object:
5157 * @domain: an app domain
5160 * Return an System.MonoType object representing the type @type.
5163 mono_type_get_object (MonoDomain *domain, MonoType *type)
5165 MonoReflectionType *res;
5166 MonoClass *klass = mono_class_from_mono_type (type);
5168 mono_domain_lock (domain);
5169 if (!domain->type_hash)
5170 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5171 (GCompareFunc)mymono_metadata_type_equal);
5172 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5173 mono_domain_unlock (domain);
5176 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5177 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5178 mono_g_hash_table_insert (domain->type_hash, type, res);
5179 mono_domain_unlock (domain);
5182 if (klass->reflection_info && !klass->wastypebuilder) {
5183 /* g_assert_not_reached (); */
5184 /* should this be considered an error condition? */
5186 mono_domain_unlock (domain);
5187 return klass->reflection_info;
5190 mono_class_init (klass);
5191 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5193 mono_g_hash_table_insert (domain->type_hash, type, res);
5194 mono_domain_unlock (domain);
5199 * mono_method_get_object:
5200 * @domain: an app domain
5202 * @refclass: the reflected type (can be NULL)
5204 * Return an System.Reflection.MonoMethod object representing the method @method.
5206 MonoReflectionMethod*
5207 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5210 * We use the same C representation for methods and constructors, but the type
5211 * name in C# is different.
5215 MonoReflectionMethod *ret;
5218 refclass = method->klass;
5220 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5221 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5222 cname = "MonoCMethod";
5224 cname = "MonoMethod";
5225 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5227 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5228 ret->method = method;
5229 ret->name = mono_string_new (domain, method->name);
5230 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5231 CACHE_OBJECT (method, ret, refclass);
5236 * mono_field_get_object:
5237 * @domain: an app domain
5241 * Return an System.Reflection.MonoField object representing the field @field
5244 MonoReflectionField*
5245 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5247 MonoReflectionField *res;
5250 CHECK_OBJECT (MonoReflectionField *, field, klass);
5251 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5252 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5255 res->name = mono_string_new (domain, field->name);
5256 if (field->generic_info)
5257 res->attrs = field->generic_info->generic_type->attrs;
5259 res->attrs = field->type->attrs;
5260 res->type = mono_type_get_object (domain, field->type);
5261 CACHE_OBJECT (field, res, klass);
5266 * mono_property_get_object:
5267 * @domain: an app domain
5269 * @property: a property
5271 * Return an System.Reflection.MonoProperty object representing the property @property
5274 MonoReflectionProperty*
5275 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5277 MonoReflectionProperty *res;
5280 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5281 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5282 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5284 res->property = property;
5285 CACHE_OBJECT (property, res, klass);
5290 * mono_event_get_object:
5291 * @domain: an app domain
5295 * Return an System.Reflection.MonoEvent object representing the event @event
5298 MonoReflectionEvent*
5299 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5301 MonoReflectionEvent *res;
5304 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5305 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5306 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5309 CACHE_OBJECT (event, res, klass);
5314 * mono_param_get_objects:
5315 * @domain: an app domain
5318 * Return an System.Reflection.ParameterInfo array object representing the parameters
5319 * in the method @method.
5322 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5324 static MonoClass *System_Reflection_ParameterInfo;
5325 static MonoClassField *dbnull_value_field;
5327 MonoArray *res = NULL;
5328 MonoReflectionMethod *member = NULL;
5329 MonoReflectionParameter *param = NULL;
5333 if (!dbnull_value_field) {
5334 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5335 mono_class_init (klass);
5336 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5337 g_assert (dbnull_value_field);
5340 if (!System_Reflection_ParameterInfo)
5341 System_Reflection_ParameterInfo = mono_class_from_name (
5342 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5344 if (!method->signature->param_count)
5345 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5347 /* Note: the cache is based on the address of the signature into the method
5348 * since we already cache MethodInfos with the method as keys.
5350 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5352 member = mono_method_get_object (domain, method, NULL);
5353 names = g_new (char *, method->signature->param_count);
5354 mono_method_get_param_names (method, (const char **) names);
5356 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5357 for (i = 0; i < method->signature->param_count; ++i) {
5358 param = (MonoReflectionParameter *)mono_object_new (domain,
5359 System_Reflection_ParameterInfo);
5360 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5361 param->DefaultValueImpl = mono_field_get_value_object (domain, dbnull_value_field, NULL); /* FIXME */
5362 param->MemberImpl = (MonoObject*)member;
5363 param->NameImpl = mono_string_new (domain, names [i]);
5364 param->PositionImpl = i;
5365 param->AttrsImpl = method->signature->params [i]->attrs;
5366 mono_array_set (res, gpointer, i, param);
5369 CACHE_OBJECT (&(method->signature), res, NULL);
5374 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5378 memset (assembly, 0, sizeof (MonoAssemblyName));
5380 assembly->culture = "";
5381 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5383 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5386 while (*p == ' ' || *p == ',') {
5395 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5397 assembly->major = strtoul (p, &s, 10);
5398 if (s == p || *s != '.')
5401 assembly->minor = strtoul (p, &s, 10);
5402 if (s == p || *s != '.')
5405 assembly->build = strtoul (p, &s, 10);
5406 if (s == p || *s != '.')
5409 assembly->revision = strtoul (p, &s, 10);
5413 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5415 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5416 assembly->culture = "";
5419 assembly->culture = p;
5420 while (*p && *p != ',') {
5424 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5426 if (strncmp (p, "null", 4) == 0) {
5431 while (*p && *p != ',') {
5434 len = (p - start + 1);
5435 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5436 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5437 g_strlcpy (assembly->public_key_token, start, len);
5440 while (*p && *p != ',')
5444 while (*p == ' ' || *p == ',') {
5458 * mono_reflection_parse_type:
5461 * Parse a type name as accepted by the GetType () method and output the info
5462 * extracted in the info structure.
5463 * the name param will be mangled, so, make a copy before passing it to this function.
5464 * The fields in info will be valid until the memory pointed to by name is valid.
5465 * Returns 0 on parse error.
5466 * See also mono_type_get_name () below.
5469 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5471 char *start, *p, *w, *last_point, *startn;
5472 int in_modifiers = 0;
5473 int isbyref = 0, rank;
5475 start = p = w = name;
5477 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5478 info->name = info->name_space = NULL;
5479 info->nested = NULL;
5480 info->modifiers = NULL;
5482 /* last_point separates the namespace from the name */
5488 *p = 0; /* NULL terminate the name */
5490 info->nested = g_list_append (info->nested, startn);
5491 /* we have parsed the nesting namespace + name */
5495 info->name_space = start;
5497 info->name = last_point + 1;
5499 info->name_space = (char *)"";
5525 info->name_space = start;
5527 info->name = last_point + 1;
5529 info->name_space = (char *)"";
5536 if (isbyref) /* only one level allowed by the spec */
5539 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5543 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5554 else if (*p != '*') /* '*' means unknown lower bound */
5560 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5572 return 0; /* missing assembly name */
5573 if (!assembly_name_to_aname (&info->assembly, p))
5580 if (info->assembly.name)
5583 *w = 0; /* terminate class name */
5584 if (!info->name || !*info->name)
5586 /* add other consistency checks */
5591 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5598 image = mono_defaults.corlib;
5601 klass = mono_class_from_name_case (image, info->name_space, info->name);
5603 klass = mono_class_from_name (image, info->name_space, info->name);
5606 for (mod = info->nested; mod; mod = mod->next) {
5609 mono_class_init (klass);
5610 nested = klass->nested_classes;
5613 klass = nested->data;
5615 if (g_strcasecmp (klass->name, mod->data) == 0)
5618 if (strcmp (klass->name, mod->data) == 0)
5622 nested = nested->next;
5629 mono_class_init (klass);
5630 for (mod = info->modifiers; mod; mod = mod->next) {
5631 modval = GPOINTER_TO_UINT (mod->data);
5632 if (!modval) { /* byref: must be last modifier */
5633 return &klass->this_arg;
5634 } else if (modval == -1) {
5635 klass = mono_ptr_class_get (&klass->byval_arg);
5636 } else { /* array rank */
5637 klass = mono_array_class_get (klass, modval);
5639 mono_class_init (klass);
5642 return &klass->byval_arg;
5646 * mono_reflection_get_type:
5647 * @image: a metadata context
5648 * @info: type description structure
5649 * @ignorecase: flag for case-insensitive string compares
5650 * @type_resolve: whenever type resolve was already tried
5652 * Build a MonoType from the type description in @info.
5657 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5660 MonoReflectionAssembly *assembly;
5664 type = mono_reflection_get_type_internal (image, info, ignorecase);
5667 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5670 /* FIXME: Enabling this causes regressions (#65577) */
5676 *type_resolve = TRUE;
5680 /* Reconstruct the type name */
5681 fullName = g_string_new ("");
5682 if (info->name_space && (info->name_space [0] != '\0'))
5683 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5685 g_string_printf (fullName, info->name);
5686 for (mod = info->nested; mod; mod = mod->next)
5687 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5690 mono_domain_try_type_resolve (
5691 mono_domain_get (), fullName->str, NULL);
5692 if (assembly && (!image || (assembly->assembly->image == image))) {
5694 if (assembly->assembly->dynamic) {
5695 /* Enumerate all modules */
5696 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5700 if (abuilder->modules) {
5701 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5702 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5703 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5709 if (!type && abuilder->loaded_modules) {
5710 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5711 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5712 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5719 type = mono_reflection_get_type_internal (assembly->assembly->image,
5722 g_string_free (fullName, TRUE);
5727 * mono_reflection_type_from_name:
5729 * @image: a metadata context (can be NULL).
5731 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5732 * it defaults to get the type from @image or, if @image is NULL or loading
5733 * from it fails, uses corlib.
5737 mono_reflection_type_from_name (char *name, MonoImage *image)
5740 MonoTypeNameParse info;
5741 MonoAssembly *assembly;
5743 gboolean type_resolve = FALSE;
5745 /* Make a copy since parse_type modifies its argument */
5746 tmp = g_strdup (name);
5748 /*g_print ("requested type %s\n", str);*/
5749 if (!mono_reflection_parse_type (tmp, &info)) {
5751 g_list_free (info.modifiers);
5752 g_list_free (info.nested);
5756 if (info.assembly.name) {
5757 assembly = mono_assembly_loaded (&info.assembly);
5759 /* then we must load the assembly ourselve - see #60439 */
5760 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5763 g_list_free (info.modifiers);
5764 g_list_free (info.nested);
5768 image = assembly->image;
5769 } else if (image == NULL) {
5770 image = mono_defaults.corlib;
5773 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5774 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5775 image = mono_defaults.corlib;
5776 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5780 g_list_free (info.modifiers);
5781 g_list_free (info.nested);
5786 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5788 int slen, type = t->type;
5793 case MONO_TYPE_BOOLEAN: {
5794 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5799 case MONO_TYPE_CHAR:
5801 case MONO_TYPE_I2: {
5802 guint16 *val = g_malloc (sizeof (guint16));
5807 #if SIZEOF_VOID_P == 4
5813 case MONO_TYPE_I4: {
5814 guint32 *val = g_malloc (sizeof (guint32));
5819 #if SIZEOF_VOID_P == 8
5820 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5825 case MONO_TYPE_I8: {
5826 guint64 *val = g_malloc (sizeof (guint64));
5831 case MONO_TYPE_VALUETYPE:
5832 if (t->data.klass->enumtype) {
5833 type = t->data.klass->enum_basetype->type;
5836 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5839 case MONO_TYPE_STRING:
5840 if (*p == (char)0xFF) {
5844 slen = mono_metadata_decode_value (p, &p);
5846 return mono_string_new_len (mono_domain_get (), p, slen);
5847 case MONO_TYPE_CLASS: {
5850 if (*p == (char)0xFF) {
5855 slen = mono_metadata_decode_value (p, &p);
5856 n = g_memdup (p, slen + 1);
5858 t = mono_reflection_type_from_name (n, image);
5860 g_warning ("Cannot load type '%s'", n);
5864 return mono_type_get_object (mono_domain_get (), t);
5868 case MONO_TYPE_OBJECT: {
5871 MonoClass *subc = NULL;
5876 } else if (subt == 0x0E) {
5877 type = MONO_TYPE_STRING;
5879 } else if (subt == 0x55) {
5882 slen = mono_metadata_decode_value (p, &p);
5883 n = g_memdup (p, slen + 1);
5885 t = mono_reflection_type_from_name (n, image);
5887 g_warning ("Cannot load type '%s'", n);
5890 subc = mono_class_from_mono_type (t);
5891 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5892 MonoType simple_type = {{0}};
5893 simple_type.type = subt;
5894 subc = mono_class_from_mono_type (&simple_type);
5896 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5898 val = load_cattr_value (image, &subc->byval_arg, p, end);
5899 obj = mono_object_new (mono_domain_get (), subc);
5900 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5904 case MONO_TYPE_SZARRAY:
5907 guint32 i, alen, basetype;
5910 if (alen == 0xffffffff) {
5914 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5915 basetype = t->data.klass->byval_arg.type;
5920 case MONO_TYPE_BOOLEAN:
5921 for (i=0;i<alen;i++)
5923 MonoBoolean val=*p++;
5924 mono_array_set(arr,MonoBoolean,i,val);
5927 case MONO_TYPE_CHAR:
5930 for (i=0;i<alen;i++)
5932 guint16 val=read16(p);
5933 mono_array_set(arr,guint16,i,val);
5940 for (i=0;i<alen;i++)
5942 guint32 val=read32(p);
5943 mono_array_set(arr,guint32,i,val);
5950 for (i=0;i<alen;i++)
5952 guint64 val=read64(p);
5953 mono_array_set(arr,guint64,i,val);
5957 case MONO_TYPE_CLASS:
5958 case MONO_TYPE_OBJECT:
5959 case MONO_TYPE_STRING:
5960 for (i = 0; i < alen; i++) {
5961 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5962 mono_array_set (arr, gpointer, i, item);
5966 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5972 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5978 type_is_reference (MonoType *type)
5980 switch (type->type) {
5981 case MONO_TYPE_BOOLEAN:
5982 case MONO_TYPE_CHAR:
5995 case MONO_TYPE_VALUETYPE:
6003 free_param_data (MonoMethodSignature *sig, void **params) {
6005 for (i = 0; i < sig->param_count; ++i) {
6006 if (!type_is_reference (sig->params [i]))
6007 g_free (params [i]);
6012 * Find the method index in the metadata methodDef table.
6013 * Later put these three helper methods in metadata and export them.
6016 find_method_index (MonoMethod *method) {
6017 MonoClass *klass = method->klass;
6020 for (i = 0; i < klass->method.count; ++i) {
6021 if (method == klass->methods [i])
6022 return klass->method.first + 1 + i;
6028 * Find the field index in the metadata FieldDef table.
6031 find_field_index (MonoClass *klass, MonoClassField *field) {
6034 for (i = 0; i < klass->field.count; ++i) {
6035 if (field == &klass->fields [i])
6036 return klass->field.first + 1 + i;
6042 * Find the property index in the metadata Property table.
6045 find_property_index (MonoClass *klass, MonoProperty *property) {
6048 for (i = 0; i < klass->property.count; ++i) {
6049 if (property == &klass->properties [i])
6050 return klass->property.first + 1 + i;
6056 * Find the event index in the metadata Event table.
6059 find_event_index (MonoClass *klass, MonoEvent *event) {
6062 for (i = 0; i < klass->event.count; ++i) {
6063 if (event == &klass->events [i])
6064 return klass->event.first + 1 + i;
6070 create_custom_attr (MonoImage *image, MonoMethod *method,
6071 const char *data, guint32 len)
6073 const char *p = data;
6075 guint32 i, j, num_named;
6079 mono_class_init (method->klass);
6082 attr = mono_object_new (mono_domain_get (), method->klass);
6083 mono_runtime_invoke (method, attr, NULL, NULL);
6087 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6090 /*g_print ("got attr %s\n", method->klass->name);*/
6092 params = g_new (void*, method->signature->param_count);
6096 for (i = 0; i < method->signature->param_count; ++i) {
6097 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6101 attr = mono_object_new (mono_domain_get (), method->klass);
6102 mono_runtime_invoke (method, attr, params, NULL);
6103 free_param_data (method->signature, params);
6105 num_named = read16 (named);
6107 for (j = 0; j < num_named; j++) {
6109 char *name, named_type, data_type;
6110 named_type = *named++;
6111 data_type = *named++; /* type of data */
6112 if (data_type == 0x55) {
6115 type_len = mono_metadata_decode_blob_size (named, &named);
6116 type_name = g_malloc (type_len + 1);
6117 memcpy (type_name, named, type_len);
6118 type_name [type_len] = 0;
6120 /* FIXME: lookup the type and check type consistency */
6121 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6122 /* this seems to be the type of the element of the array */
6123 /* g_print ("skipping 0x%02x after prop\n", *named); */
6126 name_len = mono_metadata_decode_blob_size (named, &named);
6127 name = g_malloc (name_len + 1);
6128 memcpy (name, named, name_len);
6129 name [name_len] = 0;
6131 if (named_type == 0x53) {
6132 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6133 void *val = load_cattr_value (image, field->type, named, &named);
6134 mono_field_set_value (attr, field, val);
6135 if (!type_is_reference (field->type))
6137 } else if (named_type == 0x54) {
6140 MonoType *prop_type;
6142 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6143 /* can we have more that 1 arg in a custom attr named property? */
6144 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6145 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6146 mono_property_set_value (prop, attr, pparams, NULL);
6147 if (!type_is_reference (prop_type))
6148 g_free (pparams [0]);
6157 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6164 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6165 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6166 for (i = 0; i < cinfo->num_attrs; ++i) {
6167 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6168 mono_array_set (result, gpointer, i, attr);
6174 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6176 guint32 mtoken, i, len;
6177 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6179 MonoCustomAttrInfo *ainfo;
6180 GList *tmp, *list = NULL;
6183 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6185 i = mono_metadata_custom_attrs_from_index (image, idx);
6189 while (i < ca->rows) {
6190 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6192 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6195 len = g_list_length (list);
6198 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6199 ainfo->num_attrs = len;
6200 ainfo->image = image;
6201 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6202 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6203 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6204 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6205 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6206 mtoken |= MONO_TOKEN_METHOD_DEF;
6208 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6209 mtoken |= MONO_TOKEN_MEMBER_REF;
6212 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6215 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6216 if (!ainfo->attrs [i].ctor)
6217 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6218 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6219 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6220 ainfo->attrs [i].data = data;
6228 mono_custom_attrs_from_method (MonoMethod *method)
6230 MonoCustomAttrInfo *cinfo;
6233 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6235 idx = find_method_index (method);
6236 idx <<= MONO_CUSTOM_ATTR_BITS;
6237 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6238 return mono_custom_attrs_from_index (method->klass->image, idx);
6242 mono_custom_attrs_from_class (MonoClass *klass)
6244 MonoCustomAttrInfo *cinfo;
6247 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6249 idx = mono_metadata_token_index (klass->type_token);
6250 idx <<= MONO_CUSTOM_ATTR_BITS;
6251 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6252 return mono_custom_attrs_from_index (klass->image, idx);
6256 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6258 MonoCustomAttrInfo *cinfo;
6261 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6263 idx = 1; /* there is only one assembly */
6264 idx <<= MONO_CUSTOM_ATTR_BITS;
6265 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6266 return mono_custom_attrs_from_index (assembly->image, idx);
6269 static MonoCustomAttrInfo*
6270 mono_custom_attrs_from_module (MonoImage *image)
6272 MonoCustomAttrInfo *cinfo;
6275 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6277 idx = 1; /* there is only one module */
6278 idx <<= MONO_CUSTOM_ATTR_BITS;
6279 idx |= MONO_CUSTOM_ATTR_MODULE;
6280 return mono_custom_attrs_from_index (image, idx);
6284 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6286 MonoCustomAttrInfo *cinfo;
6289 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6291 idx = find_property_index (klass, property);
6292 idx <<= MONO_CUSTOM_ATTR_BITS;
6293 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6294 return mono_custom_attrs_from_index (klass->image, idx);
6298 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6300 MonoCustomAttrInfo *cinfo;
6303 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6305 idx = find_event_index (klass, event);
6306 idx <<= MONO_CUSTOM_ATTR_BITS;
6307 idx |= MONO_CUSTOM_ATTR_EVENT;
6308 return mono_custom_attrs_from_index (klass->image, idx);
6312 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6314 MonoCustomAttrInfo *cinfo;
6317 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6319 idx = find_field_index (klass, field);
6320 idx <<= MONO_CUSTOM_ATTR_BITS;
6321 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6322 return mono_custom_attrs_from_index (klass->image, idx);
6326 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6329 guint32 i, idx, method_index;
6330 guint32 param_list, param_last, param_pos, found;
6332 MonoReflectionMethodAux *aux;
6334 if (method->klass->image->dynamic) {
6335 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6336 if (!aux || !aux->param_cattr)
6338 return aux->param_cattr [param];
6341 image = method->klass->image;
6342 method_index = find_method_index (method);
6343 ca = &image->tables [MONO_TABLE_METHOD];
6345 if (method->klass->generic_inst || method->klass->gen_params ||
6346 method->signature->generic_param_count) {
6347 /* FIXME FIXME FIXME */
6351 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6352 if (method_index == ca->rows) {
6353 ca = &image->tables [MONO_TABLE_PARAM];
6354 param_last = ca->rows + 1;
6356 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6357 ca = &image->tables [MONO_TABLE_PARAM];
6360 for (i = param_list; i < param_last; ++i) {
6361 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6362 if (param_pos == param) {
6370 idx <<= MONO_CUSTOM_ATTR_BITS;
6371 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6372 return mono_custom_attrs_from_index (image, idx);
6376 * mono_reflection_get_custom_attrs:
6377 * @obj: a reflection object handle
6379 * Return an array with all the custom attributes defined of the
6380 * reflection handle @obj. The objects are fully build.
6383 mono_reflection_get_custom_attrs (MonoObject *obj)
6387 MonoCustomAttrInfo *cinfo = NULL;
6389 MONO_ARCH_SAVE_REGS;
6391 klass = obj->vtable->klass;
6392 /* FIXME: need to handle: Module */
6393 if (klass == mono_defaults.monotype_class) {
6394 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6395 klass = mono_class_from_mono_type (rtype->type);
6396 cinfo = mono_custom_attrs_from_class (klass);
6397 } else if (strcmp ("Assembly", klass->name) == 0) {
6398 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6399 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6400 } else if (strcmp ("Module", klass->name) == 0) {
6401 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6402 cinfo = mono_custom_attrs_from_module (module->image);
6403 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6404 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6405 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6406 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6407 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6408 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6409 } else if (strcmp ("MonoField", klass->name) == 0) {
6410 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6411 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6412 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6413 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6414 cinfo = mono_custom_attrs_from_method (rmethod->method);
6415 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6416 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6417 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6418 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6419 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6420 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6421 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6422 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6423 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6424 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6425 } else { /* handle other types here... */
6426 g_error ("get custom attrs not yet supported for %s", klass->name);
6430 result = mono_custom_attrs_construct (cinfo);
6432 mono_custom_attrs_free (cinfo);
6434 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6435 result = mono_array_new (mono_domain_get (), klass, 0);
6441 static MonoMethodSignature*
6442 parameters_to_signature (MonoArray *parameters) {
6443 MonoMethodSignature *sig;
6446 count = parameters? mono_array_length (parameters): 0;
6448 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6449 sig->param_count = count;
6450 sig->sentinelpos = -1; /* FIXME */
6451 for (i = 0; i < count; ++i) {
6452 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6453 sig->params [i] = pt->type;
6458 static MonoMethodSignature*
6459 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6460 MonoMethodSignature *sig;
6462 sig = parameters_to_signature (ctor->parameters);
6463 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6464 sig->ret = &mono_defaults.void_class->byval_arg;
6468 static MonoMethodSignature*
6469 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6470 MonoMethodSignature *sig;
6472 sig = parameters_to_signature (method->parameters);
6473 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6474 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6475 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6479 static MonoMethodSignature*
6480 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6481 MonoMethodSignature *sig;
6483 sig = parameters_to_signature (method->parameters);
6484 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6485 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6486 sig->generic_param_count = 0;
6491 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6493 MonoClass *klass = mono_object_class (prop);
6494 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6495 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6496 *name = mono_string_to_utf8 (pb->name);
6497 *type = pb->type->type;
6499 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6500 *name = g_strdup (p->property->name);
6501 if (p->property->get)
6502 *type = p->property->get->signature->ret;
6504 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6509 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6511 MonoClass *klass = mono_object_class (field);
6512 if (strcmp (klass->name, "FieldBuilder") == 0) {
6513 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6514 *name = mono_string_to_utf8 (fb->name);
6515 *type = fb->type->type;
6517 MonoReflectionField *f = (MonoReflectionField *)field;
6518 *name = g_strdup (f->field->name);
6519 *type = f->field->type;
6524 * Encode a value in a custom attribute stream of bytes.
6525 * The value to encode is either supplied as an object in argument val
6526 * (valuetypes are boxed), or as a pointer to the data in the
6528 * @type represents the type of the value
6529 * @buffer is the start of the buffer
6530 * @p the current position in the buffer
6531 * @buflen contains the size of the buffer and is used to return the new buffer size
6532 * if this needs to be realloced.
6533 * @retbuffer and @retp return the start and the position of the buffer
6536 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6538 MonoTypeEnum simple_type;
6540 if ((p-buffer) + 10 >= *buflen) {
6543 newbuf = g_realloc (buffer, *buflen);
6544 p = newbuf + (p-buffer);
6548 argval = ((char*)arg + sizeof (MonoObject));
6549 simple_type = type->type;
6551 switch (simple_type) {
6552 case MONO_TYPE_BOOLEAN:
6557 case MONO_TYPE_CHAR:
6560 swap_with_size (p, argval, 2, 1);
6566 swap_with_size (p, argval, 4, 1);
6572 swap_with_size (p, argval, 8, 1);
6575 case MONO_TYPE_VALUETYPE:
6576 if (type->data.klass->enumtype) {
6577 simple_type = type->data.klass->enum_basetype->type;
6580 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6583 case MONO_TYPE_STRING: {
6590 str = mono_string_to_utf8 ((MonoString*)arg);
6591 slen = strlen (str);
6592 if ((p-buffer) + 10 + slen >= *buflen) {
6596 newbuf = g_realloc (buffer, *buflen);
6597 p = newbuf + (p-buffer);
6600 mono_metadata_encode_value (slen, p, &p);
6601 memcpy (p, str, slen);
6606 case MONO_TYPE_CLASS: {
6614 k = mono_object_class (arg);
6615 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6616 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6617 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6619 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6620 slen = strlen (str);
6621 if ((p-buffer) + 10 + slen >= *buflen) {
6625 newbuf = g_realloc (buffer, *buflen);
6626 p = newbuf + (p-buffer);
6629 mono_metadata_encode_value (slen, p, &p);
6630 memcpy (p, str, slen);
6635 case MONO_TYPE_SZARRAY: {
6637 MonoClass *eclass, *arg_eclass;
6640 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6643 len = mono_array_length ((MonoArray*)arg);
6645 *p++ = (len >> 8) & 0xff;
6646 *p++ = (len >> 16) & 0xff;
6647 *p++ = (len >> 24) & 0xff;
6649 *retbuffer = buffer;
6650 eclass = type->data.klass;
6651 arg_eclass = mono_object_class (arg)->element_class;
6652 if (eclass->valuetype && arg_eclass->valuetype) {
6653 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6654 int elsize = mono_class_array_element_size (eclass);
6655 for (i = 0; i < len; ++i) {
6656 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6660 for (i = 0; i < len; ++i) {
6661 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6666 /* it may be a boxed value or a Type */
6667 case MONO_TYPE_OBJECT: {
6668 MonoClass *klass = mono_object_class (arg);
6672 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6675 } else if (klass->enumtype) {
6677 } else if (klass == mono_defaults.string_class) {
6678 simple_type = MONO_TYPE_STRING;
6681 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6682 *p++ = simple_type = klass->byval_arg.type;
6685 g_error ("unhandled type in custom attr");
6687 str = type_get_qualified_name (klass->enum_basetype, NULL);
6688 slen = strlen (str);
6689 if ((p-buffer) + 10 + slen >= *buflen) {
6693 newbuf = g_realloc (buffer, *buflen);
6694 p = newbuf + (p-buffer);
6697 mono_metadata_encode_value (slen, p, &p);
6698 memcpy (p, str, slen);
6701 simple_type = klass->enum_basetype->type;
6705 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6708 *retbuffer = buffer;
6712 * mono_reflection_get_custom_attrs_blob:
6713 * @ctor: custom attribute constructor
6714 * @ctorArgs: arguments o the constructor
6720 * Creates the blob of data that needs to be saved in the metadata and that represents
6721 * the custom attributed described by @ctor, @ctorArgs etc.
6722 * Returns: a Byte array representing the blob of data.
6725 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6728 MonoMethodSignature *sig;
6733 MONO_ARCH_SAVE_REGS;
6735 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6736 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6738 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6740 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6742 p = buffer = g_malloc (buflen);
6743 /* write the prolog */
6746 for (i = 0; i < sig->param_count; ++i) {
6747 arg = mono_array_get (ctorArgs, MonoObject*, i);
6748 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
6752 i += mono_array_length (properties);
6754 i += mono_array_length (fields);
6756 *p++ = (i >> 8) & 0xff;
6759 for (i = 0; i < mono_array_length (properties); ++i) {
6764 prop = mono_array_get (properties, gpointer, i);
6765 get_prop_name_and_type (prop, &pname, &ptype);
6766 *p++ = 0x54; /* PROPERTY signature */
6768 /* Preallocate a large enough buffer */
6769 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6770 char *str = type_get_qualified_name (ptype, NULL);
6776 len += strlen (pname);
6778 if ((p-buffer) + 20 + len >= buflen) {
6782 newbuf = g_realloc (buffer, buflen);
6783 p = newbuf + (p-buffer);
6787 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6788 char *str = type_get_qualified_name (ptype, NULL);
6789 int slen = strlen (str);
6793 * This seems to be optional...
6796 mono_metadata_encode_value (slen, p, &p);
6797 memcpy (p, str, slen);
6801 mono_metadata_encode_value (ptype->type, p, &p);
6802 if (ptype->type == MONO_TYPE_SZARRAY)
6803 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6805 len = strlen (pname);
6806 mono_metadata_encode_value (len, p, &p);
6807 memcpy (p, pname, len);
6809 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
6816 for (i = 0; i < mono_array_length (fields); ++i) {
6821 field = mono_array_get (fields, gpointer, i);
6822 get_field_name_and_type (field, &fname, &ftype);
6823 *p++ = 0x53; /* FIELD signature */
6824 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6825 char *str = type_get_qualified_name (ftype, NULL);
6826 int slen = strlen (str);
6827 if ((p-buffer) + 10 + slen >= buflen) {
6831 newbuf = g_realloc (buffer, buflen);
6832 p = newbuf + (p-buffer);
6837 * This seems to be optional...
6840 mono_metadata_encode_value (slen, p, &p);
6841 memcpy (p, str, slen);
6845 mono_metadata_encode_value (ftype->type, p, &p);
6846 if (ftype->type == MONO_TYPE_SZARRAY)
6847 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
6849 len = strlen (fname);
6850 mono_metadata_encode_value (len, p, &p);
6851 memcpy (p, fname, len);
6853 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
6858 g_assert (p - buffer <= buflen);
6859 buflen = p - buffer;
6860 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6861 p = mono_array_addr (result, char, 0);
6862 memcpy (p, buffer, buflen);
6864 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6870 * mono_reflection_setup_internal_class:
6871 * @tb: a TypeBuilder object
6873 * Creates a MonoClass that represents the TypeBuilder.
6874 * This is a trick that lets us simplify a lot of reflection code
6875 * (and will allow us to support Build and Run assemblies easier).
6878 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6880 MonoClass *klass, *parent;
6882 MONO_ARCH_SAVE_REGS;
6885 /* check so we can compile corlib correctly */
6886 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6887 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6888 parent = tb->parent->type->data.klass;
6890 parent = my_mono_class_from_mono_type (tb->parent->type);
6894 /* the type has already being created: it means we just have to change the parent */
6895 if (tb->type.type) {
6896 klass = mono_class_from_mono_type (tb->type.type);
6897 klass->parent = NULL;
6898 /* fool mono_class_setup_parent */
6899 g_free (klass->supertypes);
6900 klass->supertypes = NULL;
6901 mono_class_setup_parent (klass, parent);
6902 mono_class_setup_mono_type (klass);
6906 klass = g_new0 (MonoClass, 1);
6908 klass->image = &tb->module->dynamic_image->image;
6910 klass->inited = 1; /* we lie to the runtime */
6911 klass->name = mono_string_to_utf8 (tb->name);
6912 klass->name_space = mono_string_to_utf8 (tb->nspace);
6913 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6914 klass->flags = tb->attrs;
6916 klass->element_class = klass;
6917 klass->reflection_info = tb; /* need to pin. */
6919 /* Put into cache so mono_class_get () will find it */
6920 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6923 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6924 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6928 mono_class_setup_parent (klass, parent);
6929 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6930 const char *old_n = klass->name;
6931 /* trick to get relative numbering right when compiling corlib */
6932 klass->name = "BuildingObject";
6933 mono_class_setup_parent (klass, mono_defaults.object_class);
6934 klass->name = old_n;
6936 mono_class_setup_mono_type (klass);
6938 mono_class_setup_supertypes (klass);
6941 * FIXME: handle interfaces.
6944 tb->type.type = &klass->byval_arg;
6946 if (tb->nesting_type) {
6947 g_assert (tb->nesting_type->type);
6948 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6951 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6955 * mono_reflection_setup_generic_class:
6956 * @tb: a TypeBuilder object
6958 * Setup the generic class after all generic parameters have been added.
6961 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6966 MONO_ARCH_SAVE_REGS;
6968 klass = my_mono_class_from_mono_type (tb->type.type);
6970 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6972 if (klass->gen_params || (count == 0))
6975 klass->num_gen_params = count;
6976 klass->gen_params = g_new0 (MonoGenericParam, count);
6978 for (i = 0; i < count; i++) {
6979 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6980 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6985 * mono_reflection_create_internal_class:
6986 * @tb: a TypeBuilder object
6988 * Actually create the MonoClass that is associated with the TypeBuilder.
6991 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6995 MONO_ARCH_SAVE_REGS;
6997 klass = my_mono_class_from_mono_type (tb->type.type);
6999 if (klass->enumtype && klass->enum_basetype == NULL) {
7000 MonoReflectionFieldBuilder *fb;
7002 g_assert (tb->fields != NULL);
7003 g_assert (mono_array_length (tb->fields) >= 1);
7005 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7007 klass->enum_basetype = fb->type->type;
7008 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7009 if (!klass->element_class)
7010 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7011 klass->instance_size = klass->element_class->instance_size;
7012 klass->size_inited = 1;
7014 * this is almost safe to do with enums and it's needed to be able
7015 * to create objects of the enum type (for use in SetConstant).
7017 /* FIXME: Does this mean enums can't have method overrides ? */
7018 mono_class_setup_vtable (klass, NULL, 0);
7022 static MonoMarshalSpec*
7023 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7024 MonoReflectionMarshal *minfo)
7026 MonoMarshalSpec *res;
7028 res = g_new0 (MonoMarshalSpec, 1);
7029 res->native = minfo->type;
7031 switch (minfo->type) {
7032 case MONO_NATIVE_LPARRAY:
7033 res->data.array_data.elem_type = minfo->eltype;
7034 res->data.array_data.param_num = 0; /* Not yet */
7035 res->data.array_data.num_elem = minfo->count;
7038 case MONO_NATIVE_BYVALTSTR:
7039 case MONO_NATIVE_BYVALARRAY:
7040 res->data.array_data.num_elem = minfo->count;
7043 case MONO_NATIVE_CUSTOM:
7044 if (minfo->marshaltyperef)
7045 res->data.custom_data.custom_name =
7046 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7048 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7059 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7060 ReflectionMethodBuilder *rmb,
7061 MonoMethodSignature *sig)
7064 MonoMethodNormal *pm;
7065 MonoMarshalSpec **specs;
7066 MonoReflectionMethodAux *method_aux;
7069 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7070 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7071 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7074 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7076 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7078 pm = (MonoMethodNormal*)m;
7081 m->flags = rmb->attrs;
7082 m->iflags = rmb->iattrs;
7083 m->name = mono_string_to_utf8 (rmb->name);
7087 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7089 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7090 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7093 m->signature->pinvoke = 1;
7094 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7096 m->signature->pinvoke = 1;
7098 } else if (!m->klass->dummy &&
7099 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7100 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7101 MonoMethodHeader *header;
7103 gint32 max_stack, i;
7104 gint32 num_locals = 0;
7105 gint32 num_clauses = 0;
7109 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7110 code_size = rmb->ilgen->code_len;
7111 max_stack = rmb->ilgen->max_stack;
7112 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7113 if (rmb->ilgen->ex_handlers)
7114 num_clauses = method_count_clauses (rmb->ilgen);
7117 code = mono_array_addr (rmb->code, guint8, 0);
7118 code_size = mono_array_length (rmb->code);
7119 /* we probably need to run a verifier on the code... */
7129 header = g_malloc0 (sizeof (MonoMethodHeader) +
7130 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7131 header->code_size = code_size;
7132 header->code = g_malloc (code_size);
7133 memcpy ((char*)header->code, code, code_size);
7134 header->max_stack = max_stack;
7135 header->init_locals = rmb->init_locals;
7136 header->num_locals = num_locals;
7138 for (i = 0; i < num_locals; ++i) {
7139 MonoReflectionLocalBuilder *lb =
7140 mono_array_get (rmb->ilgen->locals,
7141 MonoReflectionLocalBuilder*, i);
7143 header->locals [i] = g_new0 (MonoType, 1);
7144 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7147 header->num_clauses = num_clauses;
7149 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7154 pm->header = header;
7157 if (rmb->generic_params) {
7158 int count = mono_array_length (rmb->generic_params);
7159 pm->gen_params = g_new0 (MonoGenericParam, count);
7160 for (i = 0; i < count; i++) {
7161 MonoReflectionGenericParam *gp =
7162 mono_array_get (rmb->generic_params,
7163 MonoReflectionGenericParam*, i);
7165 pm->gen_params [i] = *gp->type.type->data.generic_param;
7170 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7173 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7175 for (i = 0; i < rmb->nrefs; ++i)
7176 mw->data = g_list_append (mw->data, rmb->refs [i]);
7181 /* Parameter names */
7184 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7185 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7186 for (i = 0; i <= m->signature->param_count; ++i) {
7187 MonoReflectionParamBuilder *pb;
7188 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7190 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7192 if (!method_aux->param_cattr)
7193 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7194 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7200 /* Parameter marshalling */
7203 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7204 MonoReflectionParamBuilder *pb;
7205 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7206 if (pb->marshal_info) {
7208 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7209 specs [pb->position] =
7210 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7214 if (specs != NULL) {
7216 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7217 method_aux->param_marshall = specs;
7220 if (klass->image->dynamic && method_aux)
7221 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7227 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7229 ReflectionMethodBuilder rmb;
7230 MonoMethodSignature *sig;
7232 sig = ctor_builder_to_signature (mb);
7234 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7236 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7237 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7239 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7240 /* ilgen is no longer needed */
7248 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7250 ReflectionMethodBuilder rmb;
7251 MonoMethodSignature *sig;
7253 sig = method_builder_to_signature (mb);
7255 reflection_methodbuilder_from_method_builder (&rmb, mb);
7257 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7258 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7260 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7261 /* ilgen is no longer needed */
7267 static MonoClassField*
7268 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7270 MonoClassField *field;
7277 field = g_new0 (MonoClassField, 1);
7279 field->name = mono_string_to_utf8 (fb->name);
7281 /* FIXME: handle type modifiers */
7282 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7283 field->type->attrs = fb->attrs;
7285 field->type = fb->type->type;
7287 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7288 field->data = mono_array_addr (fb->rva_data, char, 0);
7289 if (fb->offset != -1)
7290 field->offset = fb->offset;
7291 field->parent = klass;
7293 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7295 if (fb->def_value) {
7296 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7297 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7298 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7299 /* Copy the data from the blob since it might get realloc-ed */
7300 p = assembly->blob.data + idx;
7301 len = mono_metadata_decode_blob_size (p, &p2);
7303 field->data = g_malloc (len);
7304 memcpy ((gpointer)field->data, p, len);
7311 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7315 MonoReflectionTypeBuilder *tb = NULL;
7316 MonoGenericInst *ginst, *cached;
7321 klass = mono_class_from_mono_type (type->type);
7322 if (!klass->gen_params && !klass->generic_inst &&
7323 !(klass->nested_in && klass->nested_in->gen_params))
7326 mono_loader_lock ();
7328 domain = mono_object_domain (type);
7330 ginst = g_new0 (MonoGenericInst, 1);
7332 if (!klass->generic_inst) {
7333 ginst->type_argc = type_argc;
7334 ginst->type_argv = types;
7336 for (i = 0; i < ginst->type_argc; ++i) {
7337 if (!ginst->is_open)
7338 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7341 ginst->generic_type = &klass->byval_arg;
7343 MonoGenericInst *kginst = klass->generic_inst;
7345 ginst->type_argc = kginst->type_argc;
7346 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7348 for (i = 0; i < ginst->type_argc; i++) {
7349 MonoType *t = kginst->type_argv [i];
7351 if (t->type == MONO_TYPE_VAR)
7352 t = types [t->data.generic_param->num];
7354 if (!ginst->is_open)
7355 ginst->is_open = mono_class_is_open_constructed_type (t);
7357 ginst->type_argv [i] = t;
7360 ginst->generic_type = kginst->generic_type;
7363 geninst = g_new0 (MonoType, 1);
7364 geninst->type = MONO_TYPE_GENERICINST;
7366 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7369 mono_loader_unlock ();
7370 geninst->data.generic_inst = cached;
7374 geninst->data.generic_inst = ginst;
7376 ginst->context = g_new0 (MonoGenericContext, 1);
7377 ginst->context->ginst = ginst;
7379 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7380 tb = (MonoReflectionTypeBuilder *) type;
7382 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7383 ginst->is_dynamic = TRUE;
7384 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7385 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7386 MonoReflectionType *rgt = rgi->generic_type;
7388 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7389 tb = (MonoReflectionTypeBuilder *) rgt;
7391 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7392 ginst->is_dynamic = TRUE;
7394 icount = klass->interface_count;
7396 ginst->ifaces = g_new0 (MonoType *, icount);
7397 ginst->count_ifaces = icount;
7399 for (i = 0; i < icount; i++) {
7400 MonoReflectionType *itype;
7403 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7405 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7406 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7407 if (!ginst->ifaces [i])
7408 ginst->ifaces [i] = itype->type;
7411 mono_class_create_generic (ginst);
7413 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7415 mono_loader_unlock ();
7421 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7423 MonoClass *klass, *pklass = NULL;
7424 MonoReflectionType *parent = NULL;
7426 MonoReflectionTypeBuilder *tb = NULL;
7427 MonoGenericInst *ginst;
7430 domain = mono_object_domain (type);
7431 klass = mono_class_from_mono_type (type->type);
7433 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7434 tb = (MonoReflectionTypeBuilder *) type;
7437 parent = tb->parent;
7438 pklass = mono_class_from_mono_type (parent->type);
7441 pklass = klass->parent;
7443 parent = mono_type_get_object (domain, &pklass->byval_arg);
7446 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7450 ginst = geninst->data.generic_inst;
7452 if (pklass && pklass->generic_inst)
7453 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7458 MonoReflectionMethod*
7459 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7461 MonoMethod *method, *inflated;
7462 MonoReflectionMethodBuilder *mb = NULL;
7463 MonoGenericMethod *gmethod;
7464 MonoGenericContext *context;
7467 MONO_ARCH_SAVE_REGS;
7468 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7469 MonoReflectionTypeBuilder *tb;
7472 mb = (MonoReflectionMethodBuilder *) rmethod;
7473 tb = (MonoReflectionTypeBuilder *) mb->type;
7474 klass = mono_class_from_mono_type (tb->type.type);
7476 method = methodbuilder_to_mono_method (klass, mb);
7478 method = rmethod->method;
7480 count = method->signature->generic_param_count;
7481 if (count != mono_array_length (types))
7484 gmethod = g_new0 (MonoGenericMethod, 1);
7485 gmethod->mtype_argc = count;
7486 gmethod->mtype_argv = g_new0 (MonoType *, count);
7487 for (i = 0; i < count; i++) {
7488 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7489 gmethod->mtype_argv [i] = garg->type;
7492 gmethod->reflection_info = rmethod;
7494 context = g_new0 (MonoGenericContext, 1);
7495 context->ginst = method->klass->generic_inst;
7496 context->gmethod = gmethod;
7498 inflated = mono_class_inflate_generic_method (method, context, NULL);
7500 return mono_method_get_object (
7501 mono_object_domain (rmethod), inflated, NULL);
7505 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7507 MonoGenericMethod *gmethod;
7508 MonoGenericInst *ginst;
7509 MonoGenericContext *context;
7512 ginst = type->type.type->data.generic_inst;
7514 gmethod = g_new0 (MonoGenericMethod, 1);
7515 gmethod->reflection_info = obj;
7517 gmethod->mtype_argc = method->signature->generic_param_count;
7518 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7520 for (i = 0; i < gmethod->mtype_argc; i++) {
7521 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7522 MonoGenericParam *gparam = &mn->gen_params [i];
7524 g_assert (gparam->pklass);
7525 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7528 context = g_new0 (MonoGenericContext, 1);
7529 context->ginst = ginst;
7530 context->gmethod = gmethod;
7532 return mono_class_inflate_generic_method (method, context, ginst->klass);
7536 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7541 klass = mono_class_from_mono_type (type->type.type);
7543 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7544 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7545 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7546 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7547 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7548 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7549 method = ((MonoReflectionMethod *) obj)->method;
7551 method = NULL; /* prevent compiler warning */
7552 g_assert_not_reached ();
7555 return inflate_mono_method (type, method, obj);
7559 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7560 MonoArray *methods, MonoArray *ctors,
7561 MonoArray *fields, MonoArray *properties,
7564 MonoGenericInst *ginst;
7565 MonoDynamicGenericInst *dginst;
7566 MonoClass *klass, *gklass, *pklass;
7569 MONO_ARCH_SAVE_REGS;
7571 klass = mono_class_from_mono_type (type->type.type);
7572 ginst = type->type.type->data.generic_inst;
7574 if (ginst->initialized)
7577 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7579 gklass = mono_class_from_mono_type (ginst->generic_type);
7580 mono_class_init (gklass);
7583 pklass = mono_class_from_mono_type (ginst->parent);
7585 pklass = gklass->parent;
7587 mono_class_setup_parent (klass, pklass);
7589 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7590 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7591 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7592 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7593 dginst->count_events = events ? mono_array_length (events) : 0;
7595 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7596 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7597 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7598 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7599 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7601 for (i = 0; i < dginst->count_methods; i++) {
7602 MonoObject *obj = mono_array_get (methods, gpointer, i);
7604 dginst->methods [i] = inflate_method (type, obj);
7607 for (i = 0; i < dginst->count_ctors; i++) {
7608 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7610 dginst->ctors [i] = inflate_method (type, obj);
7613 for (i = 0; i < dginst->count_fields; i++) {
7614 MonoObject *obj = mono_array_get (fields, gpointer, i);
7615 MonoClassField *field;
7616 MonoInflatedField *ifield;
7618 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7619 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7620 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7621 field = ((MonoReflectionField *) obj)->field;
7623 field = NULL; /* prevent compiler warning */
7624 g_assert_not_reached ();
7627 ifield = g_new0 (MonoInflatedField, 1);
7628 ifield->generic_type = field->type;
7629 ifield->reflection_info = obj;
7631 dginst->fields [i] = *field;
7632 dginst->fields [i].generic_info = ifield;
7633 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7636 for (i = 0; i < dginst->count_properties; i++) {
7637 MonoObject *obj = mono_array_get (properties, gpointer, i);
7638 MonoProperty *property = &dginst->properties [i];
7640 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7641 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7643 property->parent = klass;
7644 property->attrs = pb->attrs;
7645 property->name = mono_string_to_utf8 (pb->name);
7647 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7649 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7650 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7651 *property = *((MonoReflectionProperty *) obj)->property;
7654 property->get = inflate_mono_method (type, property->get, NULL);
7656 property->set = inflate_mono_method (type, property->set, NULL);
7658 g_assert_not_reached ();
7661 for (i = 0; i < dginst->count_events; i++) {
7662 MonoObject *obj = mono_array_get (events, gpointer, i);
7663 MonoEvent *event = &dginst->events [i];
7665 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7666 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7668 event->parent = klass;
7669 event->attrs = eb->attrs;
7670 event->name = mono_string_to_utf8 (eb->name);
7672 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7673 if (eb->remove_method)
7674 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7675 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7676 *event = *((MonoReflectionEvent *) obj)->event;
7679 event->add = inflate_mono_method (type, event->add, NULL);
7681 event->remove = inflate_mono_method (type, event->remove, NULL);
7683 g_assert_not_reached ();
7686 ginst->initialized = TRUE;
7690 ensure_runtime_vtable (MonoClass *klass)
7692 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7693 int i, num, j, onum;
7694 MonoMethod **overrides;
7696 if (!tb || klass->wastypebuilder)
7699 ensure_runtime_vtable (klass->parent);
7701 num = tb->ctors? mono_array_length (tb->ctors): 0;
7702 num += tb->num_methods;
7703 klass->method.count = num;
7704 klass->methods = g_new (MonoMethod*, num);
7705 num = tb->ctors? mono_array_length (tb->ctors): 0;
7706 for (i = 0; i < num; ++i)
7707 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7708 num = tb->num_methods;
7710 for (i = 0; i < num; ++i)
7711 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7713 klass->wastypebuilder = TRUE;
7714 if (tb->interfaces) {
7715 klass->interface_count = mono_array_length (tb->interfaces);
7716 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7717 for (i = 0; i < klass->interface_count; ++i) {
7718 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7719 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7723 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7724 for (i = 0; i < klass->method.count; ++i)
7725 klass->methods [i]->slot = i;
7730 for (i = 0; i < tb->num_methods; ++i) {
7731 MonoReflectionMethodBuilder *mb =
7732 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7733 if (mb->override_method)
7738 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7742 for (i = 0; i < tb->num_methods; ++i) {
7743 MonoReflectionMethodBuilder *mb =
7744 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7745 if (mb->override_method) {
7746 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7747 overrides [onum * 2] =
7748 mb->override_method->method;
7749 overrides [onum * 2 + 1] =
7752 g_assert (mb->mhandle);
7759 mono_class_setup_vtable (klass, overrides, onum);
7763 typebuilder_setup_fields (MonoClass *klass)
7765 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7766 MonoReflectionFieldBuilder *fb;
7767 MonoClassField *field;
7772 klass->field.count = tb->num_fields;
7773 klass->field.first = 0;
7774 klass->field.last = klass->field.count;
7776 if (!klass->field.count)
7779 klass->fields = g_new0 (MonoClassField, klass->field.count);
7781 for (i = 0; i < klass->field.count; ++i) {
7782 fb = mono_array_get (tb->fields, gpointer, i);
7783 field = &klass->fields [i];
7784 field->name = mono_string_to_utf8 (fb->name);
7786 /* FIXME: handle type modifiers */
7787 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7788 field->type->attrs = fb->attrs;
7790 field->type = fb->type->type;
7792 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7793 field->data = mono_array_addr (fb->rva_data, char, 0);
7794 if (fb->offset != -1)
7795 field->offset = fb->offset;
7796 field->parent = klass;
7798 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7800 if (fb->def_value) {
7801 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7802 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7803 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7804 /* Copy the data from the blob since it might get realloc-ed */
7805 p = assembly->blob.data + idx;
7806 len = mono_metadata_decode_blob_size (p, &p2);
7808 field->data = g_malloc (len);
7809 memcpy ((gpointer)field->data, p, len);
7812 mono_class_layout_fields (klass);
7816 typebuilder_setup_properties (MonoClass *klass)
7818 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7819 MonoReflectionPropertyBuilder *pb;
7822 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7823 klass->property.first = 0;
7824 klass->property.last = klass->property.count;
7826 klass->properties = g_new0 (MonoProperty, klass->property.count);
7827 for (i = 0; i < klass->property.count; ++i) {
7828 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7829 klass->properties [i].parent = klass;
7830 klass->properties [i].attrs = pb->attrs;
7831 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7833 klass->properties [i].get = pb->get_method->mhandle;
7835 klass->properties [i].set = pb->set_method->mhandle;
7839 MonoReflectionEvent *
7840 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7842 MonoEvent *event = g_new0 (MonoEvent, 1);
7846 klass = my_mono_class_from_mono_type (tb->type.type);
7848 event->parent = klass;
7849 event->attrs = eb->attrs;
7850 event->name = mono_string_to_utf8 (eb->name);
7852 event->add = eb->add_method->mhandle;
7853 if (eb->remove_method)
7854 event->remove = eb->remove_method->mhandle;
7855 if (eb->raise_method)
7856 event->raise = eb->raise_method->mhandle;
7858 if (eb->other_methods) {
7859 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7860 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7861 MonoReflectionMethodBuilder *mb =
7862 mono_array_get (eb->other_methods,
7863 MonoReflectionMethodBuilder*, j);
7864 event->other [j] = mb->mhandle;
7868 return mono_event_get_object (mono_object_domain (tb), klass, event);
7872 typebuilder_setup_events (MonoClass *klass)
7874 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7875 MonoReflectionEventBuilder *eb;
7878 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7879 klass->event.first = 0;
7880 klass->event.last = klass->event.count;
7882 klass->events = g_new0 (MonoEvent, klass->event.count);
7883 for (i = 0; i < klass->event.count; ++i) {
7884 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7885 klass->events [i].parent = klass;
7886 klass->events [i].attrs = eb->attrs;
7887 klass->events [i].name = mono_string_to_utf8 (eb->name);
7889 klass->events [i].add = eb->add_method->mhandle;
7890 if (eb->remove_method)
7891 klass->events [i].remove = eb->remove_method->mhandle;
7892 if (eb->raise_method)
7893 klass->events [i].raise = eb->raise_method->mhandle;
7895 if (eb->other_methods) {
7896 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7897 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7898 MonoReflectionMethodBuilder *mb =
7899 mono_array_get (eb->other_methods,
7900 MonoReflectionMethodBuilder*, j);
7901 klass->events [i].other [j] = mb->mhandle;
7908 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7911 MonoReflectionType* res;
7914 MONO_ARCH_SAVE_REGS;
7916 klass = my_mono_class_from_mono_type (tb->type.type);
7918 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7921 * Fields to set in klass:
7922 * the various flags: delegate/unicode/contextbound etc.
7924 klass->flags = tb->attrs;
7926 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7927 /* No need to fully construct the type */
7928 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7930 /* enums are done right away */
7931 if (!klass->enumtype)
7932 ensure_runtime_vtable (klass);
7935 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
7936 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
7937 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
7941 /* fields and object layout */
7942 if (klass->parent) {
7943 if (!klass->parent->size_inited)
7944 mono_class_init (klass->parent);
7945 klass->instance_size += klass->parent->instance_size;
7946 klass->class_size += klass->parent->class_size;
7947 klass->min_align = klass->parent->min_align;
7949 klass->instance_size = sizeof (MonoObject);
7950 klass->min_align = 1;
7953 /* FIXME: handle packing_size and instance_size */
7954 typebuilder_setup_fields (klass);
7956 typebuilder_setup_properties (klass);
7958 typebuilder_setup_events (klass);
7960 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7961 /* with enums res == tb: need to fix that. */
7962 if (!klass->enumtype)
7963 g_assert (res != (MonoReflectionType*)tb);
7968 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7970 MonoGenericParam *param;
7973 MONO_ARCH_SAVE_REGS;
7975 param = g_new0 (MonoGenericParam, 1);
7977 param->method = NULL;
7978 param->name = mono_string_to_utf8 (gparam->name);
7979 param->num = gparam->index;
7981 image = &gparam->tbuilder->module->dynamic_image->image;
7982 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7984 param->pklass->reflection_info = gparam;
7986 gparam->type.type = g_new0 (MonoType, 1);
7987 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7988 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7989 gparam->type.type->data.generic_param = param;
7993 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7995 MonoDynamicImage *assembly = sig->module->dynamic_image;
7996 guint32 na = mono_array_length (sig->arguments);
8001 MONO_ARCH_SAVE_REGS;
8003 p = buf = g_malloc (10 + na * 10);
8005 mono_metadata_encode_value (0x07, p, &p);
8006 mono_metadata_encode_value (na, p, &p);
8007 for (i = 0; i < na; ++i) {
8008 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8009 encode_reflection_type (assembly, type, p, &p);
8013 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8014 p = mono_array_addr (result, char, 0);
8015 memcpy (p, buf, buflen);
8022 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8024 MonoDynamicImage *assembly = sig->module->dynamic_image;
8025 guint32 na = mono_array_length (sig->arguments);
8030 MONO_ARCH_SAVE_REGS;
8032 p = buf = g_malloc (10 + na * 10);
8034 mono_metadata_encode_value (0x06, p, &p);
8035 for (i = 0; i < na; ++i) {
8036 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8037 encode_reflection_type (assembly, type, p, &p);
8041 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8042 p = mono_array_addr (result, char, 0);
8043 memcpy (p, buf, buflen);
8050 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8052 ReflectionMethodBuilder rmb;
8053 MonoMethodSignature *sig;
8056 sig = dynamic_method_to_signature (mb);
8058 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8061 * Resolve references.
8063 rmb.nrefs = mb->nrefs;
8064 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8065 for (i = 0; i < mb->nrefs; ++i) {
8066 gpointer ref = resolve_object (mb->module->image,
8067 mono_array_get (mb->refs, MonoObject*, i));
8070 mono_raise_exception (mono_get_exception_type_load (NULL));
8077 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8081 /* ilgen is no longer needed */
8086 * mono_reflection_lookup_dynamic_token:
8088 * Finish the Builder object pointed to by TOKEN and return the corresponding
8089 * runtime structure.
8092 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8094 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8097 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8100 return resolve_object (image, obj);
8104 resolve_object (MonoImage *image, MonoObject *obj)
8106 gpointer result = NULL;
8108 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8109 result = mono_string_intern ((MonoString*)obj);
8112 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8113 MonoReflectionType *tb = (MonoReflectionType*)obj;
8114 result = mono_class_from_mono_type (tb->type);
8117 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8118 result = ((MonoReflectionMethod*)obj)->method;
8121 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8122 result = ((MonoReflectionMethod*)obj)->method;
8125 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8126 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8127 result = mb->mhandle;
8129 /* Type is not yet created */
8130 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8132 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8135 * Hopefully this has been filled in by calling CreateType() on the
8139 * TODO: This won't work if the application finishes another
8140 * TypeBuilder instance instead of this one.
8142 result = mb->mhandle;
8145 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8146 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8148 result = cb->mhandle;
8150 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8152 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8153 result = cb->mhandle;
8156 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8157 result = ((MonoReflectionField*)obj)->field;
8160 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8161 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8162 result = fb->handle;
8165 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8167 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8168 result = fb->handle;
8171 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8172 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8175 klass = tb->type.type->data.klass;
8176 if (klass->wastypebuilder) {
8177 /* Already created */
8181 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8182 result = tb->type.type->data.klass;
8186 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8187 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8188 MonoMethodSignature *sig;
8191 if (helper->arguments)
8192 nargs = mono_array_length (helper->arguments);
8196 sig = mono_metadata_signature_alloc (image, nargs);
8197 sig->explicit_this = helper->call_conv & 64;
8198 sig->hasthis = helper->call_conv & 32;
8200 if (helper->call_conv == 0) /* unmanaged */
8201 sig->call_convention = helper->unmanaged_call_conv - 1;
8203 if (helper->call_conv & 0x02)
8204 sig->call_convention = MONO_CALL_VARARG;
8206 sig->call_convention = MONO_CALL_DEFAULT;
8208 sig->param_count = nargs;
8209 /* TODO: Copy type ? */
8210 sig->ret = helper->return_type->type;
8211 for (i = 0; i < nargs; ++i) {
8212 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8213 sig->params [i] = rt->type;
8219 g_print (obj->vtable->klass->name);
8220 g_assert_not_reached ();