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)
2276 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2279 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2280 method->name, method_encode_signature (assembly, method->signature));
2281 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2286 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2287 const gchar *name, guint32 sig)
2289 MonoDynamicTable *table;
2293 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2295 if (assembly->save) {
2296 alloc_table (table, table->rows + 1);
2297 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2298 values [MONO_MEMBERREF_CLASS] = original;
2299 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2300 values [MONO_MEMBERREF_SIGNATURE] = sig;
2303 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2310 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2313 ReflectionMethodBuilder rmb;
2315 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2319 reflection_methodbuilder_from_method_builder (&rmb, mb);
2321 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2322 mono_string_to_utf8 (rmb.name),
2323 method_builder_encode_signature (assembly, &rmb));
2324 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2329 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2332 ReflectionMethodBuilder rmb;
2334 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2338 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2340 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2341 mono_string_to_utf8 (rmb.name),
2342 method_builder_encode_signature (assembly, &rmb));
2343 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2348 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2353 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2356 g_assert (f->field->parent);
2357 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2358 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2359 f->field->name, fieldref_encode_signature (assembly, type));
2360 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2365 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2370 guint32 nparams = gmethod->mtype_argc;
2371 guint32 size = 10 + nparams * 10;
2374 char *b = blob_size;
2376 if (!assembly->save)
2379 p = buf = g_malloc (size);
2381 * FIXME: vararg, explicit_this, differenc call_conv values...
2383 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2384 mono_metadata_encode_value (nparams, p, &p);
2386 for (i = 0; i < nparams; i++)
2387 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2390 g_assert (p - buf < size);
2391 mono_metadata_encode_value (p-buf, b, &b);
2392 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2398 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2400 MonoDynamicTable *table;
2402 guint32 token, mtoken = 0, sig;
2403 MonoMethodInflated *imethod;
2404 MonoMethod *declaring;
2406 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2408 g_assert (method->signature->is_inflated);
2409 imethod = (MonoMethodInflated *) method;
2410 declaring = imethod->declaring;
2412 sig = method_encode_signature (assembly, declaring->signature);
2413 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2414 declaring->name, sig);
2416 if (!declaring->signature->generic_param_count)
2419 switch (mono_metadata_token_table (mtoken)) {
2420 case MONO_TABLE_MEMBERREF:
2421 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2423 case MONO_TABLE_METHOD:
2424 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2427 g_assert_not_reached ();
2430 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2432 if (assembly->save) {
2433 alloc_table (table, table->rows + 1);
2434 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2435 values [MONO_METHODSPEC_METHOD] = mtoken;
2436 values [MONO_METHODSPEC_SIGNATURE] = sig;
2439 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2446 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2448 MonoMethodInflated *imethod;
2451 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2455 g_assert (m->signature->is_inflated);
2456 imethod = (MonoMethodInflated *) m;
2458 if (imethod->declaring->signature->generic_param_count)
2459 token = method_encode_methodspec (assembly, m);
2461 guint32 sig = method_encode_signature (
2462 assembly, imethod->declaring->signature);
2463 token = mono_image_get_memberref_token (
2464 assembly, &m->klass->byval_arg, m->name, sig);
2467 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2472 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2474 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2477 sig = method_encode_signature (assembly, imethod->declaring->signature);
2478 token = mono_image_get_memberref_token (
2479 assembly, &m->klass->byval_arg, m->name, sig);
2485 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2487 MonoDynamicTable *table;
2494 char *b = blob_size;
2498 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2499 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2500 * Because of this, we must not insert it into the `typeref' hash table.
2503 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2507 g_assert (tb->generic_params);
2508 klass = mono_class_from_mono_type (tb->type.type);
2510 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2511 encode_type (assembly, &klass->byval_arg, p, &p);
2513 count = mono_array_length (tb->generic_params);
2514 mono_metadata_encode_value (count, p, &p);
2515 for (i = 0; i < count; i++) {
2516 MonoReflectionGenericParam *gparam;
2518 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2520 encode_type (assembly, gparam->type.type, p, &p);
2523 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2524 if (assembly->save) {
2525 g_assert (p-sig < 128);
2526 mono_metadata_encode_value (p-sig, b, &b);
2527 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2528 alloc_table (table, table->rows + 1);
2529 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2530 values [MONO_TYPESPEC_SIGNATURE] = token;
2533 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2534 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2540 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2542 MonoDynamicTable *table;
2545 guint32 token, pclass, parent, sig;
2548 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2552 klass = mono_class_from_mono_type (fb->typeb->type);
2553 name = mono_string_to_utf8 (fb->name);
2555 sig = fieldref_encode_signature (assembly, fb->type->type);
2557 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2558 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2560 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2561 parent >>= MONO_TYPEDEFORREF_BITS;
2563 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2565 if (assembly->save) {
2566 alloc_table (table, table->rows + 1);
2567 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2568 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2569 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2570 values [MONO_MEMBERREF_SIGNATURE] = sig;
2573 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2575 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2580 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2588 char *b = blob_size;
2590 if (!assembly->save)
2594 g_assert (helper->type == 2);
2596 if (helper->arguments)
2597 nargs = mono_array_length (helper->arguments);
2601 size = 10 + (nargs * 10);
2603 p = buf = g_malloc (size);
2605 /* Encode calling convention */
2606 /* Change Any to Standard */
2607 if ((helper->call_conv & 0x03) == 0x03)
2608 helper->call_conv = 0x01;
2609 /* explicit_this implies has_this */
2610 if (helper->call_conv & 0x40)
2611 helper->call_conv &= 0x20;
2613 if (helper->call_conv == 0) /* Unmanaged */
2614 *p = helper->unmanaged_call_conv - 1;
2617 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2618 if (helper->call_conv & 0x02) /* varargs */
2623 mono_metadata_encode_value (nargs, p, &p);
2624 encode_reflection_type (assembly, helper->return_type, p, &p);
2625 for (i = 0; i < nargs; ++i) {
2626 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2627 encode_reflection_type (assembly, pt, p, &p);
2630 g_assert (p - buf < size);
2631 mono_metadata_encode_value (p-buf, b, &b);
2632 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2639 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2642 MonoDynamicTable *table;
2645 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2646 idx = table->next_idx ++;
2648 alloc_table (table, table->rows);
2649 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2651 values [MONO_STAND_ALONE_SIGNATURE] =
2652 mono_reflection_encode_sighelper (assembly, helper);
2658 reflection_cc_to_file (int call_conv) {
2659 switch (call_conv & 0x3) {
2661 case 1: return MONO_CALL_DEFAULT;
2662 case 2: return MONO_CALL_VARARG;
2664 g_assert_not_reached ();
2671 MonoMethodSignature *sig;
2677 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2682 MonoMethodSignature *sig;
2685 name = mono_string_to_utf8 (m->name);
2686 nparams = mono_array_length (m->parameters);
2687 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2689 sig->sentinelpos = -1;
2690 sig->call_convention = reflection_cc_to_file (m->call_conv);
2691 sig->param_count = nparams;
2692 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2693 for (i = 0; i < nparams; ++i) {
2694 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2695 sig->params [i] = t->type;
2698 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2700 if (strcmp (name, am->name) == 0 &&
2701 mono_metadata_type_equal (am->parent, m->parent->type) &&
2702 mono_metadata_signature_equal (am->sig, sig)) {
2705 m->table_idx = am->token & 0xffffff;
2709 am = g_new0 (ArrayMethod, 1);
2712 am->parent = m->parent->type;
2713 am->token = mono_image_get_memberref_token (assembly, am->parent,
2714 name, method_encode_signature (assembly, sig));
2715 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2716 m->table_idx = am->token & 0xffffff;
2721 * Insert into the metadata tables all the info about the TypeBuilder tb.
2722 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2725 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2727 MonoDynamicTable *table;
2729 int i, is_object = 0, is_system = 0;
2732 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2733 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2734 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2735 n = mono_string_to_utf8 (tb->name);
2736 if (strcmp (n, "Object") == 0)
2738 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2740 n = mono_string_to_utf8 (tb->nspace);
2741 if (strcmp (n, "System") == 0)
2743 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2745 if (tb->parent && !(is_system && is_object) &&
2746 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2747 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2749 values [MONO_TYPEDEF_EXTENDS] = 0;
2750 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2751 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2754 * if we have explicitlayout or sequentiallayouts, output data in the
2755 * ClassLayout table.
2757 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2758 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2759 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2761 alloc_table (table, table->rows);
2762 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2763 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2764 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2765 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2768 /* handle interfaces */
2769 if (tb->interfaces) {
2770 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2772 table->rows += mono_array_length (tb->interfaces);
2773 alloc_table (table, table->rows);
2774 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2775 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2776 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2777 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2778 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2779 values += MONO_INTERFACEIMPL_SIZE;
2785 table = &assembly->tables [MONO_TABLE_FIELD];
2786 table->rows += tb->num_fields;
2787 alloc_table (table, table->rows);
2788 for (i = 0; i < tb->num_fields; ++i)
2789 mono_image_get_field_info (
2790 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2793 /* handle constructors */
2795 table = &assembly->tables [MONO_TABLE_METHOD];
2796 table->rows += mono_array_length (tb->ctors);
2797 alloc_table (table, table->rows);
2798 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2799 mono_image_get_ctor_info (domain,
2800 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2803 /* handle methods */
2805 table = &assembly->tables [MONO_TABLE_METHOD];
2806 table->rows += tb->num_methods;
2807 alloc_table (table, table->rows);
2808 for (i = 0; i < tb->num_methods; ++i)
2809 mono_image_get_method_info (
2810 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2813 /* Do the same with properties etc.. */
2814 if (tb->events && mono_array_length (tb->events)) {
2815 table = &assembly->tables [MONO_TABLE_EVENT];
2816 table->rows += mono_array_length (tb->events);
2817 alloc_table (table, table->rows);
2818 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2820 alloc_table (table, table->rows);
2821 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2822 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2823 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2824 for (i = 0; i < mono_array_length (tb->events); ++i)
2825 mono_image_get_event_info (
2826 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2828 if (tb->properties && mono_array_length (tb->properties)) {
2829 table = &assembly->tables [MONO_TABLE_PROPERTY];
2830 table->rows += mono_array_length (tb->properties);
2831 alloc_table (table, table->rows);
2832 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2834 alloc_table (table, table->rows);
2835 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2836 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2837 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2838 for (i = 0; i < mono_array_length (tb->properties); ++i)
2839 mono_image_get_property_info (
2840 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2843 /* handle generic parameters */
2844 if (tb->generic_params) {
2845 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2846 table->rows += mono_array_length (tb->generic_params);
2847 alloc_table (table, table->rows);
2848 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2849 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2851 mono_image_get_generic_param_info (
2852 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2856 mono_image_add_decl_security (assembly,
2857 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2861 MonoDynamicTable *ntable;
2863 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2864 ntable->rows += mono_array_length (tb->subtypes);
2865 alloc_table (ntable, ntable->rows);
2866 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2868 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2869 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2871 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2872 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2873 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2874 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2875 mono_string_to_utf8 (tb->name), tb->table_idx,
2876 ntable->next_idx, ntable->rows);*/
2877 values += MONO_NESTED_CLASS_SIZE;
2884 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2888 g_ptr_array_add (types, type);
2890 if (!type->subtypes)
2893 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2894 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2895 collect_types (types, subtype);
2900 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2901 MonoReflectionTypeBuilder **type2)
2903 if ((*type1)->table_idx < (*type2)->table_idx)
2906 if ((*type1)->table_idx > (*type2)->table_idx)
2913 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2918 for (i = 0; i < mono_array_length (pinfo); ++i) {
2919 MonoReflectionParamBuilder *pb;
2920 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2923 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2928 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2931 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2933 for (i = 0; i < tb->num_fields; ++i) {
2934 MonoReflectionFieldBuilder* fb;
2935 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2936 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2940 for (i = 0; i < mono_array_length (tb->events); ++i) {
2941 MonoReflectionEventBuilder* eb;
2942 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2943 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2946 if (tb->properties) {
2947 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2948 MonoReflectionPropertyBuilder* pb;
2949 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2950 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2954 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2955 MonoReflectionCtorBuilder* cb;
2956 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2957 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2958 params_add_cattrs (assembly, cb->pinfo);
2963 for (i = 0; i < tb->num_methods; ++i) {
2964 MonoReflectionMethodBuilder* mb;
2965 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2966 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2967 params_add_cattrs (assembly, mb->pinfo);
2972 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2973 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2978 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2981 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
2983 /* no types in the module */
2987 for (i = 0; i < mb->num_types; ++i)
2988 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2992 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2993 MonoDynamicImage *assembly)
2995 MonoDynamicTable *table;
2999 char *b = blob_size;
3002 table = &assembly->tables [MONO_TABLE_FILE];
3004 alloc_table (table, table->rows);
3005 values = table->values + table->next_idx * MONO_FILE_SIZE;
3006 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3007 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3008 if (module->image->dynamic) {
3009 /* This depends on the fact that the main module is emitted last */
3010 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3011 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3015 path = g_strdup (module->image->name);
3017 mono_sha1_get_digest_from_file (path, hash);
3020 mono_metadata_encode_value (20, b, &b);
3021 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3022 mono_image_add_stream_data (&assembly->blob, hash, 20);
3027 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3029 MonoDynamicTable *table;
3033 table = &assembly->tables [MONO_TABLE_MODULE];
3034 mb->table_idx = table->next_idx ++;
3035 name = mono_string_to_utf8 (mb->module.name);
3036 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3038 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3041 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3042 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3043 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3047 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3048 guint32 module_index, guint32 parent_index,
3049 MonoDynamicImage *assembly)
3051 MonoDynamicTable *table;
3055 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3056 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3059 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3061 alloc_table (table, table->rows);
3062 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3064 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3065 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3066 if (klass->nested_in)
3067 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3069 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3070 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3071 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3073 res = table->next_idx;
3077 /* Emit nested types */
3078 if (klass->nested_classes) {
3081 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3082 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3089 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3090 guint32 module_index, guint32 parent_index,
3091 MonoDynamicImage *assembly)
3096 klass = mono_class_from_mono_type (tb->type.type);
3098 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3100 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3101 parent_index, assembly);
3105 * We need to do this ourselves since klass->nested_classes is not set up.
3108 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3109 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3114 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3115 guint32 module_index,
3116 MonoDynamicImage *assembly)
3118 MonoImage *image = module->image;
3122 t = &image->tables [MONO_TABLE_TYPEDEF];
3124 for (i = 0; i < t->rows; ++i) {
3125 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3127 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3128 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3132 #define align_pointer(base,p)\
3134 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3136 (p) += 4 - (__diff & 3);\
3140 compare_semantics (const void *a, const void *b)
3142 const guint32 *a_values = a;
3143 const guint32 *b_values = b;
3144 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3147 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3151 compare_custom_attrs (const void *a, const void *b)
3153 const guint32 *a_values = a;
3154 const guint32 *b_values = b;
3156 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3160 compare_field_marshal (const void *a, const void *b)
3162 const guint32 *a_values = a;
3163 const guint32 *b_values = b;
3165 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3169 compare_nested (const void *a, const void *b)
3171 const guint32 *a_values = a;
3172 const guint32 *b_values = b;
3174 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3178 compare_genericparam (const void *a, const void *b)
3180 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3181 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3183 return (*a_entry)->owner - (*b_entry)->owner;
3187 pad_heap (MonoDynamicStream *sh)
3189 if (sh->index & 3) {
3190 int sz = 4 - (sh->index & 3);
3191 memset (sh->data + sh->index, 0, sz);
3196 static struct StreamDesc {
3198 MonoDynamicStream *stream;
3202 * build_compressed_metadata() fills in the blob of data that represents the
3203 * raw metadata as it will be saved in the PE file. The five streams are output
3204 * and the metadata tables are comnpressed from the guint32 array representation,
3205 * to the compressed on-disk format.
3208 build_compressed_metadata (MonoDynamicImage *assembly)
3210 MonoDynamicTable *table;
3212 guint64 valid_mask = 0;
3213 guint64 sorted_mask;
3214 guint32 heapt_size = 0;
3215 guint32 meta_size = 256; /* allow for header and other stuff */
3216 guint32 table_offset;
3217 guint32 ntables = 0;
3224 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3225 for (i = 0; i < assembly->gen_params->len; i++){
3226 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3227 write_generic_param_entry (assembly, entry);
3230 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3231 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3232 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3233 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3234 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3236 /* tables that are sorted */
3237 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3238 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3239 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3240 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3241 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3242 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3244 /* Compute table sizes */
3245 /* the MonoImage has already been created in mono_image_basic_init() */
3246 meta = &assembly->image;
3248 /* sizes should be multiple of 4 */
3249 pad_heap (&assembly->blob);
3250 pad_heap (&assembly->guid);
3251 pad_heap (&assembly->sheap);
3252 pad_heap (&assembly->us);
3254 /* Setup the info used by compute_sizes () */
3255 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3256 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3257 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3259 meta_size += assembly->blob.index;
3260 meta_size += assembly->guid.index;
3261 meta_size += assembly->sheap.index;
3262 meta_size += assembly->us.index;
3264 for (i=0; i < 64; ++i)
3265 meta->tables [i].rows = assembly->tables [i].rows;
3267 for (i = 0; i < 64; i++){
3268 if (meta->tables [i].rows == 0)
3270 valid_mask |= (guint64)1 << i;
3272 meta->tables [i].row_size = mono_metadata_compute_size (
3273 meta, i, &meta->tables [i].size_bitfield);
3274 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3276 heapt_size += 24; /* #~ header size */
3277 heapt_size += ntables * 4;
3278 /* make multiple of 4 */
3281 meta_size += heapt_size;
3282 meta->raw_metadata = g_malloc0 (meta_size);
3283 p = meta->raw_metadata;
3284 /* the metadata signature */
3285 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3286 /* version numbers and 4 bytes reserved */
3287 int16val = (guint16*)p;
3288 *int16val++ = GUINT16_TO_LE (1);
3289 *int16val = GUINT16_TO_LE (1);
3291 /* version string */
3292 int32val = (guint32*)p;
3293 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3295 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3296 p += GUINT32_FROM_LE (*int32val);
3297 align_pointer (meta->raw_metadata, p);
3298 int16val = (guint16*)p;
3299 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3300 *int16val = GUINT16_TO_LE (5); /* number of streams */
3304 * write the stream info.
3306 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3307 table_offset += 3; table_offset &= ~3;
3309 assembly->tstream.index = heapt_size;
3310 for (i = 0; i < 5; ++i) {
3311 int32val = (guint32*)p;
3312 stream_desc [i].stream->offset = table_offset;
3313 *int32val++ = GUINT32_TO_LE (table_offset);
3314 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3315 table_offset += GUINT32_FROM_LE (*int32val);
3316 table_offset += 3; table_offset &= ~3;
3318 strcpy (p, stream_desc [i].name);
3319 p += strlen (stream_desc [i].name) + 1;
3320 align_pointer (meta->raw_metadata, p);
3323 * now copy the data, the table stream header and contents goes first.
3325 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3326 p = meta->raw_metadata + assembly->tstream.offset;
3327 int32val = (guint32*)p;
3328 *int32val = GUINT32_TO_LE (0); /* reserved */
3331 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3332 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3333 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3334 *p++ = 1; /* version */
3337 *p++ = 1; /* version */
3341 if (meta->idx_string_wide)
3343 if (meta->idx_guid_wide)
3345 if (meta->idx_blob_wide)
3348 *p++ = 0; /* reserved */
3349 int64val = (guint64*)p;
3350 *int64val++ = GUINT64_TO_LE (valid_mask);
3351 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3353 int32val = (guint32*)p;
3354 for (i = 0; i < 64; i++){
3355 if (meta->tables [i].rows == 0)
3357 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3359 p = (unsigned char*)int32val;
3361 /* sort the tables that still need sorting */
3362 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3364 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3365 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3367 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3368 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3370 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3371 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3373 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3376 /* compress the tables */
3377 for (i = 0; i < 64; i++){
3380 guint32 bitfield = meta->tables [i].size_bitfield;
3381 if (!meta->tables [i].rows)
3383 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3384 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3385 meta->tables [i].base = p;
3386 for (row = 1; row <= meta->tables [i].rows; ++row) {
3387 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3388 for (col = 0; col < assembly->tables [i].columns; ++col) {
3389 switch (mono_metadata_table_size (bitfield, col)) {
3391 *p++ = values [col];
3394 *p++ = values [col] & 0xff;
3395 *p++ = (values [col] >> 8) & 0xff;
3398 *p++ = values [col] & 0xff;
3399 *p++ = (values [col] >> 8) & 0xff;
3400 *p++ = (values [col] >> 16) & 0xff;
3401 *p++ = (values [col] >> 24) & 0xff;
3404 g_assert_not_reached ();
3408 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3411 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3412 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3413 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3414 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3415 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3417 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3421 * Some tables in metadata need to be sorted according to some criteria, but
3422 * when methods and fields are first created with reflection, they may be assigned a token
3423 * that doesn't correspond to the final token they will get assigned after the sorting.
3424 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3425 * with the reflection objects that represent them. Once all the tables are set up, the
3426 * reflection objects will contains the correct table index. fixup_method() will fixup the
3427 * tokens for the method with ILGenerator @ilgen.
3430 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3431 guint32 code_idx = GPOINTER_TO_UINT (value);
3432 MonoReflectionILTokenInfo *iltoken;
3433 MonoReflectionFieldBuilder *field;
3434 MonoReflectionCtorBuilder *ctor;
3435 MonoReflectionMethodBuilder *method;
3436 MonoReflectionTypeBuilder *tb;
3437 MonoReflectionArrayMethod *am;
3439 unsigned char *target;
3441 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3442 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3443 target = assembly->code.data + code_idx + iltoken->code_pos;
3444 switch (target [3]) {
3445 case MONO_TABLE_FIELD:
3446 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3447 field = (MonoReflectionFieldBuilder *)iltoken->member;
3448 idx = field->table_idx;
3449 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3450 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3451 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3453 g_assert_not_reached ();
3456 case MONO_TABLE_METHOD:
3457 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3458 method = (MonoReflectionMethodBuilder *)iltoken->member;
3459 idx = method->table_idx;
3460 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3461 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3462 idx = ctor->table_idx;
3463 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3464 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3465 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3466 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3468 g_assert_not_reached ();
3471 case MONO_TABLE_TYPEDEF:
3472 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3473 g_assert_not_reached ();
3474 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3475 idx = tb->table_idx;
3477 case MONO_TABLE_MEMBERREF:
3478 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3479 am = (MonoReflectionArrayMethod*)iltoken->member;
3480 idx = am->table_idx;
3481 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3482 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3483 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3484 g_assert (m->klass->generic_inst);
3486 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3488 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3489 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3490 g_assert (f->generic_info);
3492 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3495 g_assert_not_reached ();
3498 case MONO_TABLE_METHODSPEC:
3499 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3500 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3501 g_assert (m->signature->generic_param_count);
3504 g_assert_not_reached ();
3508 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3510 target [0] = idx & 0xff;
3511 target [1] = (idx >> 8) & 0xff;
3512 target [2] = (idx >> 16) & 0xff;
3519 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3520 * value is not known when the table is emitted.
3523 fixup_cattrs (MonoDynamicImage *assembly)
3525 MonoDynamicTable *table;
3527 guint32 type, i, idx, token;
3530 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3532 for (i = 0; i < table->rows; ++i) {
3533 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3535 type = values [MONO_CUSTOM_ATTR_TYPE];
3536 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3537 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3538 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3539 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3542 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3543 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3544 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3545 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3552 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3554 MonoDynamicTable *table;
3558 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3560 alloc_table (table, table->rows);
3561 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3562 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3563 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3564 name = mono_string_to_utf8 (rsrc->name);
3565 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3567 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3572 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3574 MonoDynamicTable *table;
3578 char *b = blob_size;
3580 guint32 idx, offset;
3582 if (rsrc->filename) {
3583 name = mono_string_to_utf8 (rsrc->filename);
3584 sname = g_path_get_basename (name);
3586 table = &assembly->tables [MONO_TABLE_FILE];
3588 alloc_table (table, table->rows);
3589 values = table->values + table->next_idx * MONO_FILE_SIZE;
3590 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3591 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3594 mono_sha1_get_digest_from_file (name, hash);
3595 mono_metadata_encode_value (20, b, &b);
3596 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3597 mono_image_add_stream_data (&assembly->blob, hash, 20);
3599 idx = table->next_idx++;
3601 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3604 offset = mono_array_length (rsrc->data);
3605 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3606 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3607 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3608 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3612 * The entry should be emitted into the MANIFESTRESOURCE table of
3613 * the main module, but that needs to reference the FILE table
3614 * which isn't emitted yet.
3621 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3625 set_version_from_string (MonoString *version, guint32 *values)
3627 gchar *ver, *p, *str;
3630 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3631 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3632 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3633 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3636 ver = str = mono_string_to_utf8 (version);
3637 for (i = 0; i < 4; ++i) {
3638 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3644 /* handle Revision and Build */
3654 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3658 char *b = blob_size;
3663 len = mono_array_length (pkey);
3664 mono_metadata_encode_value (len, b, &b);
3665 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3666 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3668 /* need to get the actual value from the key type... */
3669 assembly->strong_name_size = 128;
3670 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3676 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3678 MonoDynamicTable *table;
3679 MonoDynamicImage *assembly;
3680 MonoReflectionAssemblyBuilder *assemblyb;
3685 guint32 module_index;
3687 assemblyb = moduleb->assemblyb;
3688 assembly = moduleb->dynamic_image;
3689 domain = mono_object_domain (assemblyb);
3691 /* Emit ASSEMBLY table */
3692 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3693 alloc_table (table, 1);
3694 values = table->values + MONO_ASSEMBLY_SIZE;
3695 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3696 name = mono_string_to_utf8 (assemblyb->name);
3697 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3699 if (assemblyb->culture) {
3700 name = mono_string_to_utf8 (assemblyb->culture);
3701 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3704 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3706 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3707 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3708 set_version_from_string (assemblyb->version, values);
3710 /* Emit FILE + EXPORTED_TYPE table */
3712 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3714 MonoReflectionModuleBuilder *file_module =
3715 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3716 if (file_module != moduleb) {
3717 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3719 if (file_module->types) {
3720 for (j = 0; j < file_module->num_types; ++j) {
3721 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3722 mono_image_fill_export_table (domain, tb, module_index, 0,
3728 if (assemblyb->loaded_modules) {
3729 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3730 MonoReflectionModule *file_module =
3731 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3732 mono_image_fill_file_table (domain, file_module, assembly);
3734 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3738 /* Emit MANIFESTRESOURCE table */
3740 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3742 MonoReflectionModuleBuilder *file_module =
3743 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3744 /* The table for the main module is emitted later */
3745 if (file_module != moduleb) {
3747 if (file_module->resources) {
3748 int len = mono_array_length (file_module->resources);
3749 for (j = 0; j < len; ++j) {
3750 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3751 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3759 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3760 * for the modulebuilder @moduleb.
3761 * At the end of the process, method and field tokens are fixed up and the
3762 * on-disk compressed metadata representation is created.
3765 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3767 MonoDynamicTable *table;
3768 MonoDynamicImage *assembly;
3769 MonoReflectionAssemblyBuilder *assemblyb;
3774 assemblyb = moduleb->assemblyb;
3775 assembly = moduleb->dynamic_image;
3776 domain = mono_object_domain (assemblyb);
3778 if (assembly->text_rva)
3781 assembly->text_rva = START_TEXT_RVA;
3783 if (moduleb->is_main) {
3784 mono_image_emit_manifest (moduleb);
3787 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3788 table->rows = 1; /* .<Module> */
3790 alloc_table (table, table->rows);
3792 * Set the first entry.
3794 values = table->values + table->columns;
3795 values [MONO_TYPEDEF_FLAGS] = 0;
3796 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3797 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3798 values [MONO_TYPEDEF_EXTENDS] = 0;
3799 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3800 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3803 * handle global methods
3804 * FIXME: test what to do when global methods are defined in multiple modules.
3806 if (moduleb->global_methods) {
3807 table = &assembly->tables [MONO_TABLE_METHOD];
3808 table->rows += mono_array_length (moduleb->global_methods);
3809 alloc_table (table, table->rows);
3810 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3811 mono_image_get_method_info (
3812 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3814 if (moduleb->global_fields) {
3815 table = &assembly->tables [MONO_TABLE_FIELD];
3816 table->rows += mono_array_length (moduleb->global_fields);
3817 alloc_table (table, table->rows);
3818 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3819 mono_image_get_field_info (
3820 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3823 table = &assembly->tables [MONO_TABLE_MODULE];
3824 alloc_table (table, 1);
3825 mono_image_fill_module_table (domain, moduleb, assembly);
3829 /* Collect all types into a list sorted by their table_idx */
3830 GPtrArray *types = g_ptr_array_new ();
3833 for (i = 0; i < moduleb->num_types; ++i) {
3834 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3835 collect_types (types, type);
3838 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3839 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3840 table->rows += types->len;
3841 alloc_table (table, table->rows);
3843 for (i = 0; i < types->len; ++i) {
3844 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3845 mono_image_get_type_info (domain, type, assembly);
3847 g_ptr_array_free (types, TRUE);
3851 * table->rows is already set above and in mono_image_fill_module_table.
3853 /* add all the custom attributes at the end, once all the indexes are stable */
3854 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3856 module_add_cattrs (assembly, moduleb);
3859 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3860 fixup_cattrs (assembly);
3864 * mono_image_insert_string:
3865 * @module: module builder object
3868 * Insert @str into the user string stream of @module.
3871 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3873 MonoDynamicImage *assembly;
3878 MONO_ARCH_SAVE_REGS;
3880 if (!module->dynamic_image)
3881 mono_image_module_basic_init (module);
3883 assembly = module->dynamic_image;
3885 if (assembly->save) {
3886 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3887 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3888 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3890 char *swapped = g_malloc (2 * mono_string_length (str));
3891 const char *p = (const char*)mono_string_chars (str);
3893 swap_with_size (swapped, p, 2, mono_string_length (str));
3894 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3898 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3900 mono_image_add_stream_data (&assembly->us, "", 1);
3903 idx = assembly->us.index ++;
3905 mono_g_hash_table_insert (assembly->tokens,
3906 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3908 return MONO_TOKEN_STRING | idx;
3912 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj,
3913 MonoArray *opt_param_types)
3918 klass = obj->vtable->klass;
3919 if (strcmp (klass->name, "MonoMethod") == 0) {
3920 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3921 MonoMethodSignature *sig, *old;
3922 guint32 sig_token, parent;
3925 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3927 nargs = mono_array_length (opt_param_types);
3928 old = method->signature;
3929 sig = mono_metadata_signature_alloc (
3930 &assembly->image, old->param_count + nargs);
3932 sig->hasthis = old->hasthis;
3933 sig->explicit_this = old->explicit_this;
3934 sig->call_convention = old->call_convention;
3935 sig->generic_param_count = old->generic_param_count;
3936 sig->param_count = old->param_count + nargs;
3937 sig->sentinelpos = old->param_count;
3938 sig->ret = old->ret;
3940 for (i = 0; i < old->param_count; i++)
3941 sig->params [i] = old->params [i];
3943 for (i = 0; i < nargs; i++) {
3944 MonoReflectionType *rt = mono_array_get (
3945 opt_param_types, MonoReflectionType *, i);
3946 sig->params [old->param_count + i] = rt->type;
3949 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
3950 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
3951 parent >>= MONO_TYPEDEFORREF_BITS;
3953 parent <<= MONO_MEMBERREF_PARENT_BITS;
3954 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
3956 sig_token = method_encode_signature (assembly, sig);
3957 token = mono_image_get_varargs_method_token (
3958 assembly, parent, method->name, sig_token);
3959 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
3960 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3961 ReflectionMethodBuilder rmb;
3962 guint32 parent, sig;
3964 reflection_methodbuilder_from_method_builder (&rmb, mb);
3965 rmb.opt_types = opt_param_types;
3967 sig = method_builder_encode_signature (assembly, &rmb);
3969 parent = mono_image_create_token (assembly, obj, TRUE);
3970 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
3972 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
3973 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
3975 token = mono_image_get_varargs_method_token (
3976 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
3978 g_error ("requested method token for %s\n", klass->name);
3984 * mono_image_create_token:
3985 * @assembly: a dynamic assembly
3988 * Get a token to insert in the IL code stream for the given MemberInfo.
3989 * @obj can be one of:
3990 * ConstructorBuilder
4000 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4001 gboolean create_methodspec)
4006 klass = obj->vtable->klass;
4007 if (strcmp (klass->name, "MethodBuilder") == 0) {
4008 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4010 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4011 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4013 token = mono_image_get_methodbuilder_token (assembly, mb);
4014 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4016 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4017 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4019 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4020 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4022 token = mono_image_get_ctorbuilder_token (assembly, mb);
4023 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4025 else if (strcmp (klass->name, "FieldBuilder") == 0) {
4026 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4027 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4028 if (tb->generic_params) {
4029 token = mono_image_get_generic_field_token (assembly, fb);
4031 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4034 else if (strcmp (klass->name, "TypeBuilder") == 0) {
4035 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4036 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4038 else if (strcmp (klass->name, "MonoType") == 0 ||
4039 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4040 MonoReflectionType *tb = (MonoReflectionType *)obj;
4041 token = mono_metadata_token_from_dor (
4042 mono_image_typedef_or_ref (assembly, tb->type));
4044 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
4045 MonoReflectionType *tb = (MonoReflectionType *)obj;
4046 token = mono_metadata_token_from_dor (
4047 mono_image_typedef_or_ref (assembly, tb->type));
4049 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4050 strcmp (klass->name, "MonoMethod") == 0) {
4051 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4052 if (m->method->signature->is_inflated) {
4053 if (create_methodspec)
4054 token = mono_image_get_methodspec_token (
4055 assembly, m->method);
4057 token = mono_image_get_inflated_method_token (
4058 assembly, m->method);
4059 } else if (m->method->signature->generic_param_count) {
4060 g_assert_not_reached ();
4061 } else if ((m->method->klass->image == &assembly->image) &&
4062 !m->method->klass->generic_inst) {
4063 static guint32 method_table_idx = 0xffffff;
4064 if (m->method->klass->wastypebuilder) {
4065 /* we use the same token as the one that was assigned
4066 * to the Methodbuilder.
4067 * FIXME: do the equivalent for Fields.
4069 token = m->method->token;
4072 * Each token should have a unique index, but the indexes are
4073 * assigned by managed code, so we don't know about them. An
4074 * easy solution is to count backwards...
4076 method_table_idx --;
4077 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4080 token = mono_image_get_methodref_token (assembly, m->method);
4081 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4083 else if (strcmp (klass->name, "MonoField") == 0) {
4084 MonoReflectionField *f = (MonoReflectionField *)obj;
4085 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4086 static guint32 field_table_idx = 0xffffff;
4088 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4090 token = mono_image_get_fieldref_token (assembly, f);
4091 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4093 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4094 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4095 token = mono_image_get_array_token (assembly, m);
4097 else if (strcmp (klass->name, "SignatureHelper") == 0) {
4098 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4099 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4102 g_error ("requested token for %s\n", klass->name);
4104 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
4111 guint32 import_lookup_table;
4115 guint32 import_address_table_rva;
4123 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4125 static MonoDynamicImage*
4126 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
4127 char *assembly_name, char *module_name)
4129 static const guchar entrycode [16] = {0xff, 0x25, 0};
4130 MonoDynamicImage *image;
4133 const char *version = mono_get_runtime_version ();
4136 image = GC_MALLOC (sizeof (MonoDynamicImage));
4138 image = g_new0 (MonoDynamicImage, 1);
4141 /* keep in sync with image.c */
4142 image->image.name = assembly_name;
4143 image->image.assembly_name = image->image.name; /* they may be different */
4144 image->image.module_name = module_name;
4145 image->image.version = g_strdup (version);
4146 image->image.dynamic = TRUE;
4148 image->image.references = g_new0 (MonoAssembly*, 1);
4149 image->image.references [0] = NULL;
4151 mono_image_init (&image->image);
4153 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4154 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4155 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4156 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4157 image->handleref = g_hash_table_new (NULL, NULL);
4158 image->tokens = mono_g_hash_table_new (NULL, NULL);
4159 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4160 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4161 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4162 image->gen_params = g_ptr_array_new ();
4164 string_heap_init (&image->sheap);
4165 mono_image_add_stream_data (&image->us, "", 1);
4166 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4167 /* import tables... */
4168 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4169 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4170 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4171 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4172 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4173 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4174 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4175 stream_data_align (&image->code);
4177 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4179 for (i=0; i < 64; ++i) {
4180 image->tables [i].next_idx = 1;
4181 image->tables [i].columns = table_sizes [i];
4184 image->image.assembly = (MonoAssembly*)assembly;
4185 image->run = assembly->run;
4186 image->save = assembly->save;
4192 * mono_image_basic_init:
4193 * @assembly: an assembly builder object
4195 * Create the MonoImage that represents the assembly builder and setup some
4196 * of the helper hash table and the basic metadata streams.
4199 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4201 MonoDynamicAssembly *assembly;
4202 MonoDynamicImage *image;
4204 MONO_ARCH_SAVE_REGS;
4206 if (assemblyb->dynamic_assembly)
4210 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4212 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4215 assembly->assembly.dynamic = TRUE;
4216 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4217 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4218 if (assemblyb->culture)
4219 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4221 assembly->assembly.aname.culture = g_strdup ("");
4223 assembly->run = assemblyb->access != 2;
4224 assembly->save = assemblyb->access != 1;
4226 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4227 assembly->assembly.aname.name = image->image.name;
4228 assembly->assembly.image = &image->image;
4230 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4231 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4235 calc_section_size (MonoDynamicImage *assembly)
4239 /* alignment constraints */
4240 assembly->code.index += 3;
4241 assembly->code.index &= ~3;
4242 assembly->meta_size += 3;
4243 assembly->meta_size &= ~3;
4244 assembly->resources.index += 3;
4245 assembly->resources.index &= ~3;
4247 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4248 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4251 if (assembly->win32_res) {
4252 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4254 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4255 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4259 assembly->sections [MONO_SECTION_RELOC].size = 12;
4260 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4270 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4274 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4276 ResTreeNode *t1 = (ResTreeNode*)a;
4277 ResTreeNode *t2 = (ResTreeNode*)b;
4279 return t1->id - t2->id;
4283 * resource_tree_create:
4285 * Organize the resources into a resource tree.
4287 static ResTreeNode *
4288 resource_tree_create (MonoArray *win32_resources)
4290 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4294 tree = g_new0 (ResTreeNode, 1);
4296 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4297 MonoReflectionWin32Resource *win32_res =
4298 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4302 lang_node = g_new0 (ResTreeNode, 1);
4303 lang_node->id = win32_res->lang_id;
4304 lang_node->win32_res = win32_res;
4306 /* Create type node if neccesary */
4308 for (l = tree->children; l; l = l->next)
4309 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4310 type_node = (ResTreeNode*)l->data;
4315 type_node = g_new0 (ResTreeNode, 1);
4316 type_node->id = win32_res->res_type;
4319 * The resource types have to be sorted otherwise
4320 * Windows Explorer can't display the version information.
4322 tree->children = g_slist_insert_sorted (tree->children, type_node,
4323 resource_tree_compare_by_id);
4326 /* Create res node if neccesary */
4328 for (l = type_node->children; l; l = l->next)
4329 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4330 res_node = (ResTreeNode*)l->data;
4335 res_node = g_new0 (ResTreeNode, 1);
4336 res_node->id = win32_res->res_id;
4337 type_node->children = g_slist_append (type_node->children, res_node);
4340 res_node->children = g_slist_append (res_node->children, lang_node);
4347 * resource_tree_encode:
4349 * Encode the resource tree into the format used in the PE file.
4352 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4355 MonoPEResourceDir dir;
4356 MonoPEResourceDirEntry dir_entry;
4357 MonoPEResourceDataEntry data_entry;
4361 * For the format of the resource directory, see the article
4362 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4366 memset (&dir, 0, sizeof (dir));
4367 memset (&dir_entry, 0, sizeof (dir_entry));
4368 memset (&data_entry, 0, sizeof (data_entry));
4370 g_assert (sizeof (dir) == 16);
4371 g_assert (sizeof (dir_entry) == 8);
4372 g_assert (sizeof (data_entry) == 16);
4374 node->offset = p - begin;
4376 /* IMAGE_RESOURCE_DIRECTORY */
4377 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4379 memcpy (p, &dir, sizeof (dir));
4382 /* Reserve space for entries */
4384 p += sizeof (dir_entry) * dir.res_id_entries;
4386 /* Write children */
4387 for (l = node->children; l; l = l->next) {
4388 ResTreeNode *child = (ResTreeNode*)l->data;
4390 if (child->win32_res) {
4392 child->offset = p - begin;
4394 /* IMAGE_RESOURCE_DATA_ENTRY */
4395 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4396 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4398 memcpy (p, &data_entry, sizeof (data_entry));
4399 p += sizeof (data_entry);
4401 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4402 p += data_entry.rde_size;
4405 resource_tree_encode (child, begin, p, &p);
4408 /* IMAGE_RESOURCE_ENTRY */
4409 for (l = node->children; l; l = l->next) {
4410 ResTreeNode *child = (ResTreeNode*)l->data;
4411 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4413 dir_entry.is_dir = child->win32_res ? 0 : 1;
4414 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4416 memcpy (entries, &dir_entry, sizeof (dir_entry));
4417 entries += sizeof (dir_entry);
4424 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4429 MonoReflectionWin32Resource *win32_res;
4432 if (!assemblyb->win32_resources)
4436 * Resources are stored in a three level tree inside the PE file.
4437 * - level one contains a node for each type of resource
4438 * - level two contains a node for each resource
4439 * - level three contains a node for each instance of a resource for a
4440 * specific language.
4443 tree = resource_tree_create (assemblyb->win32_resources);
4445 /* Estimate the size of the encoded tree */
4447 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4448 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4449 size += mono_array_length (win32_res->res_data);
4451 /* Directory structure */
4452 size += mono_array_length (assemblyb->win32_resources) * 256;
4453 p = buf = g_malloc (size);
4455 resource_tree_encode (tree, p, p, &p);
4457 g_assert (p - buf < size);
4459 assembly->win32_res = g_malloc (p - buf);
4460 assembly->win32_res_size = p - buf;
4461 memcpy (assembly->win32_res, buf, p - buf);
4467 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4469 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4472 p += sizeof (MonoPEResourceDir);
4473 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4474 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4475 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4476 if (dir_entry->is_dir)
4477 fixup_resource_directory (res_section, child, rva);
4479 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4480 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4483 p += sizeof (MonoPEResourceDirEntry);
4488 * mono_image_create_pefile:
4489 * @mb: a module builder object
4491 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4492 * assembly->pefile where it can be easily retrieved later in chunks.
4495 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4496 MonoMSDOSHeader *msdos;
4497 MonoDotNetHeader *header;
4498 MonoSectionTable *section;
4499 MonoCLIHeader *cli_header;
4500 guint32 size, image_size, virtual_base, text_offset;
4501 guint32 header_start, section_start, file_offset, virtual_offset;
4502 MonoDynamicImage *assembly;
4503 MonoReflectionAssemblyBuilder *assemblyb;
4504 MonoDynamicStream *pefile;
4506 guint32 *rva, value;
4509 static const unsigned char msheader[] = {
4510 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4511 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4514 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4515 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4516 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4517 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4520 assemblyb = mb->assemblyb;
4522 mono_image_basic_init (assemblyb);
4523 assembly = mb->dynamic_image;
4525 /* already created */
4526 if (assembly->pefile.index)
4529 mono_image_build_metadata (mb);
4531 if (mb->is_main && assemblyb->resources) {
4532 int len = mono_array_length (assemblyb->resources);
4533 for (i = 0; i < len; ++i)
4534 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4537 if (mb->resources) {
4538 int len = mono_array_length (mb->resources);
4539 for (i = 0; i < len; ++i)
4540 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4543 build_compressed_metadata (assembly);
4546 assembly_add_win32_resources (assembly, assemblyb);
4548 nsections = calc_section_size (assembly);
4550 pefile = &assembly->pefile;
4552 /* The DOS header and stub */
4553 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4554 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4556 /* the dotnet header */
4557 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4559 /* the section tables */
4560 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4562 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4563 virtual_offset = VIRT_ALIGN;
4566 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4567 if (!assembly->sections [i].size)
4570 file_offset += FILE_ALIGN - 1;
4571 file_offset &= ~(FILE_ALIGN - 1);
4572 virtual_offset += VIRT_ALIGN - 1;
4573 virtual_offset &= ~(VIRT_ALIGN - 1);
4575 assembly->sections [i].offset = file_offset;
4576 assembly->sections [i].rva = virtual_offset;
4578 file_offset += assembly->sections [i].size;
4579 virtual_offset += assembly->sections [i].size;
4580 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4583 file_offset += FILE_ALIGN - 1;
4584 file_offset &= ~(FILE_ALIGN - 1);
4585 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4587 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4589 /* back-patch info */
4590 msdos = (MonoMSDOSHeader*)pefile->data;
4591 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4592 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4593 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4595 header = (MonoDotNetHeader*)(pefile->data + header_start);
4596 header->pesig [0] = 'P';
4597 header->pesig [1] = 'E';
4599 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4600 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4601 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4602 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4603 if (assemblyb->pekind == 1) {
4605 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4608 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4611 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4613 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4614 header->pe.pe_major = 6;
4615 header->pe.pe_minor = 0;
4616 size = assembly->sections [MONO_SECTION_TEXT].size;
4617 size += FILE_ALIGN - 1;
4618 size &= ~(FILE_ALIGN - 1);
4619 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4620 size = assembly->sections [MONO_SECTION_RSRC].size;
4621 size += FILE_ALIGN - 1;
4622 size &= ~(FILE_ALIGN - 1);
4623 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4624 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4625 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4626 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4627 /* pe_rva_entry_point always at the beginning of the text section */
4628 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4630 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4631 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4632 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4633 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4634 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4635 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4636 size = section_start;
4637 size += FILE_ALIGN - 1;
4638 size &= ~(FILE_ALIGN - 1);
4639 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4641 size += VIRT_ALIGN - 1;
4642 size &= ~(VIRT_ALIGN - 1);
4643 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4646 // Translate the PEFileKind value to the value expected by the Windows loader
4652 // PEFileKinds.Dll == 1
4653 // PEFileKinds.ConsoleApplication == 2
4654 // PEFileKinds.WindowApplication == 3
4657 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4658 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4660 if (assemblyb->pekind == 3)
4665 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4667 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4668 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4669 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4670 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4671 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4672 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4674 /* fill data directory entries */
4676 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4677 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4679 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4680 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4682 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4683 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4684 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4685 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4686 /* patch imported function RVA name */
4687 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4688 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4690 /* the import table */
4691 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4692 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4693 /* patch imported dll RVA name and other entries in the dir */
4694 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4695 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4696 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4697 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4698 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4699 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4701 p = (assembly->code.data + assembly->ilt_offset);
4702 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4703 *p++ = (value) & 0xff;
4704 *p++ = (value >> 8) & (0xff);
4705 *p++ = (value >> 16) & (0xff);
4706 *p++ = (value >> 24) & (0xff);
4708 /* the CLI header info */
4709 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4710 cli_header->ch_size = GUINT32_FROM_LE (72);
4711 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4712 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4713 if (assemblyb->entry_point) {
4714 guint32 table_idx = 0;
4715 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4716 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4717 table_idx = methodb->table_idx;
4720 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4721 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4724 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4725 /* The embedded managed resources */
4726 text_offset = assembly->text_rva + assembly->code.index;
4727 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4728 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4729 text_offset += assembly->resources.index;
4730 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4731 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4732 text_offset += assembly->meta_size;
4733 if (assembly->strong_name_size) {
4734 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4735 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4736 text_offset += assembly->strong_name_size;
4739 /* write the section tables and section content */
4740 section = (MonoSectionTable*)(pefile->data + section_start);
4741 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4742 static const char *section_names [] = {
4743 ".text", ".rsrc", ".reloc"
4745 if (!assembly->sections [i].size)
4747 strcpy (section->st_name, section_names [i]);
4748 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4749 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4750 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4751 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4752 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4753 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4754 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4756 case MONO_SECTION_TEXT:
4757 /* patch entry point */
4758 p = (assembly->code.data + 2);
4759 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4760 *p++ = (value) & 0xff;
4761 *p++ = (value >> 8) & 0xff;
4762 *p++ = (value >> 16) & 0xff;
4763 *p++ = (value >> 24) & 0xff;
4765 text_offset = assembly->sections [i].offset;
4766 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4767 text_offset += assembly->code.index;
4768 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4769 text_offset += assembly->resources.index;
4770 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4771 text_offset += assembly->meta_size;
4772 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4774 g_free (assembly->image.raw_metadata);
4776 case MONO_SECTION_RELOC:
4777 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4778 *rva = GUINT32_FROM_LE (assembly->text_rva);
4780 *rva = GUINT32_FROM_LE (12);
4782 data16 = (guint16*)rva;
4784 * the entrypoint is always at the start of the text section
4785 * 3 is IMAGE_REL_BASED_HIGHLOW
4786 * 2 is patch_size_rva - text_rva
4788 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4790 *data16 = 0; /* terminate */
4792 case MONO_SECTION_RSRC:
4793 if (assembly->win32_res) {
4794 text_offset = assembly->sections [i].offset;
4796 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4797 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4799 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4803 g_assert_not_reached ();
4808 /* check that the file is properly padded */
4811 FILE *f = fopen ("mypetest.exe", "w");
4812 fwrite (pefile->data, pefile->index, 1, f);
4818 MonoReflectionModule *
4819 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4823 MonoImageOpenStatus status;
4824 MonoDynamicAssembly *assembly;
4826 name = mono_string_to_utf8 (fileName);
4828 image = mono_image_open (name, &status);
4831 if (status == MONO_IMAGE_ERROR_ERRNO)
4832 exc = mono_get_exception_file_not_found (fileName);
4834 exc = mono_get_exception_bad_image_format (name);
4836 mono_raise_exception (exc);
4841 assembly = ab->dynamic_assembly;
4842 image->assembly = (MonoAssembly*)assembly;
4844 mono_assembly_load_references (image, &status);
4846 mono_image_close (image);
4847 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4850 return mono_module_get_object (mono_domain_get (), image);
4854 * We need to return always the same object for MethodInfo, FieldInfo etc..
4855 * but we need to consider the reflected type.
4856 * type uses a different hash, since it uses custom hash/equal functions.
4861 MonoClass *refclass;
4865 reflected_equal (gconstpointer a, gconstpointer b) {
4866 const ReflectedEntry *ea = a;
4867 const ReflectedEntry *eb = b;
4869 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4873 reflected_hash (gconstpointer a) {
4874 const ReflectedEntry *ea = a;
4875 return GPOINTER_TO_UINT (ea->item);
4878 #define CHECK_OBJECT(t,p,k) \
4884 mono_domain_lock (domain); \
4885 if (!domain->refobject_hash) \
4886 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4887 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4888 mono_domain_unlock (domain); \
4894 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4896 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4899 #define CACHE_OBJECT(p,o,k) \
4901 ReflectedEntry *e = ALLOC_REFENTRY; \
4903 e->refclass = (k); \
4904 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4905 mono_domain_unlock (domain); \
4909 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4911 /* this is done only once */
4912 mono_domain_lock (domain);
4913 CACHE_OBJECT (assembly, res, NULL);
4917 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4919 /* this is done only once */
4920 mono_domain_lock (domain);
4921 CACHE_OBJECT (module, res, NULL);
4925 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4927 MonoDynamicImage *image = moduleb->dynamic_image;
4928 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4931 * FIXME: we already created an image in mono_image_basic_init (), but
4932 * we don't know which module it belongs to, since that is only
4933 * determined at assembly save time.
4935 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
4936 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4938 moduleb->module.image = &image->image;
4939 moduleb->dynamic_image = image;
4940 register_module (mono_object_domain (moduleb), moduleb, image);
4945 * mono_assembly_get_object:
4946 * @domain: an app domain
4947 * @assembly: an assembly
4949 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4951 MonoReflectionAssembly*
4952 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4954 static MonoClass *System_Reflection_Assembly;
4955 MonoReflectionAssembly *res;
4957 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4958 if (!System_Reflection_Assembly)
4959 System_Reflection_Assembly = mono_class_from_name (
4960 mono_defaults.corlib, "System.Reflection", "Assembly");
4961 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4962 res->assembly = assembly;
4963 CACHE_OBJECT (assembly, res, NULL);
4969 MonoReflectionModule*
4970 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4972 static MonoClass *System_Reflection_Module;
4973 MonoReflectionModule *res;
4975 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4976 if (!System_Reflection_Module)
4977 System_Reflection_Module = mono_class_from_name (
4978 mono_defaults.corlib, "System.Reflection", "Module");
4979 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4982 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4984 res->fqname = mono_string_new (domain, image->name);
4985 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4986 res->scopename = mono_string_new (domain, image->module_name);
4988 mono_image_addref (image);
4990 CACHE_OBJECT (image, res, NULL);
4994 MonoReflectionModule*
4995 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4997 static MonoClass *System_Reflection_Module;
4998 MonoReflectionModule *res;
4999 MonoTableInfo *table;
5000 guint32 cols [MONO_FILE_SIZE];
5002 guint32 i, name_idx;
5005 if (!System_Reflection_Module)
5006 System_Reflection_Module = mono_class_from_name (
5007 mono_defaults.corlib, "System.Reflection", "Module");
5008 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5010 table = &image->tables [MONO_TABLE_FILE];
5011 g_assert (table_index < table->rows);
5012 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5015 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5016 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5018 /* Check whenever the row has a corresponding row in the moduleref table */
5019 table = &image->tables [MONO_TABLE_MODULEREF];
5020 for (i = 0; i < table->rows; ++i) {
5021 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5022 val = mono_metadata_string_heap (image, name_idx);
5023 if (strcmp (val, name) == 0)
5024 res->image = image->modules [i];
5027 res->fqname = mono_string_new (domain, name);
5028 res->name = mono_string_new (domain, name);
5029 res->scopename = mono_string_new (domain, name);
5030 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5036 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5038 if ((t1->type != t2->type) ||
5039 (t1->byref != t2->byref))
5043 case MONO_TYPE_VOID:
5044 case MONO_TYPE_BOOLEAN:
5045 case MONO_TYPE_CHAR:
5056 case MONO_TYPE_STRING:
5059 case MONO_TYPE_OBJECT:
5060 case MONO_TYPE_TYPEDBYREF:
5062 case MONO_TYPE_VALUETYPE:
5063 case MONO_TYPE_CLASS:
5064 case MONO_TYPE_SZARRAY:
5065 return t1->data.klass == t2->data.klass;
5067 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5068 case MONO_TYPE_ARRAY:
5069 if (t1->data.array->rank != t2->data.array->rank)
5071 return t1->data.array->eklass == t2->data.array->eklass;
5072 case MONO_TYPE_GENERICINST: {
5074 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5076 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5078 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5079 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5085 case MONO_TYPE_MVAR:
5086 return t1->data.generic_param == t2->data.generic_param;
5088 g_error ("implement type compare for %0x!", t1->type);
5096 mymono_metadata_type_hash (MonoType *t1)
5102 hash |= t1->byref << 6; /* do not collide with t1->type values */
5104 case MONO_TYPE_VALUETYPE:
5105 case MONO_TYPE_CLASS:
5106 case MONO_TYPE_SZARRAY:
5107 /* check if the distribution is good enough */
5108 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5110 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5115 static MonoReflectionGenericInst*
5116 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5118 static MonoClass *System_Reflection_MonoGenericInst;
5119 MonoReflectionGenericInst *res;
5120 MonoGenericInst *ginst;
5123 if (!System_Reflection_MonoGenericInst) {
5124 System_Reflection_MonoGenericInst = mono_class_from_name (
5125 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5126 g_assert (System_Reflection_MonoGenericInst);
5129 ginst = geninst->data.generic_inst;
5130 gklass = mono_class_from_mono_type (ginst->generic_type);
5132 mono_class_init (ginst->klass);
5134 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5136 res->type.type = geninst;
5137 if (gklass->wastypebuilder && gklass->reflection_info)
5138 res->generic_type = gklass->reflection_info;
5140 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5146 * mono_type_get_object:
5147 * @domain: an app domain
5150 * Return an System.MonoType object representing the type @type.
5153 mono_type_get_object (MonoDomain *domain, MonoType *type)
5155 MonoReflectionType *res;
5156 MonoClass *klass = mono_class_from_mono_type (type);
5158 mono_domain_lock (domain);
5159 if (!domain->type_hash)
5160 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5161 (GCompareFunc)mymono_metadata_type_equal);
5162 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5163 mono_domain_unlock (domain);
5166 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5167 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5168 mono_g_hash_table_insert (domain->type_hash, type, res);
5169 mono_domain_unlock (domain);
5172 if (klass->reflection_info && !klass->wastypebuilder) {
5173 /* g_assert_not_reached (); */
5174 /* should this be considered an error condition? */
5176 mono_domain_unlock (domain);
5177 return klass->reflection_info;
5180 mono_class_init (klass);
5181 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5183 mono_g_hash_table_insert (domain->type_hash, type, res);
5184 mono_domain_unlock (domain);
5189 * mono_method_get_object:
5190 * @domain: an app domain
5192 * @refclass: the reflected type (can be NULL)
5194 * Return an System.Reflection.MonoMethod object representing the method @method.
5196 MonoReflectionMethod*
5197 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5200 * We use the same C representation for methods and constructors, but the type
5201 * name in C# is different.
5205 MonoReflectionMethod *ret;
5208 refclass = method->klass;
5210 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5211 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5212 cname = "MonoCMethod";
5214 cname = "MonoMethod";
5215 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5217 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5218 ret->method = method;
5219 ret->name = mono_string_new (domain, method->name);
5220 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5221 CACHE_OBJECT (method, ret, refclass);
5226 * mono_field_get_object:
5227 * @domain: an app domain
5231 * Return an System.Reflection.MonoField object representing the field @field
5234 MonoReflectionField*
5235 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5237 MonoReflectionField *res;
5240 CHECK_OBJECT (MonoReflectionField *, field, klass);
5241 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5242 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5245 res->name = mono_string_new (domain, field->name);
5246 if (field->generic_info)
5247 res->attrs = field->generic_info->generic_type->attrs;
5249 res->attrs = field->type->attrs;
5250 res->type = mono_type_get_object (domain, field->type);
5251 CACHE_OBJECT (field, res, klass);
5256 * mono_property_get_object:
5257 * @domain: an app domain
5259 * @property: a property
5261 * Return an System.Reflection.MonoProperty object representing the property @property
5264 MonoReflectionProperty*
5265 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5267 MonoReflectionProperty *res;
5270 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5271 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5272 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5274 res->property = property;
5275 CACHE_OBJECT (property, res, klass);
5280 * mono_event_get_object:
5281 * @domain: an app domain
5285 * Return an System.Reflection.MonoEvent object representing the event @event
5288 MonoReflectionEvent*
5289 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5291 MonoReflectionEvent *res;
5294 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5295 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5296 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5299 CACHE_OBJECT (event, res, klass);
5304 * mono_param_get_objects:
5305 * @domain: an app domain
5308 * Return an System.Reflection.ParameterInfo array object representing the parameters
5309 * in the method @method.
5312 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5314 static MonoClass *System_Reflection_ParameterInfo;
5315 MonoArray *res = NULL;
5316 MonoReflectionMethod *member = NULL;
5317 MonoReflectionParameter *param = NULL;
5321 if (!System_Reflection_ParameterInfo)
5322 System_Reflection_ParameterInfo = mono_class_from_name (
5323 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5325 if (!method->signature->param_count)
5326 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5328 /* Note: the cache is based on the address of the signature into the method
5329 * since we already cache MethodInfos with the method as keys.
5331 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5333 member = mono_method_get_object (domain, method, NULL);
5334 names = g_new (char *, method->signature->param_count);
5335 mono_method_get_param_names (method, (const char **) names);
5337 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5338 for (i = 0; i < method->signature->param_count; ++i) {
5339 param = (MonoReflectionParameter *)mono_object_new (domain,
5340 System_Reflection_ParameterInfo);
5341 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5342 param->DefaultValueImpl = NULL; /* FIXME */
5343 param->MemberImpl = (MonoObject*)member;
5344 param->NameImpl = mono_string_new (domain, names [i]);
5345 param->PositionImpl = i;
5346 param->AttrsImpl = method->signature->params [i]->attrs;
5347 mono_array_set (res, gpointer, i, param);
5350 CACHE_OBJECT (&(method->signature), res, NULL);
5355 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5359 memset (assembly, 0, sizeof (MonoAssemblyName));
5361 assembly->culture = "";
5362 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5364 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5367 while (*p == ' ' || *p == ',') {
5376 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5378 assembly->major = strtoul (p, &s, 10);
5379 if (s == p || *s != '.')
5382 assembly->minor = strtoul (p, &s, 10);
5383 if (s == p || *s != '.')
5386 assembly->build = strtoul (p, &s, 10);
5387 if (s == p || *s != '.')
5390 assembly->revision = strtoul (p, &s, 10);
5394 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5396 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5397 assembly->culture = "";
5400 assembly->culture = p;
5401 while (*p && *p != ',') {
5405 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5407 if (strncmp (p, "null", 4) == 0) {
5412 while (*p && *p != ',') {
5415 len = (p - start + 1);
5416 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5417 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5418 g_strlcpy (assembly->public_key_token, start, len);
5421 while (*p && *p != ',')
5425 while (*p == ' ' || *p == ',') {
5439 * mono_reflection_parse_type:
5442 * Parse a type name as accepted by the GetType () method and output the info
5443 * extracted in the info structure.
5444 * the name param will be mangled, so, make a copy before passing it to this function.
5445 * The fields in info will be valid until the memory pointed to by name is valid.
5446 * Returns 0 on parse error.
5447 * See also mono_type_get_name () below.
5450 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5452 char *start, *p, *w, *last_point, *startn;
5453 int in_modifiers = 0;
5454 int isbyref = 0, rank;
5456 start = p = w = name;
5458 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5459 info->name = info->name_space = NULL;
5460 info->nested = NULL;
5461 info->modifiers = NULL;
5463 /* last_point separates the namespace from the name */
5469 *p = 0; /* NULL terminate the name */
5471 info->nested = g_list_append (info->nested, startn);
5472 /* we have parsed the nesting namespace + name */
5476 info->name_space = start;
5478 info->name = last_point + 1;
5480 info->name_space = (char *)"";
5506 info->name_space = start;
5508 info->name = last_point + 1;
5510 info->name_space = (char *)"";
5517 if (isbyref) /* only one level allowed by the spec */
5520 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5524 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5535 else if (*p != '*') /* '*' means unknown lower bound */
5541 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5553 return 0; /* missing assembly name */
5554 if (!assembly_name_to_aname (&info->assembly, p))
5561 if (info->assembly.name)
5564 *w = 0; /* terminate class name */
5565 if (!info->name || !*info->name)
5567 /* add other consistency checks */
5572 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5579 image = mono_defaults.corlib;
5582 klass = mono_class_from_name_case (image, info->name_space, info->name);
5584 klass = mono_class_from_name (image, info->name_space, info->name);
5587 for (mod = info->nested; mod; mod = mod->next) {
5590 mono_class_init (klass);
5591 nested = klass->nested_classes;
5594 klass = nested->data;
5596 if (g_strcasecmp (klass->name, mod->data) == 0)
5599 if (strcmp (klass->name, mod->data) == 0)
5603 nested = nested->next;
5610 mono_class_init (klass);
5611 for (mod = info->modifiers; mod; mod = mod->next) {
5612 modval = GPOINTER_TO_UINT (mod->data);
5613 if (!modval) { /* byref: must be last modifier */
5614 return &klass->this_arg;
5615 } else if (modval == -1) {
5616 klass = mono_ptr_class_get (&klass->byval_arg);
5617 } else { /* array rank */
5618 klass = mono_array_class_get (klass, modval);
5620 mono_class_init (klass);
5623 return &klass->byval_arg;
5627 * mono_reflection_get_type:
5628 * @image: a metadata context
5629 * @info: type description structure
5630 * @ignorecase: flag for case-insensitive string compares
5632 * Build a MonoType from the type description in @info.
5637 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5640 MonoReflectionAssembly *assembly;
5644 type = mono_reflection_get_type_internal (image, info, ignorecase);
5647 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5650 /* Reconstruct the type name */
5651 fullName = g_string_new ("");
5652 if (info->name_space && (info->name_space [0] != '\0'))
5653 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5655 g_string_printf (fullName, info->name);
5656 for (mod = info->nested; mod; mod = mod->next)
5657 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5660 mono_domain_try_type_resolve (
5661 mono_domain_get (), fullName->str, NULL);
5662 if (assembly && (!image || (assembly->assembly->image == image))) {
5664 if (assembly->assembly->dynamic) {
5665 /* Enumerate all modules */
5666 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5670 if (abuilder->modules) {
5671 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5672 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5673 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5679 if (!type && abuilder->loaded_modules) {
5680 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5681 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5682 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5689 type = mono_reflection_get_type_internal (assembly->assembly->image,
5692 g_string_free (fullName, TRUE);
5697 * mono_reflection_type_from_name:
5699 * @image: a metadata context (can be NULL).
5701 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5702 * it defaults to get the type from @image or, if @image is NULL or loading
5703 * from it fails, uses corlib.
5707 mono_reflection_type_from_name (char *name, MonoImage *image)
5710 MonoTypeNameParse info;
5711 MonoAssembly *assembly;
5714 /* Make a copy since parse_type modifies its argument */
5715 tmp = g_strdup (name);
5717 /*g_print ("requested type %s\n", str);*/
5718 if (!mono_reflection_parse_type (tmp, &info)) {
5720 g_list_free (info.modifiers);
5721 g_list_free (info.nested);
5725 if (info.assembly.name) {
5726 assembly = mono_assembly_loaded (&info.assembly);
5728 /* then we must load the assembly ourselve - see #60439 */
5729 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5732 g_list_free (info.modifiers);
5733 g_list_free (info.nested);
5737 image = assembly->image;
5738 } else if (image == NULL) {
5739 image = mono_defaults.corlib;
5742 type = mono_reflection_get_type (image, &info, FALSE);
5743 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5744 image = mono_defaults.corlib;
5745 type = mono_reflection_get_type (image, &info, FALSE);
5749 g_list_free (info.modifiers);
5750 g_list_free (info.nested);
5755 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5757 int slen, type = t->type;
5762 case MONO_TYPE_BOOLEAN: {
5763 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5768 case MONO_TYPE_CHAR:
5770 case MONO_TYPE_I2: {
5771 guint16 *val = g_malloc (sizeof (guint16));
5776 #if SIZEOF_VOID_P == 4
5782 case MONO_TYPE_I4: {
5783 guint32 *val = g_malloc (sizeof (guint32));
5788 #if SIZEOF_VOID_P == 8
5789 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5794 case MONO_TYPE_I8: {
5795 guint64 *val = g_malloc (sizeof (guint64));
5800 case MONO_TYPE_VALUETYPE:
5801 if (t->data.klass->enumtype) {
5802 type = t->data.klass->enum_basetype->type;
5805 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5808 case MONO_TYPE_STRING:
5809 if (*p == (char)0xFF) {
5813 slen = mono_metadata_decode_value (p, &p);
5815 return mono_string_new_len (mono_domain_get (), p, slen);
5816 case MONO_TYPE_CLASS: {
5819 if (*p == (char)0xFF) {
5824 slen = mono_metadata_decode_value (p, &p);
5825 n = g_memdup (p, slen + 1);
5827 t = mono_reflection_type_from_name (n, image);
5829 g_warning ("Cannot load type '%s'", n);
5833 return mono_type_get_object (mono_domain_get (), t);
5837 case MONO_TYPE_OBJECT: {
5840 MonoClass *subc = NULL;
5845 } else if (subt == 0x0E) {
5846 type = MONO_TYPE_STRING;
5848 } else if (subt == 0x55) {
5851 slen = mono_metadata_decode_value (p, &p);
5852 n = g_memdup (p, slen + 1);
5854 t = mono_reflection_type_from_name (n, image);
5856 g_warning ("Cannot load type '%s'", n);
5859 subc = mono_class_from_mono_type (t);
5860 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5861 MonoType simple_type = {{0}};
5862 simple_type.type = subt;
5863 subc = mono_class_from_mono_type (&simple_type);
5865 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5867 val = load_cattr_value (image, &subc->byval_arg, p, end);
5868 obj = mono_object_new (mono_domain_get (), subc);
5869 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5873 case MONO_TYPE_SZARRAY:
5876 guint32 i, alen, basetype;
5879 if (alen == 0xffffffff) {
5883 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5884 basetype = t->data.klass->byval_arg.type;
5889 case MONO_TYPE_BOOLEAN:
5890 for (i=0;i<alen;i++)
5892 MonoBoolean val=*p++;
5893 mono_array_set(arr,MonoBoolean,i,val);
5896 case MONO_TYPE_CHAR:
5899 for (i=0;i<alen;i++)
5901 guint16 val=read16(p);
5902 mono_array_set(arr,guint16,i,val);
5909 for (i=0;i<alen;i++)
5911 guint32 val=read32(p);
5912 mono_array_set(arr,guint32,i,val);
5919 for (i=0;i<alen;i++)
5921 guint64 val=read64(p);
5922 mono_array_set(arr,guint64,i,val);
5926 case MONO_TYPE_CLASS:
5927 case MONO_TYPE_OBJECT:
5928 case MONO_TYPE_STRING:
5929 for (i = 0; i < alen; i++) {
5930 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5931 mono_array_set (arr, gpointer, i, item);
5935 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5941 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5947 type_is_reference (MonoType *type)
5949 switch (type->type) {
5950 case MONO_TYPE_BOOLEAN:
5951 case MONO_TYPE_CHAR:
5964 case MONO_TYPE_VALUETYPE:
5972 free_param_data (MonoMethodSignature *sig, void **params) {
5974 for (i = 0; i < sig->param_count; ++i) {
5975 if (!type_is_reference (sig->params [i]))
5976 g_free (params [i]);
5981 * Find the method index in the metadata methodDef table.
5982 * Later put these three helper methods in metadata and export them.
5985 find_method_index (MonoMethod *method) {
5986 MonoClass *klass = method->klass;
5989 for (i = 0; i < klass->method.count; ++i) {
5990 if (method == klass->methods [i])
5991 return klass->method.first + 1 + i;
5997 * Find the field index in the metadata FieldDef table.
6000 find_field_index (MonoClass *klass, MonoClassField *field) {
6003 for (i = 0; i < klass->field.count; ++i) {
6004 if (field == &klass->fields [i])
6005 return klass->field.first + 1 + i;
6011 * Find the property index in the metadata Property table.
6014 find_property_index (MonoClass *klass, MonoProperty *property) {
6017 for (i = 0; i < klass->property.count; ++i) {
6018 if (property == &klass->properties [i])
6019 return klass->property.first + 1 + i;
6025 * Find the event index in the metadata Event table.
6028 find_event_index (MonoClass *klass, MonoEvent *event) {
6031 for (i = 0; i < klass->event.count; ++i) {
6032 if (event == &klass->events [i])
6033 return klass->event.first + 1 + i;
6039 create_custom_attr (MonoImage *image, MonoMethod *method,
6040 const char *data, guint32 len)
6042 const char *p = data;
6044 guint32 i, j, num_named;
6048 mono_class_init (method->klass);
6051 attr = mono_object_new (mono_domain_get (), method->klass);
6052 mono_runtime_invoke (method, attr, NULL, NULL);
6056 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6059 /*g_print ("got attr %s\n", method->klass->name);*/
6061 params = g_new (void*, method->signature->param_count);
6065 for (i = 0; i < method->signature->param_count; ++i) {
6066 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6070 attr = mono_object_new (mono_domain_get (), method->klass);
6071 mono_runtime_invoke (method, attr, params, NULL);
6072 free_param_data (method->signature, params);
6074 num_named = read16 (named);
6076 for (j = 0; j < num_named; j++) {
6078 char *name, named_type, data_type;
6079 named_type = *named++;
6080 data_type = *named++; /* type of data */
6081 if (data_type == 0x55) {
6084 type_len = mono_metadata_decode_blob_size (named, &named);
6085 type_name = g_malloc (type_len + 1);
6086 memcpy (type_name, named, type_len);
6087 type_name [type_len] = 0;
6089 /* FIXME: lookup the type and check type consistency */
6090 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6091 /* this seems to be the type of the element of the array */
6092 /* g_print ("skipping 0x%02x after prop\n", *named); */
6095 name_len = mono_metadata_decode_blob_size (named, &named);
6096 name = g_malloc (name_len + 1);
6097 memcpy (name, named, name_len);
6098 name [name_len] = 0;
6100 if (named_type == 0x53) {
6101 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6102 void *val = load_cattr_value (image, field->type, named, &named);
6103 mono_field_set_value (attr, field, val);
6104 if (!type_is_reference (field->type))
6106 } else if (named_type == 0x54) {
6109 MonoType *prop_type;
6111 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6112 /* can we have more that 1 arg in a custom attr named property? */
6113 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6114 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6115 mono_property_set_value (prop, attr, pparams, NULL);
6116 if (!type_is_reference (prop_type))
6117 g_free (pparams [0]);
6126 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6133 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6134 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6135 for (i = 0; i < cinfo->num_attrs; ++i) {
6136 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6137 mono_array_set (result, gpointer, i, attr);
6143 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6145 guint32 mtoken, i, len;
6146 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6148 MonoCustomAttrInfo *ainfo;
6149 GList *tmp, *list = NULL;
6152 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6154 i = mono_metadata_custom_attrs_from_index (image, idx);
6158 while (i < ca->rows) {
6159 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6161 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6164 len = g_list_length (list);
6167 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6168 ainfo->num_attrs = len;
6169 ainfo->image = image;
6170 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6171 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6172 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6173 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6174 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6175 mtoken |= MONO_TOKEN_METHOD_DEF;
6177 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6178 mtoken |= MONO_TOKEN_MEMBER_REF;
6181 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6184 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6185 if (!ainfo->attrs [i].ctor)
6186 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6187 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6188 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6189 ainfo->attrs [i].data = data;
6197 mono_custom_attrs_from_method (MonoMethod *method)
6199 MonoCustomAttrInfo *cinfo;
6202 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6204 idx = find_method_index (method);
6205 idx <<= MONO_CUSTOM_ATTR_BITS;
6206 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6207 return mono_custom_attrs_from_index (method->klass->image, idx);
6211 mono_custom_attrs_from_class (MonoClass *klass)
6213 MonoCustomAttrInfo *cinfo;
6216 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6218 idx = mono_metadata_token_index (klass->type_token);
6219 idx <<= MONO_CUSTOM_ATTR_BITS;
6220 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6221 return mono_custom_attrs_from_index (klass->image, idx);
6225 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6227 MonoCustomAttrInfo *cinfo;
6230 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6232 idx = 1; /* there is only one assembly */
6233 idx <<= MONO_CUSTOM_ATTR_BITS;
6234 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6235 return mono_custom_attrs_from_index (assembly->image, idx);
6238 static MonoCustomAttrInfo*
6239 mono_custom_attrs_from_module (MonoImage *image)
6241 MonoCustomAttrInfo *cinfo;
6244 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6246 idx = 1; /* there is only one module */
6247 idx <<= MONO_CUSTOM_ATTR_BITS;
6248 idx |= MONO_CUSTOM_ATTR_MODULE;
6249 return mono_custom_attrs_from_index (image, idx);
6253 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6255 MonoCustomAttrInfo *cinfo;
6258 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6260 idx = find_property_index (klass, property);
6261 idx <<= MONO_CUSTOM_ATTR_BITS;
6262 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6263 return mono_custom_attrs_from_index (klass->image, idx);
6267 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6269 MonoCustomAttrInfo *cinfo;
6272 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6274 idx = find_event_index (klass, event);
6275 idx <<= MONO_CUSTOM_ATTR_BITS;
6276 idx |= MONO_CUSTOM_ATTR_EVENT;
6277 return mono_custom_attrs_from_index (klass->image, idx);
6281 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6283 MonoCustomAttrInfo *cinfo;
6286 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6288 idx = find_field_index (klass, field);
6289 idx <<= MONO_CUSTOM_ATTR_BITS;
6290 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6291 return mono_custom_attrs_from_index (klass->image, idx);
6295 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6298 guint32 i, idx, method_index;
6299 guint32 param_list, param_last, param_pos, found;
6301 MonoReflectionMethodAux *aux;
6303 if (method->klass->image->dynamic) {
6304 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6305 if (!aux || !aux->param_cattr)
6307 return aux->param_cattr [param];
6310 image = method->klass->image;
6311 method_index = find_method_index (method);
6312 ca = &image->tables [MONO_TABLE_METHOD];
6314 if (method->klass->generic_inst || method->klass->gen_params ||
6315 method->signature->generic_param_count) {
6316 /* FIXME FIXME FIXME */
6320 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6321 if (method_index == ca->rows) {
6322 ca = &image->tables [MONO_TABLE_PARAM];
6323 param_last = ca->rows + 1;
6325 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6326 ca = &image->tables [MONO_TABLE_PARAM];
6329 for (i = param_list; i < param_last; ++i) {
6330 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6331 if (param_pos == param) {
6339 idx <<= MONO_CUSTOM_ATTR_BITS;
6340 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6341 return mono_custom_attrs_from_index (image, idx);
6345 * mono_reflection_get_custom_attrs:
6346 * @obj: a reflection object handle
6348 * Return an array with all the custom attributes defined of the
6349 * reflection handle @obj. The objects are fully build.
6352 mono_reflection_get_custom_attrs (MonoObject *obj)
6356 MonoCustomAttrInfo *cinfo = NULL;
6358 MONO_ARCH_SAVE_REGS;
6360 klass = obj->vtable->klass;
6361 /* FIXME: need to handle: Module */
6362 if (klass == mono_defaults.monotype_class) {
6363 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6364 klass = mono_class_from_mono_type (rtype->type);
6365 cinfo = mono_custom_attrs_from_class (klass);
6366 } else if (strcmp ("Assembly", klass->name) == 0) {
6367 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6368 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6369 } else if (strcmp ("Module", klass->name) == 0) {
6370 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6371 cinfo = mono_custom_attrs_from_module (module->image);
6372 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6373 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6374 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6375 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6376 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6377 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6378 } else if (strcmp ("MonoField", klass->name) == 0) {
6379 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6380 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6381 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6382 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6383 cinfo = mono_custom_attrs_from_method (rmethod->method);
6384 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6385 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6386 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6387 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6388 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6389 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6390 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6391 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6392 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6393 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6394 } else { /* handle other types here... */
6395 g_error ("get custom attrs not yet supported for %s", klass->name);
6399 result = mono_custom_attrs_construct (cinfo);
6401 mono_custom_attrs_free (cinfo);
6403 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6404 result = mono_array_new (mono_domain_get (), klass, 0);
6410 static MonoMethodSignature*
6411 parameters_to_signature (MonoArray *parameters) {
6412 MonoMethodSignature *sig;
6415 count = parameters? mono_array_length (parameters): 0;
6417 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6418 sig->param_count = count;
6419 sig->sentinelpos = -1; /* FIXME */
6420 for (i = 0; i < count; ++i) {
6421 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6422 sig->params [i] = pt->type;
6427 static MonoMethodSignature*
6428 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6429 MonoMethodSignature *sig;
6431 sig = parameters_to_signature (ctor->parameters);
6432 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6433 sig->ret = &mono_defaults.void_class->byval_arg;
6437 static MonoMethodSignature*
6438 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6439 MonoMethodSignature *sig;
6441 sig = parameters_to_signature (method->parameters);
6442 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6443 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6444 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6448 static MonoMethodSignature*
6449 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6450 MonoMethodSignature *sig;
6452 sig = parameters_to_signature (method->parameters);
6453 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6454 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6455 sig->generic_param_count = 0;
6460 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6462 MonoClass *klass = mono_object_class (prop);
6463 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6464 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6465 *name = mono_string_to_utf8 (pb->name);
6466 *type = pb->type->type;
6468 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6469 *name = g_strdup (p->property->name);
6470 if (p->property->get)
6471 *type = p->property->get->signature->ret;
6473 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6478 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6480 MonoClass *klass = mono_object_class (field);
6481 if (strcmp (klass->name, "FieldBuilder") == 0) {
6482 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6483 *name = mono_string_to_utf8 (fb->name);
6484 *type = fb->type->type;
6486 MonoReflectionField *f = (MonoReflectionField *)field;
6487 *name = g_strdup (f->field->name);
6488 *type = f->field->type;
6493 * Encode a value in a custom attribute stream of bytes.
6494 * The value to encode is either supplied as an object in argument val
6495 * (valuetypes are boxed), or as a pointer to the data in the
6497 * @type represents the type of the value
6498 * @buffer is the start of the buffer
6499 * @p the current position in the buffer
6500 * @buflen contains the size of the buffer and is used to return the new buffer size
6501 * if this needs to be realloced.
6502 * @retbuffer and @retp return the start and the position of the buffer
6505 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6507 MonoTypeEnum simple_type;
6509 if ((p-buffer) + 10 >= *buflen) {
6512 newbuf = g_realloc (buffer, *buflen);
6513 p = newbuf + (p-buffer);
6517 argval = ((char*)arg + sizeof (MonoObject));
6518 simple_type = type->type;
6520 switch (simple_type) {
6521 case MONO_TYPE_BOOLEAN:
6526 case MONO_TYPE_CHAR:
6529 swap_with_size (p, argval, 2, 1);
6535 swap_with_size (p, argval, 4, 1);
6541 swap_with_size (p, argval, 8, 1);
6544 case MONO_TYPE_VALUETYPE:
6545 if (type->data.klass->enumtype) {
6546 simple_type = type->data.klass->enum_basetype->type;
6549 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6552 case MONO_TYPE_STRING: {
6559 str = mono_string_to_utf8 ((MonoString*)arg);
6560 slen = strlen (str);
6561 if ((p-buffer) + 10 + slen >= *buflen) {
6565 newbuf = g_realloc (buffer, *buflen);
6566 p = newbuf + (p-buffer);
6569 mono_metadata_encode_value (slen, p, &p);
6570 memcpy (p, str, slen);
6575 case MONO_TYPE_CLASS: {
6583 k = mono_object_class (arg);
6584 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6585 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6586 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6588 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6589 slen = strlen (str);
6590 if ((p-buffer) + 10 + slen >= *buflen) {
6594 newbuf = g_realloc (buffer, *buflen);
6595 p = newbuf + (p-buffer);
6598 mono_metadata_encode_value (slen, p, &p);
6599 memcpy (p, str, slen);
6604 case MONO_TYPE_SZARRAY: {
6606 MonoClass *eclass, *arg_eclass;
6609 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6612 len = mono_array_length ((MonoArray*)arg);
6614 *p++ = (len >> 8) & 0xff;
6615 *p++ = (len >> 16) & 0xff;
6616 *p++ = (len >> 24) & 0xff;
6618 *retbuffer = buffer;
6619 eclass = type->data.klass;
6620 arg_eclass = mono_object_class (arg)->element_class;
6621 if (eclass->valuetype && arg_eclass->valuetype) {
6622 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6623 int elsize = mono_class_array_element_size (eclass);
6624 for (i = 0; i < len; ++i) {
6625 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6629 for (i = 0; i < len; ++i) {
6630 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6635 /* it may be a boxed value or a Type */
6636 case MONO_TYPE_OBJECT: {
6637 MonoClass *klass = mono_object_class (arg);
6641 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6644 } else if (klass->enumtype) {
6646 } else if (klass == mono_defaults.string_class) {
6647 simple_type = MONO_TYPE_STRING;
6650 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6651 *p++ = simple_type = klass->byval_arg.type;
6654 g_error ("unhandled type in custom attr");
6656 str = type_get_qualified_name (klass->enum_basetype, NULL);
6657 slen = strlen (str);
6658 if ((p-buffer) + 10 + slen >= *buflen) {
6662 newbuf = g_realloc (buffer, *buflen);
6663 p = newbuf + (p-buffer);
6666 mono_metadata_encode_value (slen, p, &p);
6667 memcpy (p, str, slen);
6670 simple_type = klass->enum_basetype->type;
6674 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6677 *retbuffer = buffer;
6681 * mono_reflection_get_custom_attrs_blob:
6682 * @ctor: custom attribute constructor
6683 * @ctorArgs: arguments o the constructor
6689 * Creates the blob of data that needs to be saved in the metadata and that represents
6690 * the custom attributed described by @ctor, @ctorArgs etc.
6691 * Returns: a Byte array representing the blob of data.
6694 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6697 MonoMethodSignature *sig;
6702 MONO_ARCH_SAVE_REGS;
6704 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6705 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6707 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6709 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6711 p = buffer = g_malloc (buflen);
6712 /* write the prolog */
6715 for (i = 0; i < sig->param_count; ++i) {
6716 arg = mono_array_get (ctorArgs, MonoObject*, i);
6717 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
6721 i += mono_array_length (properties);
6723 i += mono_array_length (fields);
6725 *p++ = (i >> 8) & 0xff;
6728 for (i = 0; i < mono_array_length (properties); ++i) {
6733 prop = mono_array_get (properties, gpointer, i);
6734 get_prop_name_and_type (prop, &pname, &ptype);
6735 *p++ = 0x54; /* PROPERTY signature */
6737 /* Preallocate a large enough buffer */
6738 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6739 char *str = type_get_qualified_name (ptype, NULL);
6745 len += strlen (pname);
6747 if ((p-buffer) + 20 + len >= buflen) {
6751 newbuf = g_realloc (buffer, buflen);
6752 p = newbuf + (p-buffer);
6756 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6757 char *str = type_get_qualified_name (ptype, NULL);
6758 int slen = strlen (str);
6762 * This seems to be optional...
6765 mono_metadata_encode_value (slen, p, &p);
6766 memcpy (p, str, slen);
6770 mono_metadata_encode_value (ptype->type, p, &p);
6771 if (ptype->type == MONO_TYPE_SZARRAY)
6772 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6774 len = strlen (pname);
6775 mono_metadata_encode_value (len, p, &p);
6776 memcpy (p, pname, len);
6778 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
6785 for (i = 0; i < mono_array_length (fields); ++i) {
6790 field = mono_array_get (fields, gpointer, i);
6791 get_field_name_and_type (field, &fname, &ftype);
6792 *p++ = 0x53; /* FIELD signature */
6793 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6794 char *str = type_get_qualified_name (ftype, NULL);
6795 int slen = strlen (str);
6796 if ((p-buffer) + 10 + slen >= buflen) {
6800 newbuf = g_realloc (buffer, buflen);
6801 p = newbuf + (p-buffer);
6806 * This seems to be optional...
6809 mono_metadata_encode_value (slen, p, &p);
6810 memcpy (p, str, slen);
6814 mono_metadata_encode_value (ftype->type, p, &p);
6815 if (ftype->type == MONO_TYPE_SZARRAY)
6816 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
6818 len = strlen (fname);
6819 mono_metadata_encode_value (len, p, &p);
6820 memcpy (p, fname, len);
6822 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
6827 g_assert (p - buffer <= buflen);
6828 buflen = p - buffer;
6829 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6830 p = mono_array_addr (result, char, 0);
6831 memcpy (p, buffer, buflen);
6833 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6839 * mono_reflection_setup_internal_class:
6840 * @tb: a TypeBuilder object
6842 * Creates a MonoClass that represents the TypeBuilder.
6843 * This is a trick that lets us simplify a lot of reflection code
6844 * (and will allow us to support Build and Run assemblies easier).
6847 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6849 MonoClass *klass, *parent;
6851 MONO_ARCH_SAVE_REGS;
6854 /* check so we can compile corlib correctly */
6855 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6856 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6857 parent = tb->parent->type->data.klass;
6859 parent = my_mono_class_from_mono_type (tb->parent->type);
6863 /* the type has already being created: it means we just have to change the parent */
6864 if (tb->type.type) {
6865 klass = mono_class_from_mono_type (tb->type.type);
6866 klass->parent = NULL;
6867 /* fool mono_class_setup_parent */
6868 g_free (klass->supertypes);
6869 klass->supertypes = NULL;
6870 mono_class_setup_parent (klass, parent);
6871 mono_class_setup_mono_type (klass);
6875 klass = g_new0 (MonoClass, 1);
6877 klass->image = &tb->module->dynamic_image->image;
6879 klass->inited = 1; /* we lie to the runtime */
6880 klass->name = mono_string_to_utf8 (tb->name);
6881 klass->name_space = mono_string_to_utf8 (tb->nspace);
6882 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6883 klass->flags = tb->attrs;
6885 klass->element_class = klass;
6886 klass->reflection_info = tb; /* need to pin. */
6888 /* Put into cache so mono_class_get () will find it */
6889 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6892 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6893 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6897 mono_class_setup_parent (klass, parent);
6898 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6899 const char *old_n = klass->name;
6900 /* trick to get relative numbering right when compiling corlib */
6901 klass->name = "BuildingObject";
6902 mono_class_setup_parent (klass, mono_defaults.object_class);
6903 klass->name = old_n;
6905 mono_class_setup_mono_type (klass);
6907 mono_class_setup_supertypes (klass);
6910 * FIXME: handle interfaces.
6913 tb->type.type = &klass->byval_arg;
6915 if (tb->nesting_type) {
6916 g_assert (tb->nesting_type->type);
6917 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6920 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6924 * mono_reflection_setup_generic_class:
6925 * @tb: a TypeBuilder object
6927 * Setup the generic class after all generic parameters have been added.
6930 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6935 MONO_ARCH_SAVE_REGS;
6937 klass = my_mono_class_from_mono_type (tb->type.type);
6939 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6941 if (klass->gen_params || (count == 0))
6944 klass->num_gen_params = count;
6945 klass->gen_params = g_new0 (MonoGenericParam, count);
6947 for (i = 0; i < count; i++) {
6948 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6949 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6954 * mono_reflection_create_internal_class:
6955 * @tb: a TypeBuilder object
6957 * Actually create the MonoClass that is associated with the TypeBuilder.
6960 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6964 MONO_ARCH_SAVE_REGS;
6966 klass = my_mono_class_from_mono_type (tb->type.type);
6968 if (klass->enumtype && klass->enum_basetype == NULL) {
6969 MonoReflectionFieldBuilder *fb;
6971 g_assert (tb->fields != NULL);
6972 g_assert (mono_array_length (tb->fields) >= 1);
6974 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6976 klass->enum_basetype = fb->type->type;
6977 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6978 if (!klass->element_class)
6979 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6980 klass->instance_size = klass->element_class->instance_size;
6981 klass->size_inited = 1;
6983 * this is almost safe to do with enums and it's needed to be able
6984 * to create objects of the enum type (for use in SetConstant).
6986 /* FIXME: Does this mean enums can't have method overrides ? */
6987 mono_class_setup_vtable (klass, NULL, 0);
6991 static MonoMarshalSpec*
6992 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6993 MonoReflectionMarshal *minfo)
6995 MonoMarshalSpec *res;
6997 res = g_new0 (MonoMarshalSpec, 1);
6998 res->native = minfo->type;
7000 switch (minfo->type) {
7001 case MONO_NATIVE_LPARRAY:
7002 res->data.array_data.elem_type = minfo->eltype;
7003 res->data.array_data.param_num = 0; /* Not yet */
7004 res->data.array_data.num_elem = minfo->count;
7007 case MONO_NATIVE_BYVALTSTR:
7008 case MONO_NATIVE_BYVALARRAY:
7009 res->data.array_data.num_elem = minfo->count;
7012 case MONO_NATIVE_CUSTOM:
7013 if (minfo->marshaltyperef)
7014 res->data.custom_data.custom_name =
7015 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7017 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7028 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7029 ReflectionMethodBuilder *rmb,
7030 MonoMethodSignature *sig)
7033 MonoMethodNormal *pm;
7034 MonoMarshalSpec **specs;
7035 MonoReflectionMethodAux *method_aux;
7038 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7039 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7040 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7043 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7045 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7047 pm = (MonoMethodNormal*)m;
7050 m->flags = rmb->attrs;
7051 m->iflags = rmb->iattrs;
7052 m->name = mono_string_to_utf8 (rmb->name);
7056 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7058 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7059 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7062 m->signature->pinvoke = 1;
7063 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7065 m->signature->pinvoke = 1;
7067 } else if (!m->klass->dummy &&
7068 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7069 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7070 MonoMethodHeader *header;
7072 gint32 max_stack, i;
7073 gint32 num_locals = 0;
7074 gint32 num_clauses = 0;
7078 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7079 code_size = rmb->ilgen->code_len;
7080 max_stack = rmb->ilgen->max_stack;
7081 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7082 if (rmb->ilgen->ex_handlers)
7083 num_clauses = method_count_clauses (rmb->ilgen);
7086 code = mono_array_addr (rmb->code, guint8, 0);
7087 code_size = mono_array_length (rmb->code);
7088 /* we probably need to run a verifier on the code... */
7098 header = g_malloc0 (sizeof (MonoMethodHeader) +
7099 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7100 header->code_size = code_size;
7101 header->code = g_malloc (code_size);
7102 memcpy ((char*)header->code, code, code_size);
7103 header->max_stack = max_stack;
7104 header->init_locals = rmb->init_locals;
7105 header->num_locals = num_locals;
7107 for (i = 0; i < num_locals; ++i) {
7108 MonoReflectionLocalBuilder *lb =
7109 mono_array_get (rmb->ilgen->locals,
7110 MonoReflectionLocalBuilder*, i);
7112 header->locals [i] = g_new0 (MonoType, 1);
7113 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7116 header->num_clauses = num_clauses;
7118 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7123 pm->header = header;
7126 if (rmb->generic_params) {
7127 int count = mono_array_length (rmb->generic_params);
7128 pm->gen_params = g_new0 (MonoGenericParam, count);
7129 for (i = 0; i < count; i++) {
7130 MonoReflectionGenericParam *gp =
7131 mono_array_get (rmb->generic_params,
7132 MonoReflectionGenericParam*, i);
7134 pm->gen_params [i] = *gp->type.type->data.generic_param;
7139 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7142 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7144 for (i = 0; i < rmb->nrefs; ++i)
7145 mw->data = g_list_append (mw->data, rmb->refs [i]);
7150 /* Parameter names */
7153 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7154 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7155 for (i = 0; i <= m->signature->param_count; ++i) {
7156 MonoReflectionParamBuilder *pb;
7157 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7159 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7161 if (!method_aux->param_cattr)
7162 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7163 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7169 /* Parameter marshalling */
7172 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7173 MonoReflectionParamBuilder *pb;
7174 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7175 if (pb->marshal_info) {
7177 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7178 specs [pb->position] =
7179 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7183 if (specs != NULL) {
7185 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7186 method_aux->param_marshall = specs;
7189 if (klass->image->dynamic && method_aux)
7190 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7196 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7198 ReflectionMethodBuilder rmb;
7199 MonoMethodSignature *sig;
7201 sig = ctor_builder_to_signature (mb);
7203 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7205 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7206 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7208 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7209 /* ilgen is no longer needed */
7217 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7219 ReflectionMethodBuilder rmb;
7220 MonoMethodSignature *sig;
7222 sig = method_builder_to_signature (mb);
7224 reflection_methodbuilder_from_method_builder (&rmb, mb);
7226 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7227 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7229 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7230 /* ilgen is no longer needed */
7236 static MonoClassField*
7237 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7239 MonoClassField *field;
7246 field = g_new0 (MonoClassField, 1);
7248 field->name = mono_string_to_utf8 (fb->name);
7250 /* FIXME: handle type modifiers */
7251 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7252 field->type->attrs = fb->attrs;
7254 field->type = fb->type->type;
7256 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7257 field->data = mono_array_addr (fb->rva_data, char, 0);
7258 if (fb->offset != -1)
7259 field->offset = fb->offset;
7260 field->parent = klass;
7262 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7264 if (fb->def_value) {
7265 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7266 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7267 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7268 /* Copy the data from the blob since it might get realloc-ed */
7269 p = assembly->blob.data + idx;
7270 len = mono_metadata_decode_blob_size (p, &p2);
7272 field->data = g_malloc (len);
7273 memcpy (field->data, p, len);
7280 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7284 MonoReflectionTypeBuilder *tb = NULL;
7285 MonoGenericInst *ginst, *cached;
7290 klass = mono_class_from_mono_type (type->type);
7291 if (!klass->gen_params && !klass->generic_inst &&
7292 !(klass->nested_in && klass->nested_in->gen_params))
7295 mono_loader_lock ();
7297 domain = mono_object_domain (type);
7299 ginst = g_new0 (MonoGenericInst, 1);
7301 if (!klass->generic_inst) {
7302 ginst->type_argc = type_argc;
7303 ginst->type_argv = types;
7305 for (i = 0; i < ginst->type_argc; ++i) {
7306 if (!ginst->is_open)
7307 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7310 ginst->generic_type = &klass->byval_arg;
7312 MonoGenericInst *kginst = klass->generic_inst;
7314 ginst->type_argc = kginst->type_argc;
7315 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7317 for (i = 0; i < ginst->type_argc; i++) {
7318 MonoType *t = kginst->type_argv [i];
7320 if (t->type == MONO_TYPE_VAR)
7321 t = types [t->data.generic_param->num];
7323 if (!ginst->is_open)
7324 ginst->is_open = mono_class_is_open_constructed_type (t);
7326 ginst->type_argv [i] = t;
7329 ginst->generic_type = kginst->generic_type;
7332 geninst = g_new0 (MonoType, 1);
7333 geninst->type = MONO_TYPE_GENERICINST;
7335 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7338 mono_loader_unlock ();
7339 geninst->data.generic_inst = cached;
7343 geninst->data.generic_inst = ginst;
7345 ginst->context = g_new0 (MonoGenericContext, 1);
7346 ginst->context->ginst = ginst;
7348 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7349 tb = (MonoReflectionTypeBuilder *) type;
7351 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7352 ginst->is_dynamic = TRUE;
7353 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7354 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7355 MonoReflectionType *rgt = rgi->generic_type;
7357 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7358 tb = (MonoReflectionTypeBuilder *) rgt;
7360 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7361 ginst->is_dynamic = TRUE;
7363 icount = klass->interface_count;
7365 ginst->ifaces = g_new0 (MonoType *, icount);
7366 ginst->count_ifaces = icount;
7368 for (i = 0; i < icount; i++) {
7369 MonoReflectionType *itype;
7372 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7374 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7375 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7376 if (!ginst->ifaces [i])
7377 ginst->ifaces [i] = itype->type;
7380 mono_class_create_generic (ginst);
7382 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7384 mono_loader_unlock ();
7390 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7392 MonoClass *klass, *pklass = NULL;
7393 MonoReflectionType *parent = NULL;
7395 MonoReflectionTypeBuilder *tb = NULL;
7396 MonoGenericInst *ginst;
7399 domain = mono_object_domain (type);
7400 klass = mono_class_from_mono_type (type->type);
7402 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7403 tb = (MonoReflectionTypeBuilder *) type;
7406 parent = tb->parent;
7407 pklass = mono_class_from_mono_type (parent->type);
7410 pklass = klass->parent;
7412 parent = mono_type_get_object (domain, &pklass->byval_arg);
7415 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7419 ginst = geninst->data.generic_inst;
7421 if (pklass && pklass->generic_inst)
7422 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7427 MonoReflectionMethod*
7428 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7430 MonoMethod *method, *inflated;
7431 MonoReflectionMethodBuilder *mb = NULL;
7432 MonoGenericMethod *gmethod;
7433 MonoGenericContext *context;
7436 MONO_ARCH_SAVE_REGS;
7437 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7438 MonoReflectionTypeBuilder *tb;
7441 mb = (MonoReflectionMethodBuilder *) rmethod;
7442 tb = (MonoReflectionTypeBuilder *) mb->type;
7443 klass = mono_class_from_mono_type (tb->type.type);
7445 method = methodbuilder_to_mono_method (klass, mb);
7447 method = rmethod->method;
7449 count = method->signature->generic_param_count;
7450 if (count != mono_array_length (types))
7453 gmethod = g_new0 (MonoGenericMethod, 1);
7454 gmethod->mtype_argc = count;
7455 gmethod->mtype_argv = g_new0 (MonoType *, count);
7456 for (i = 0; i < count; i++) {
7457 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7458 gmethod->mtype_argv [i] = garg->type;
7461 gmethod->reflection_info = rmethod;
7463 context = g_new0 (MonoGenericContext, 1);
7464 context->ginst = method->klass->generic_inst;
7465 context->gmethod = gmethod;
7467 inflated = mono_class_inflate_generic_method (method, context, NULL);
7469 return mono_method_get_object (
7470 mono_object_domain (rmethod), inflated, NULL);
7474 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7476 MonoGenericMethod *gmethod;
7477 MonoGenericInst *ginst;
7478 MonoGenericContext *context;
7481 ginst = type->type.type->data.generic_inst;
7483 gmethod = g_new0 (MonoGenericMethod, 1);
7484 gmethod->reflection_info = obj;
7486 gmethod->mtype_argc = method->signature->generic_param_count;
7487 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7489 for (i = 0; i < gmethod->mtype_argc; i++) {
7490 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7491 MonoGenericParam *gparam = &mn->gen_params [i];
7493 g_assert (gparam->pklass);
7494 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7497 context = g_new0 (MonoGenericContext, 1);
7498 context->ginst = ginst;
7499 context->gmethod = gmethod;
7501 return mono_class_inflate_generic_method (method, context, ginst->klass);
7505 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7510 klass = mono_class_from_mono_type (type->type.type);
7512 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7513 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7514 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7515 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7516 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7517 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7518 method = ((MonoReflectionMethod *) obj)->method;
7520 method = NULL; /* prevent compiler warning */
7521 g_assert_not_reached ();
7524 return inflate_mono_method (type, method, obj);
7528 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7529 MonoArray *methods, MonoArray *ctors,
7530 MonoArray *fields, MonoArray *properties,
7533 MonoGenericInst *ginst;
7534 MonoDynamicGenericInst *dginst;
7535 MonoClass *klass, *gklass, *pklass;
7538 MONO_ARCH_SAVE_REGS;
7540 klass = mono_class_from_mono_type (type->type.type);
7541 ginst = type->type.type->data.generic_inst;
7543 if (ginst->initialized)
7546 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7548 gklass = mono_class_from_mono_type (ginst->generic_type);
7549 mono_class_init (gklass);
7552 pklass = mono_class_from_mono_type (ginst->parent);
7554 pklass = gklass->parent;
7556 mono_class_setup_parent (klass, pklass);
7558 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7559 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7560 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7561 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7562 dginst->count_events = events ? mono_array_length (events) : 0;
7564 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7565 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7566 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7567 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7568 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7570 for (i = 0; i < dginst->count_methods; i++) {
7571 MonoObject *obj = mono_array_get (methods, gpointer, i);
7573 dginst->methods [i] = inflate_method (type, obj);
7576 for (i = 0; i < dginst->count_ctors; i++) {
7577 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7579 dginst->ctors [i] = inflate_method (type, obj);
7582 for (i = 0; i < dginst->count_fields; i++) {
7583 MonoObject *obj = mono_array_get (fields, gpointer, i);
7584 MonoClassField *field;
7585 MonoInflatedField *ifield;
7587 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7588 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7589 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7590 field = ((MonoReflectionField *) obj)->field;
7592 field = NULL; /* prevent compiler warning */
7593 g_assert_not_reached ();
7596 ifield = g_new0 (MonoInflatedField, 1);
7597 ifield->generic_type = field->type;
7598 ifield->reflection_info = obj;
7600 dginst->fields [i] = *field;
7601 dginst->fields [i].generic_info = ifield;
7602 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7605 for (i = 0; i < dginst->count_properties; i++) {
7606 MonoObject *obj = mono_array_get (properties, gpointer, i);
7607 MonoProperty *property = &dginst->properties [i];
7609 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7610 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7612 property->parent = klass;
7613 property->attrs = pb->attrs;
7614 property->name = mono_string_to_utf8 (pb->name);
7616 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7618 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7619 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7620 *property = *((MonoReflectionProperty *) obj)->property;
7623 property->get = inflate_mono_method (type, property->get, NULL);
7625 property->set = inflate_mono_method (type, property->set, NULL);
7627 g_assert_not_reached ();
7630 for (i = 0; i < dginst->count_events; i++) {
7631 MonoObject *obj = mono_array_get (events, gpointer, i);
7632 MonoEvent *event = &dginst->events [i];
7634 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7635 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7637 event->parent = klass;
7638 event->attrs = eb->attrs;
7639 event->name = mono_string_to_utf8 (eb->name);
7641 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7642 if (eb->remove_method)
7643 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7644 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7645 *event = *((MonoReflectionEvent *) obj)->event;
7648 event->add = inflate_mono_method (type, event->add, NULL);
7650 event->remove = inflate_mono_method (type, event->remove, NULL);
7652 g_assert_not_reached ();
7655 ginst->initialized = TRUE;
7659 ensure_runtime_vtable (MonoClass *klass)
7661 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7662 int i, num, j, onum;
7663 MonoMethod **overrides;
7665 if (!tb || klass->wastypebuilder)
7668 ensure_runtime_vtable (klass->parent);
7670 num = tb->ctors? mono_array_length (tb->ctors): 0;
7671 num += tb->num_methods;
7672 klass->method.count = num;
7673 klass->methods = g_new (MonoMethod*, num);
7674 num = tb->ctors? mono_array_length (tb->ctors): 0;
7675 for (i = 0; i < num; ++i)
7676 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7677 num = tb->num_methods;
7679 for (i = 0; i < num; ++i)
7680 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7682 klass->wastypebuilder = TRUE;
7683 if (tb->interfaces) {
7684 klass->interface_count = mono_array_length (tb->interfaces);
7685 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7686 for (i = 0; i < klass->interface_count; ++i) {
7687 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7688 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7692 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7693 for (i = 0; i < klass->method.count; ++i)
7694 klass->methods [i]->slot = i;
7699 for (i = 0; i < tb->num_methods; ++i) {
7700 MonoReflectionMethodBuilder *mb =
7701 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7702 if (mb->override_method)
7707 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7711 for (i = 0; i < tb->num_methods; ++i) {
7712 MonoReflectionMethodBuilder *mb =
7713 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7714 if (mb->override_method) {
7715 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7716 overrides [onum * 2] =
7717 mb->override_method->method;
7718 overrides [onum * 2 + 1] =
7721 g_assert (mb->mhandle);
7728 mono_class_setup_vtable (klass, overrides, onum);
7732 typebuilder_setup_fields (MonoClass *klass)
7734 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7735 MonoReflectionFieldBuilder *fb;
7736 MonoClassField *field;
7741 klass->field.count = tb->num_fields;
7742 klass->field.first = 0;
7743 klass->field.last = klass->field.count;
7745 if (!klass->field.count)
7748 klass->fields = g_new0 (MonoClassField, klass->field.count);
7750 for (i = 0; i < klass->field.count; ++i) {
7751 fb = mono_array_get (tb->fields, gpointer, i);
7752 field = &klass->fields [i];
7753 field->name = mono_string_to_utf8 (fb->name);
7755 /* FIXME: handle type modifiers */
7756 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7757 field->type->attrs = fb->attrs;
7759 field->type = fb->type->type;
7761 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7762 field->data = mono_array_addr (fb->rva_data, char, 0);
7763 if (fb->offset != -1)
7764 field->offset = fb->offset;
7765 field->parent = klass;
7767 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7769 if (fb->def_value) {
7770 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7771 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7772 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7773 /* Copy the data from the blob since it might get realloc-ed */
7774 p = assembly->blob.data + idx;
7775 len = mono_metadata_decode_blob_size (p, &p2);
7777 field->data = g_malloc (len);
7778 memcpy (field->data, p, len);
7781 mono_class_layout_fields (klass);
7785 typebuilder_setup_properties (MonoClass *klass)
7787 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7788 MonoReflectionPropertyBuilder *pb;
7791 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7792 klass->property.first = 0;
7793 klass->property.last = klass->property.count;
7795 klass->properties = g_new0 (MonoProperty, klass->property.count);
7796 for (i = 0; i < klass->property.count; ++i) {
7797 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7798 klass->properties [i].parent = klass;
7799 klass->properties [i].attrs = pb->attrs;
7800 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7802 klass->properties [i].get = pb->get_method->mhandle;
7804 klass->properties [i].set = pb->set_method->mhandle;
7808 MonoReflectionEvent *
7809 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7811 MonoEvent *event = g_new0 (MonoEvent, 1);
7815 klass = my_mono_class_from_mono_type (tb->type.type);
7817 event->parent = klass;
7818 event->attrs = eb->attrs;
7819 event->name = mono_string_to_utf8 (eb->name);
7821 event->add = eb->add_method->mhandle;
7822 if (eb->remove_method)
7823 event->remove = eb->remove_method->mhandle;
7824 if (eb->raise_method)
7825 event->raise = eb->raise_method->mhandle;
7827 if (eb->other_methods) {
7828 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7829 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7830 MonoReflectionMethodBuilder *mb =
7831 mono_array_get (eb->other_methods,
7832 MonoReflectionMethodBuilder*, j);
7833 event->other [j] = mb->mhandle;
7837 return mono_event_get_object (mono_object_domain (tb), klass, event);
7841 typebuilder_setup_events (MonoClass *klass)
7843 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7844 MonoReflectionEventBuilder *eb;
7847 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7848 klass->event.first = 0;
7849 klass->event.last = klass->event.count;
7851 klass->events = g_new0 (MonoEvent, klass->event.count);
7852 for (i = 0; i < klass->event.count; ++i) {
7853 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7854 klass->events [i].parent = klass;
7855 klass->events [i].attrs = eb->attrs;
7856 klass->events [i].name = mono_string_to_utf8 (eb->name);
7858 klass->events [i].add = eb->add_method->mhandle;
7859 if (eb->remove_method)
7860 klass->events [i].remove = eb->remove_method->mhandle;
7861 if (eb->raise_method)
7862 klass->events [i].raise = eb->raise_method->mhandle;
7864 if (eb->other_methods) {
7865 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7866 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7867 MonoReflectionMethodBuilder *mb =
7868 mono_array_get (eb->other_methods,
7869 MonoReflectionMethodBuilder*, j);
7870 klass->events [i].other [j] = mb->mhandle;
7877 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7880 MonoReflectionType* res;
7882 MONO_ARCH_SAVE_REGS;
7884 klass = my_mono_class_from_mono_type (tb->type.type);
7886 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7889 * Fields to set in klass:
7890 * the various flags: delegate/unicode/contextbound etc.
7893 klass->flags = tb->attrs;
7895 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7896 /* No need to fully construct the type */
7897 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7899 /* enums are done right away */
7900 if (!klass->enumtype)
7901 ensure_runtime_vtable (klass);
7903 /* fields and object layout */
7904 if (klass->parent) {
7905 if (!klass->parent->size_inited)
7906 mono_class_init (klass->parent);
7907 klass->instance_size += klass->parent->instance_size;
7908 klass->class_size += klass->parent->class_size;
7909 klass->min_align = klass->parent->min_align;
7911 klass->instance_size = sizeof (MonoObject);
7912 klass->min_align = 1;
7915 /* FIXME: handle packing_size and instance_size */
7916 typebuilder_setup_fields (klass);
7918 typebuilder_setup_properties (klass);
7920 typebuilder_setup_events (klass);
7922 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7923 /* with enums res == tb: need to fix that. */
7924 if (!klass->enumtype)
7925 g_assert (res != (MonoReflectionType*)tb);
7930 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7932 MonoGenericParam *param;
7935 MONO_ARCH_SAVE_REGS;
7937 param = g_new0 (MonoGenericParam, 1);
7939 param->method = NULL;
7940 param->name = mono_string_to_utf8 (gparam->name);
7941 param->num = gparam->index;
7943 image = &gparam->tbuilder->module->dynamic_image->image;
7944 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7946 param->pklass->reflection_info = gparam;
7948 gparam->type.type = g_new0 (MonoType, 1);
7949 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7950 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7951 gparam->type.type->data.generic_param = param;
7955 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7957 MonoDynamicImage *assembly = sig->module->dynamic_image;
7958 guint32 na = mono_array_length (sig->arguments);
7963 MONO_ARCH_SAVE_REGS;
7965 p = buf = g_malloc (10 + na * 10);
7967 mono_metadata_encode_value (0x07, p, &p);
7968 mono_metadata_encode_value (na, p, &p);
7969 for (i = 0; i < na; ++i) {
7970 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7971 encode_reflection_type (assembly, type, p, &p);
7975 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7976 p = mono_array_addr (result, char, 0);
7977 memcpy (p, buf, buflen);
7984 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7986 MonoDynamicImage *assembly = sig->module->dynamic_image;
7987 guint32 na = mono_array_length (sig->arguments);
7992 MONO_ARCH_SAVE_REGS;
7994 p = buf = g_malloc (10 + na * 10);
7996 mono_metadata_encode_value (0x06, p, &p);
7997 for (i = 0; i < na; ++i) {
7998 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7999 encode_reflection_type (assembly, type, p, &p);
8003 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8004 p = mono_array_addr (result, char, 0);
8005 memcpy (p, buf, buflen);
8012 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8014 ReflectionMethodBuilder rmb;
8015 MonoMethodSignature *sig;
8018 sig = dynamic_method_to_signature (mb);
8020 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8023 * Resolve references.
8025 rmb.nrefs = mb->nrefs;
8026 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8027 for (i = 0; i < mb->nrefs; ++i) {
8028 gpointer ref = resolve_object (mb->module->image,
8029 mono_array_get (mb->refs, MonoObject*, i));
8032 mono_raise_exception (mono_get_exception_type_load (NULL));
8039 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8043 /* ilgen is no longer needed */
8048 * mono_reflection_lookup_dynamic_token:
8050 * Finish the Builder object pointed to by TOKEN and return the corresponding
8051 * runtime structure.
8054 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8056 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8059 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8062 return resolve_object (image, obj);
8066 resolve_object (MonoImage *image, MonoObject *obj)
8068 gpointer result = NULL;
8070 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8071 result = mono_string_intern ((MonoString*)obj);
8074 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8075 MonoReflectionType *tb = (MonoReflectionType*)obj;
8076 result = mono_class_from_mono_type (tb->type);
8079 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8080 result = ((MonoReflectionMethod*)obj)->method;
8083 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8084 result = ((MonoReflectionMethod*)obj)->method;
8087 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8088 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8089 result = mb->mhandle;
8091 /* Type is not yet created */
8092 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8094 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8097 * Hopefully this has been filled in by calling CreateType() on the
8101 * TODO: This won't work if the application finishes another
8102 * TypeBuilder instance instead of this one.
8104 result = mb->mhandle;
8107 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8108 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8110 result = cb->mhandle;
8112 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8114 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8115 result = cb->mhandle;
8118 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8119 result = ((MonoReflectionField*)obj)->field;
8122 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8123 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8124 result = fb->handle;
8127 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8129 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8130 result = fb->handle;
8133 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8134 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8137 klass = tb->type.type->data.klass;
8138 if (klass->wastypebuilder) {
8139 /* Already created */
8143 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8144 result = tb->type.type->data.klass;
8148 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8149 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8150 MonoMethodSignature *sig;
8153 if (helper->arguments)
8154 nargs = mono_array_length (helper->arguments);
8158 sig = mono_metadata_signature_alloc (image, nargs);
8159 sig->explicit_this = helper->call_conv & 64;
8160 sig->hasthis = helper->call_conv & 32;
8162 if (helper->call_conv == 0) /* unmanaged */
8163 sig->call_convention = helper->unmanaged_call_conv - 1;
8165 if (helper->call_conv & 0x02)
8166 sig->call_convention = MONO_CALL_VARARG;
8168 sig->call_convention = MONO_CALL_DEFAULT;
8170 sig->param_count = nargs;
8171 /* TODO: Copy type ? */
8172 sig->ret = helper->return_type->type;
8173 for (i = 0; i < nargs; ++i) {
8174 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8175 sig->params [i] = rt->type;
8181 g_print (obj->vtable->klass->name);
8182 g_assert_not_reached ();