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