3 * reflection.c: Routines for creating an image at runtime.
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
12 #include "mono/utils/mono-digest.h"
13 #include "mono/metadata/reflection.h"
14 #include "mono/metadata/tabledefs.h"
15 #include "mono/metadata/tokentype.h"
16 #include "mono/metadata/appdomain.h"
17 #include "mono/metadata/opcodes.h"
18 #include "mono/metadata/assembly.h"
19 #include <mono/metadata/exception.h>
28 #include "rawbuffer.h"
29 #include "mono-endian.h"
31 #include <mono/os/gc_wrapper.h>
33 #define TEXT_OFFSET 512
34 #define CLI_H_SIZE 136
35 #define FILE_ALIGN 512
36 #define VIRT_ALIGN 8192
37 #define START_TEXT_RVA 0x00002000
40 MonoReflectionILGen *ilgen;
41 MonoReflectionType *rtype;
42 MonoArray *parameters;
43 MonoArray *generic_params;
48 guint32 *table_idx; /* note: it's a pointer */
52 MonoBoolean init_locals;
54 } ReflectionMethodBuilder;
56 const unsigned char table_sizes [64] = {
66 MONO_INTERFACEIMPL_SIZE,
67 MONO_MEMBERREF_SIZE, /* 0x0A */
69 MONO_CUSTOM_ATTR_SIZE,
70 MONO_FIELD_MARSHAL_SIZE,
71 MONO_DECL_SECURITY_SIZE,
72 MONO_CLASS_LAYOUT_SIZE,
73 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
74 MONO_STAND_ALONE_SIGNATURE_SIZE,
78 MONO_PROPERTY_MAP_SIZE,
81 MONO_METHOD_SEMA_SIZE,
83 MONO_MODULEREF_SIZE, /* 0x1A */
89 MONO_ASSEMBLY_SIZE, /* 0x20 */
90 MONO_ASSEMBLY_PROCESSOR_SIZE,
92 MONO_ASSEMBLYREF_SIZE,
93 MONO_ASSEMBLYREFPROC_SIZE,
94 MONO_ASSEMBLYREFOS_SIZE,
98 MONO_NESTED_CLASS_SIZE,
100 MONO_GENERICPARAM_SIZE, /* 0x2A */
101 MONO_METHODSPEC_SIZE,
102 MONO_GENPARCONSTRAINT_SIZE,
108 * These macros can be used to allocate long living atomic data so it won't be
109 * tracked by the garbage collector. We use libgc because it's apparently faster
113 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
114 #define FREE_ATOMIC(ptr)
115 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
117 #define ALLOC_ATOMIC(size) g_malloc (size)
118 #define FREE_ATOMIC(ptr) g_free (ptr)
119 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
122 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
123 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
124 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
125 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
126 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
127 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
128 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
129 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
130 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
131 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
132 static void ensure_runtime_vtable (MonoClass *klass);
135 alloc_table (MonoDynamicTable *table, guint nrows)
138 g_assert (table->columns);
139 if (nrows + 1 >= table->alloc_rows) {
140 while (nrows + 1 >= table->alloc_rows)
141 if (table->alloc_rows == 0)
142 table->alloc_rows = 16;
144 table->alloc_rows *= 2;
147 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
149 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
154 make_room_in_stream (MonoDynamicStream *stream, int size)
156 while (stream->alloc_size <= size) {
157 if (stream->alloc_size < 4096)
158 stream->alloc_size = 4096;
160 stream->alloc_size *= 2;
163 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
165 stream->data = ALLOC_ATOMIC (stream->alloc_size);
169 string_heap_insert (MonoDynamicStream *sh, const char *str)
173 gpointer oldkey, oldval;
175 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
176 return GPOINTER_TO_UINT (oldval);
178 len = strlen (str) + 1;
180 if (idx + len > sh->alloc_size)
181 make_room_in_stream (sh, idx + len);
184 * We strdup the string even if we already copy them in sh->data
185 * so that the string pointers in the hash remain valid even if
186 * we need to realloc sh->data. We may want to avoid that later.
188 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
189 memcpy (sh->data + idx, str, len);
195 string_heap_init (MonoDynamicStream *sh)
198 sh->alloc_size = 4096;
199 sh->data = ALLOC_ATOMIC (4096);
200 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
201 string_heap_insert (sh, "");
204 #if 0 /* never used */
206 string_heap_free (MonoDynamicStream *sh)
208 FREE_ATOMIC (sh->data);
209 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
210 g_hash_table_destroy (sh->hash);
215 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
218 if (stream->alloc_size < stream->index + len)
219 make_room_in_stream (stream, stream->index + len);
220 memcpy (stream->data + stream->index, data, len);
222 stream->index += len;
224 * align index? Not without adding an additional param that controls it since
225 * we may store a blob value in pieces.
231 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
234 if (stream->alloc_size < stream->index + len)
235 make_room_in_stream (stream, stream->index + len);
236 memset (stream->data + stream->index, 0, len);
238 stream->index += len;
243 stream_data_align (MonoDynamicStream *stream)
246 guint32 count = stream->index % 4;
248 /* we assume the stream data will be aligned */
250 mono_image_add_stream_data (stream, buf, 4 - count);
254 mono_blob_entry_hash (const char* str)
258 len = mono_metadata_decode_blob_size (str, &str);
262 for (str += 1; str < end; str++)
263 h = (h << 5) - h + *str;
271 mono_blob_entry_equal (const char *str1, const char *str2) {
275 len = mono_metadata_decode_blob_size (str1, &end1);
276 len2 = mono_metadata_decode_blob_size (str2, &end2);
279 return memcmp (end1, end2, len) == 0;
283 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
287 gpointer oldkey, oldval;
289 copy = ALLOC_ATOMIC (s1+s2);
290 memcpy (copy, b1, s1);
291 memcpy (copy + s1, b2, s2);
292 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
294 idx = GPOINTER_TO_UINT (oldval);
296 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
297 mono_image_add_stream_data (&assembly->blob, b2, s2);
298 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
303 /* modified version needed to handle building corlib */
305 my_mono_class_from_mono_type (MonoType *type) {
306 switch (type->type) {
307 case MONO_TYPE_ARRAY:
309 case MONO_TYPE_SZARRAY:
310 case MONO_TYPE_GENERICINST:
311 return mono_class_from_mono_type (type);
314 g_assert (type->data.generic_param->pklass);
315 return type->data.generic_param->pklass;
317 /* should be always valid when we reach this case... */
318 return type->data.klass;
323 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
326 g_assert_not_reached ();
331 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
335 case MONO_TYPE_BOOLEAN:
349 case MONO_TYPE_STRING:
350 case MONO_TYPE_OBJECT:
351 case MONO_TYPE_TYPEDBYREF:
352 mono_metadata_encode_value (type->type, p, &p);
355 mono_metadata_encode_value (type->type, p, &p);
356 encode_type (assembly, type->data.type, p, &p);
358 case MONO_TYPE_SZARRAY:
359 mono_metadata_encode_value (type->type, p, &p);
360 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
363 case MONO_TYPE_VALUETYPE:
364 case MONO_TYPE_CLASS: {
365 MonoClass *k = mono_class_from_mono_type (type);
366 mono_metadata_encode_value (type->type, p, &p);
368 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
369 * otherwise two typerefs could point to the same type, leading to
370 * verification errors.
372 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
376 case MONO_TYPE_ARRAY:
377 mono_metadata_encode_value (type->type, p, &p);
378 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
379 mono_metadata_encode_value (type->data.array->rank, p, &p);
380 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
381 mono_metadata_encode_value (0, p, &p);
383 case MONO_TYPE_GENERICINST: {
385 mono_metadata_encode_value (type->type, p, &p);
386 encode_type (assembly, type->data.generic_inst->generic_type, p, &p);
387 mono_metadata_encode_value (type->data.generic_inst->type_argc, p, &p);
388 for (i = 0; i < type->data.generic_inst->type_argc; ++i) {
389 encode_type (assembly, type->data.generic_inst->type_argv [i], p, &p);
395 mono_metadata_encode_value (type->type, p, &p);
396 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
400 g_error ("need to encode type %x", type->type);
406 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
409 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
413 encode_type (assembly, type->type, p, endbuf);
417 g_assert_not_reached ();
422 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
427 guint32 nparams = sig->param_count;
428 guint32 size = 10 + nparams * 10;
436 p = buf = g_malloc (size);
438 * FIXME: vararg, explicit_this, differenc call_conv values...
440 *p = sig->call_convention;
442 *p |= 0x20; /* hasthis */
443 if (sig->generic_param_count)
444 *p |= 0x10; /* generic */
446 if (sig->generic_param_count)
447 mono_metadata_encode_value (sig->generic_param_count, p, &p);
448 mono_metadata_encode_value (nparams, p, &p);
449 encode_type (assembly, sig->ret, p, &p);
450 for (i = 0; i < nparams; ++i)
451 encode_type (assembly, sig->params [i], p, &p);
453 g_assert (p - buf < size);
454 mono_metadata_encode_value (p-buf, b, &b);
455 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
461 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
464 * FIXME: reuse code from method_encode_signature().
469 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
470 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
471 guint32 size = 11 + nparams * 10;
476 p = buf = g_malloc (size);
477 /* LAMESPEC: all the call conv spec is foobared */
478 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
479 if (mb->call_conv & 2)
480 *p |= 0x5; /* vararg */
481 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
482 *p |= 0x20; /* hasthis */
484 *p |= 0x10; /* generic */
487 mono_metadata_encode_value (ngparams, p, &p);
488 mono_metadata_encode_value (nparams, p, &p);
489 encode_reflection_type (assembly, mb->rtype, p, &p);
490 for (i = 0; i < nparams; ++i) {
491 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
492 encode_reflection_type (assembly, pt, p, &p);
495 g_assert (p - buf < size);
496 mono_metadata_encode_value (p-buf, b, &b);
497 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
503 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
505 MonoDynamicTable *table;
508 guint32 idx, sig_idx, size;
509 guint nl = mono_array_length (ilgen->locals);
516 p = buf = g_malloc (size);
517 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
518 idx = table->next_idx ++;
520 alloc_table (table, table->rows);
521 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
523 mono_metadata_encode_value (0x07, p, &p);
524 mono_metadata_encode_value (nl, p, &p);
525 for (i = 0; i < nl; ++i) {
526 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
527 encode_reflection_type (assembly, lb->type, p, &p);
529 g_assert (p - buf < size);
530 mono_metadata_encode_value (p-buf, b, &b);
531 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
534 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
540 method_count_clauses (MonoReflectionILGen *ilgen)
542 guint32 num_clauses = 0;
545 MonoILExceptionInfo *ex_info;
546 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
547 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
548 if (ex_info->handlers)
549 num_clauses += mono_array_length (ex_info->handlers);
557 static MonoExceptionClause*
558 method_encode_clauses (MonoDynamicImage *assembly,
559 MonoReflectionILGen *ilgen, guint32 num_clauses)
561 MonoExceptionClause *clauses;
562 MonoExceptionClause *clause;
563 MonoILExceptionInfo *ex_info;
564 MonoILExceptionBlock *ex_block;
565 guint32 finally_start;
566 int i, j, clause_index;;
568 clauses = g_new0 (MonoExceptionClause, num_clauses);
571 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
572 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
573 finally_start = ex_info->start + ex_info->len;
574 g_assert (ex_info->handlers);
575 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
576 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
577 clause = &(clauses [clause_index]);
579 clause->flags = ex_block->type;
580 clause->try_offset = ex_info->start;
582 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
583 clause->try_len = finally_start - ex_info->start;
585 clause->try_len = ex_info->len;
586 clause->handler_offset = ex_block->start;
587 clause->handler_len = ex_block->len;
588 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
589 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
590 if (ex_block->extype) {
591 mono_g_hash_table_insert (assembly->tokens,
592 GUINT_TO_POINTER (clause->token_or_filter),
595 finally_start = ex_block->start + ex_block->len;
605 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
611 gint32 num_locals = 0;
612 gint32 num_exception = 0;
615 char fat_header [12];
618 guint32 local_sig = 0;
619 guint32 header_size = 12;
622 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
623 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
624 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
625 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
629 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
631 code = mb->ilgen->code;
632 code_size = mb->ilgen->code_len;
633 max_stack = mb->ilgen->max_stack;
634 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
635 if (mb->ilgen->ex_handlers)
636 num_exception = method_count_clauses (mb->ilgen);
640 mono_raise_exception (mono_get_exception_argument (NULL, "a method does not have any IL associated"));
642 code_size = mono_array_length (code);
643 max_stack = 8; /* we probably need to run a verifier on the code... */
646 /* check for exceptions, maxstack, locals */
647 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
649 if (code_size < 64 && !(code_size & 1)) {
650 flags = (code_size << 2) | 0x2;
651 } else if (code_size < 32 && (code_size & 1)) {
652 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
656 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
657 /* add to the fixup todo list */
658 if (mb->ilgen && mb->ilgen->num_token_fixups)
659 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
660 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
661 return assembly->text_rva + idx;
665 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
667 * FIXME: need to set also the header size in fat_flags.
668 * (and more sects and init locals flags)
672 fat_flags |= METHOD_HEADER_MORE_SECTS;
674 fat_flags |= METHOD_HEADER_INIT_LOCALS;
675 fat_header [0] = fat_flags;
676 fat_header [1] = (header_size / 4 ) << 4;
677 shortp = (guint16*)(fat_header + 2);
678 *shortp = GUINT16_TO_LE (max_stack);
679 intp = (guint32*)(fat_header + 4);
680 *intp = GUINT32_TO_LE (code_size);
681 intp = (guint32*)(fat_header + 8);
682 *intp = GUINT32_TO_LE (local_sig);
683 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
684 /* add to the fixup todo list */
685 if (mb->ilgen && mb->ilgen->num_token_fixups)
686 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
688 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
690 unsigned char sheader [4];
691 MonoExceptionClause clause;
692 MonoILExceptionInfo * ex_info;
693 MonoILExceptionBlock * ex_block;
696 stream_data_align (&assembly->code);
697 /* always use fat format for now */
698 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
699 num_exception *= sizeof (MonoExceptionClause);
700 num_exception += 4; /* include the size of the header */
701 sheader [1] = num_exception & 0xff;
702 sheader [2] = (num_exception >> 8) & 0xff;
703 sheader [3] = (num_exception >> 16) & 0xff;
704 mono_image_add_stream_data (&assembly->code, sheader, 4);
705 /* fat header, so we are already aligned */
707 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
708 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
709 if (ex_info->handlers) {
710 int finally_start = ex_info->start + ex_info->len;
711 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
712 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
713 clause.flags = GUINT32_TO_LE (ex_block->type);
714 clause.try_offset = GUINT32_TO_LE (ex_info->start);
715 /* need fault, too, probably */
716 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
717 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
719 clause.try_len = GUINT32_TO_LE (ex_info->len);
720 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
721 clause.handler_len = GUINT32_TO_LE (ex_block->len);
722 finally_start = ex_block->start + ex_block->len;
723 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
724 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
725 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
726 /*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",
727 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);*/
728 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
731 g_error ("No clauses for ex info block %d", i);
735 return assembly->text_rva + idx;
739 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
742 MonoDynamicTable *table;
745 table = &assembly->tables [table_idx];
747 g_assert (col < table->columns);
749 values = table->values + table->columns;
750 for (i = 1; i <= table->rows; ++i) {
751 if (values [col] == token)
753 values += table->columns;
758 static GHashTable *dynamic_custom_attrs = NULL;
760 static MonoCustomAttrInfo*
761 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
764 MonoCustomAttrInfo *ainfo;
765 MonoReflectionCustomAttr *cattr;
769 /* FIXME: check in assembly the Run flag is set */
771 count = mono_array_length (cattrs);
773 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
775 ainfo->image = image;
776 ainfo->num_attrs = count;
777 for (i = 0; i < count; ++i) {
778 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
779 ainfo->attrs [i].ctor = cattr->ctor->method;
780 /* FIXME: might want to memdup the data here */
781 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
782 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
789 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
791 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
796 if (!dynamic_custom_attrs)
797 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
799 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
803 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
805 /* they are cached, so we don't free them */
806 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
812 * idx is the table index of the object
813 * type is one of CUSTOM_ATTR_*
816 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
818 MonoDynamicTable *table;
819 MonoReflectionCustomAttr *cattr;
821 guint32 count, i, token;
825 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
828 count = mono_array_length (cattrs);
829 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
830 table->rows += count;
831 alloc_table (table, table->rows);
832 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
833 idx <<= CUSTOM_ATTR_BITS;
835 for (i = 0; i < count; ++i) {
836 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
837 values [MONO_CUSTOM_ATTR_PARENT] = idx;
838 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
839 type = mono_metadata_token_index (token);
840 type <<= CUSTOM_ATTR_TYPE_BITS;
841 switch (mono_metadata_token_table (token)) {
842 case MONO_TABLE_METHOD:
843 type |= CUSTOM_ATTR_TYPE_METHODDEF;
845 case MONO_TABLE_MEMBERREF:
846 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
849 g_warning ("got wrong token in custom attr");
852 values [MONO_CUSTOM_ATTR_TYPE] = type;
854 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
855 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
856 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
857 values += MONO_CUSTOM_ATTR_SIZE;
863 * Fill in the MethodDef and ParamDef tables for a method.
864 * This is used for both normal methods and constructors.
867 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
869 MonoDynamicTable *table;
874 /* room in this table is already allocated */
875 table = &assembly->tables [MONO_TABLE_METHOD];
876 *mb->table_idx = table->next_idx ++;
877 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
878 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
879 name = mono_string_to_utf8 (mb->name);
880 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
882 values [MONO_METHOD_FLAGS] = mb->attrs;
883 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
884 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
885 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
887 table = &assembly->tables [MONO_TABLE_PARAM];
888 values [MONO_METHOD_PARAMLIST] = table->next_idx;
891 MonoDynamicTable *mtable;
894 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
895 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
898 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
899 if (mono_array_get (mb->pinfo, gpointer, i))
902 table->rows += count;
903 alloc_table (table, table->rows);
904 values = table->values + table->next_idx * MONO_PARAM_SIZE;
905 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
906 MonoReflectionParamBuilder *pb;
907 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
908 values [MONO_PARAM_FLAGS] = pb->attrs;
909 values [MONO_PARAM_SEQUENCE] = i;
910 if (pb->name != NULL) {
911 name = mono_string_to_utf8 (pb->name);
912 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
916 values [MONO_PARAM_NAME] = 0;
917 values += MONO_PARAM_SIZE;
918 if (pb->marshal_info) {
920 alloc_table (mtable, mtable->rows);
921 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
922 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
923 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
925 pb->table_idx = table->next_idx++;
932 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
933 MonoReflectionMethodBuilder *mb)
935 rmb->ilgen = mb->ilgen;
936 rmb->rtype = mb->rtype;
937 rmb->parameters = mb->parameters;
938 rmb->generic_params = mb->generic_params;
939 rmb->pinfo = mb->pinfo;
940 rmb->attrs = mb->attrs;
941 rmb->iattrs = mb->iattrs;
942 rmb->call_conv = mb->call_conv;
943 rmb->code = mb->code;
944 rmb->type = mb->type;
945 rmb->name = mb->name;
946 rmb->table_idx = &mb->table_idx;
947 rmb->init_locals = mb->init_locals;
948 rmb->mhandle = mb->mhandle;
952 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
953 MonoReflectionCtorBuilder *mb)
955 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
957 rmb->ilgen = mb->ilgen;
958 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
959 rmb->parameters = mb->parameters;
960 rmb->generic_params = NULL;
961 rmb->pinfo = mb->pinfo;
962 rmb->attrs = mb->attrs;
963 rmb->iattrs = mb->iattrs;
964 rmb->call_conv = mb->call_conv;
966 rmb->type = mb->type;
967 rmb->name = mono_string_new (mono_domain_get (), name);
968 rmb->table_idx = &mb->table_idx;
969 rmb->init_locals = mb->init_locals;
970 rmb->mhandle = mb->mhandle;
974 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
976 MonoDynamicTable *table;
979 ReflectionMethodBuilder rmb;
982 reflection_methodbuilder_from_method_builder (&rmb, mb);
984 mono_image_basic_method (&rmb, assembly);
986 if (mb->dll) { /* It's a P/Invoke method */
988 int charset = mb->charset & 0xf;
989 int lasterr = mb->charset & 0x40;
990 table = &assembly->tables [MONO_TABLE_IMPLMAP];
992 alloc_table (table, table->rows);
993 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
994 /* map CharSet values to on-disk values */
996 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
997 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
998 name = mono_string_to_utf8 (mb->dllentry);
999 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1001 name = mono_string_to_utf8 (mb->dll);
1002 moduleref = string_heap_insert (&assembly->sheap, name);
1004 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1005 table = &assembly->tables [MONO_TABLE_MODULEREF];
1007 alloc_table (table, table->rows);
1008 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1009 values [MONO_IMPLMAP_SCOPE] = table->rows;
1013 if (mb->override_method) {
1014 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1016 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1018 alloc_table (table, table->rows);
1019 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1020 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1021 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
1022 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
1023 switch (mono_metadata_token_table (tok)) {
1024 case MONO_TABLE_MEMBERREF:
1025 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
1027 case MONO_TABLE_METHOD:
1028 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
1031 g_assert_not_reached ();
1033 values [MONO_METHODIMPL_DECLARATION] = tok;
1036 if (mb->generic_params) {
1037 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1038 table->rows += mono_array_length (mb->generic_params);
1039 alloc_table (table, table->rows);
1040 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1041 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1043 mono_image_get_generic_param_info (
1044 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1051 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1053 ReflectionMethodBuilder rmb;
1055 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1057 mono_image_basic_method (&rmb, assembly);
1061 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1063 char blob_size [64];
1064 char *b = blob_size;
1069 if (!assembly->save)
1072 p = buf = g_malloc (64);
1074 mono_metadata_encode_value (0x06, p, &p);
1075 /* encode custom attributes before the type */
1076 encode_type (assembly, type, p, &p);
1077 g_assert (p-buf < 64);
1078 mono_metadata_encode_value (p-buf, b, &b);
1079 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1085 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1087 char blob_size [64];
1088 char *b = blob_size;
1093 p = buf = g_malloc (64);
1095 mono_metadata_encode_value (0x06, p, &p);
1096 /* encode custom attributes before the type */
1097 encode_reflection_type (assembly, fb->type, p, &p);
1098 g_assert (p-buf < 64);
1099 mono_metadata_encode_value (p-buf, b, &b);
1100 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1106 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
1107 * dest may be misaligned.
1110 swap_with_size (char *dest, const char* val, int len, int nelem) {
1111 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1114 for (elem = 0; elem < nelem; ++elem) {
1140 g_assert_not_reached ();
1146 memcpy (dest, val, len * nelem);
1151 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1152 char blob_size [64];
1153 char *b = blob_size;
1156 guint32 idx, len, dummy = 0;
1158 p = buf = g_malloc (64);
1160 *ret_type = MONO_TYPE_CLASS;
1162 box_val = (char*)&dummy;
1164 box_val = ((char*)val) + sizeof (MonoObject);
1165 *ret_type = val->vtable->klass->byval_arg.type;
1168 switch (*ret_type) {
1169 case MONO_TYPE_BOOLEAN:
1174 case MONO_TYPE_CHAR:
1189 case MONO_TYPE_VALUETYPE:
1190 if (val->vtable->klass->enumtype) {
1191 *ret_type = val->vtable->klass->enum_basetype->type;
1194 g_error ("we can't encode valuetypes");
1195 case MONO_TYPE_CLASS:
1197 case MONO_TYPE_STRING: {
1198 MonoString *str = (MonoString*)val;
1199 /* there is no signature */
1200 len = str->length * 2;
1201 mono_metadata_encode_value (len, b, &b);
1202 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1204 char *swapped = g_malloc (2 * mono_string_length (str));
1205 const char *p = (const char*)mono_string_chars (str);
1207 swap_with_size (swapped, p, 2, mono_string_length (str));
1208 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1212 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1219 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1222 /* there is no signature */
1223 mono_metadata_encode_value (len, b, &b);
1224 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1225 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1226 swap_with_size (blob_size, box_val, len, 1);
1227 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1229 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1237 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1238 char blob_size [64];
1239 char *b = blob_size;
1240 char *p, *buf, *str;
1241 guint32 idx, len, bufsize = 256;
1243 p = buf = g_malloc (bufsize);
1245 switch (minfo->type) {
1246 case MONO_NATIVE_BYVALTSTR:
1247 case MONO_NATIVE_BYVALARRAY:
1248 mono_metadata_encode_value (minfo->type, p, &p);
1249 mono_metadata_encode_value (minfo->count, p, &p);
1251 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
1252 case MONO_NATIVE_CUSTOM:
1253 mono_metadata_encode_value (minfo->type, p, &p);
1255 str = mono_string_to_utf8 (minfo->guid);
1257 mono_metadata_encode_value (len, p, &p);
1258 memcpy (p, str, len);
1262 mono_metadata_encode_value (0, p, &p);
1264 if (minfo->marshaltype) {
1265 str = mono_string_to_utf8 (minfo->marshaltype);
1267 mono_metadata_encode_value (len, p, &p);
1268 if (p + len >= buf + bufsize) {
1271 buf = g_realloc (buf, bufsize);
1274 memcpy (p, str, len);
1278 mono_metadata_encode_value (0, p, &p);
1280 if (minfo->marshaltyperef) {
1281 str = type_get_qualified_name (minfo->marshaltyperef->type, assembly->image.assembly);
1283 mono_metadata_encode_value (len, p, &p);
1284 if (p + len >= buf + bufsize) {
1287 buf = g_realloc (buf, bufsize);
1290 memcpy (p, str, len);
1294 mono_metadata_encode_value (0, p, &p);
1296 if (minfo->mcookie) {
1297 str = mono_string_to_utf8 (minfo->mcookie);
1299 mono_metadata_encode_value (len, p, &p);
1300 if (p + len >= buf + bufsize) {
1303 buf = g_realloc (buf, bufsize);
1306 memcpy (p, str, len);
1310 mono_metadata_encode_value (0, p, &p);
1314 mono_metadata_encode_value (minfo->type, p, &p);
1318 mono_metadata_encode_value (len, b, &b);
1319 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1325 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1327 MonoDynamicTable *table;
1331 /* maybe this fixup should be done in the C# code */
1332 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1333 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1334 table = &assembly->tables [MONO_TABLE_FIELD];
1335 fb->table_idx = table->next_idx ++;
1336 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1337 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1338 name = mono_string_to_utf8 (fb->name);
1339 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1341 values [MONO_FIELD_FLAGS] = fb->attrs;
1342 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1344 if (fb->offset != -1) {
1345 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1347 alloc_table (table, table->rows);
1348 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1349 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1350 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1352 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1353 guint32 field_type = 0;
1354 table = &assembly->tables [MONO_TABLE_CONSTANT];
1356 alloc_table (table, table->rows);
1357 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1358 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1359 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1360 values [MONO_CONSTANT_TYPE] = field_type;
1361 values [MONO_CONSTANT_PADDING] = 0;
1365 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1367 alloc_table (table, table->rows);
1368 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1369 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1371 * We store it in the code section because it's simpler for now.
1373 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1374 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1376 if (fb->marshal_info) {
1377 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1379 alloc_table (table, table->rows);
1380 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1381 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1382 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1387 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1391 char *b = blob_size;
1392 guint32 nparams = 0;
1393 MonoReflectionMethodBuilder *mb = fb->get_method;
1394 MonoReflectionMethodBuilder *smb = fb->set_method;
1395 guint32 idx, i, size;
1397 if (mb && mb->parameters)
1398 nparams = mono_array_length (mb->parameters);
1399 if (!mb && smb && smb->parameters)
1400 nparams = mono_array_length (smb->parameters) - 1;
1401 size = 24 + nparams * 10;
1402 buf = p = g_malloc (size);
1405 mono_metadata_encode_value (nparams, p, &p);
1407 encode_reflection_type (assembly, mb->rtype, p, &p);
1408 for (i = 0; i < nparams; ++i) {
1409 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1410 encode_reflection_type (assembly, pt, p, &p);
1413 /* the property type is the last param */
1414 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1415 for (i = 0; i < nparams; ++i) {
1416 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1417 encode_reflection_type (assembly, pt, p, &p);
1421 g_assert (p - buf < size);
1422 mono_metadata_encode_value (p-buf, b, &b);
1423 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1429 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1431 MonoDynamicTable *table;
1434 guint num_methods = 0;
1438 * we need to set things in the following tables:
1439 * PROPERTYMAP (info already filled in _get_type_info ())
1440 * PROPERTY (rows already preallocated in _get_type_info ())
1441 * METHOD (method info already done with the generic method code)
1444 table = &assembly->tables [MONO_TABLE_PROPERTY];
1445 pb->table_idx = table->next_idx ++;
1446 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1447 name = mono_string_to_utf8 (pb->name);
1448 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1450 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1451 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1453 /* FIXME: we still don't handle 'other' methods */
1454 if (pb->get_method) num_methods ++;
1455 if (pb->set_method) num_methods ++;
1457 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1458 table->rows += num_methods;
1459 alloc_table (table, table->rows);
1461 if (pb->get_method) {
1462 semaidx = table->next_idx ++;
1463 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1464 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1465 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1466 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1468 if (pb->set_method) {
1469 semaidx = table->next_idx ++;
1470 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1471 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1472 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1473 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1478 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1480 MonoDynamicTable *table;
1483 guint num_methods = 0;
1487 * we need to set things in the following tables:
1488 * EVENTMAP (info already filled in _get_type_info ())
1489 * EVENT (rows already preallocated in _get_type_info ())
1490 * METHOD (method info already done with the generic method code)
1493 table = &assembly->tables [MONO_TABLE_EVENT];
1494 eb->table_idx = table->next_idx ++;
1495 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1496 name = mono_string_to_utf8 (eb->name);
1497 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1499 values [MONO_EVENT_FLAGS] = eb->attrs;
1500 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1503 * FIXME: we still don't handle 'other' methods
1505 if (eb->add_method) num_methods ++;
1506 if (eb->remove_method) num_methods ++;
1507 if (eb->raise_method) num_methods ++;
1509 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1510 table->rows += num_methods;
1511 alloc_table (table, table->rows);
1513 if (eb->add_method) {
1514 semaidx = table->next_idx ++;
1515 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1516 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1517 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1518 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1520 if (eb->remove_method) {
1521 semaidx = table->next_idx ++;
1522 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1523 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1524 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1525 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1527 if (eb->raise_method) {
1528 semaidx = table->next_idx ++;
1529 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1530 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1531 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1532 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1537 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1539 MonoDynamicTable *table;
1540 guint32 num_constraints, i;
1544 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1545 num_constraints = gparam ? mono_array_length (gparam->constraints) : 0;
1546 table->rows += num_constraints;
1547 alloc_table (table, table->rows);
1549 for (i = 0; i < num_constraints; i++) {
1550 MonoReflectionType *constraint = mono_array_get (gparam->constraints, gpointer, i);
1552 table_idx = table->next_idx ++;
1553 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1555 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1556 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint->type);
1561 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1563 MonoDynamicTable *table;
1567 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1568 table_idx = table->next_idx ++;
1569 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
1571 values [MONO_GENERICPARAM_OWNER] = owner;
1572 values [MONO_GENERICPARAM_FLAGS] = gparam->param->flags;
1573 values [MONO_GENERICPARAM_NUMBER] = gparam->param->num;
1574 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, gparam->param->name);
1575 values [MONO_GENERICPARAM_KIND] = 0;
1576 values [MONO_GENERICPARAM_DEPRECATED_CONSTRAINT] = 0;
1578 if (gparam->constraints)
1579 encode_constraints (gparam, table_idx, assembly);
1583 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
1585 MonoDynamicTable *table;
1588 guint32 cols [MONO_ASSEMBLY_SIZE];
1592 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1595 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
1596 table = &assembly->tables [MONO_TABLE_MODULEREF];
1597 token = table->next_idx ++;
1599 alloc_table (table, table->rows);
1600 values = table->values + token * MONO_MODULEREF_SIZE;
1601 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
1603 token <<= RESOLTION_SCOPE_BITS;
1604 token |= RESOLTION_SCOPE_MODULEREF;
1605 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1610 if (image->assembly->dynamic)
1612 memset (cols, 0, sizeof (cols));
1614 /* image->assembly->image is the manifest module */
1615 image = image->assembly->image;
1616 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1619 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1620 token = table->next_idx ++;
1622 alloc_table (table, table->rows);
1623 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1624 if (strcmp ("corlib", image->assembly_name) == 0)
1625 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1627 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1628 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1629 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1630 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1631 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1632 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1633 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1634 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1636 if ((pubkey = mono_image_get_public_key (image, &publen))) {
1637 guchar pubtoken [9];
1639 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
1640 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
1643 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
1644 * This is currently only a problem with references to System.Xml (see bug#27706),
1645 * but there may be other cases that makes this necessary. Note, we need to set
1646 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
1647 * recognized by ms, yuck!
1648 * FIXME: need to add more assembly names, as needed.
1650 if (strcmp (image->assembly_name, "corlib") == 0 ||
1651 strcmp (image->assembly_name, "mscorlib") == 0 ||
1652 strcmp (image->assembly_name, "System") == 0 ||
1653 strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 ||
1654 strcmp (image->assembly_name, "System.Xml") == 0 ||
1655 strcmp (image->assembly_name, "System.Data") == 0 ||
1656 strcmp (image->assembly_name, "System.Windows.Forms") == 0) {
1657 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
1658 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1659 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1660 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1661 } else if (strcmp (image->assembly_name, "Accessibility") == 0 ||
1662 strcmp (image->assembly_name, "cscompmgd") == 0 ||
1663 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
1664 strcmp (image->assembly_name, "Microsoft.JScript") == 0 ||
1665 strcmp (image->assembly_name, "Microsoft.VisualBasic") == 0 ||
1666 strcmp (image->assembly_name, "Microsoft.VisualBasic.Vsa") == 0 ||
1667 strcmp (image->assembly_name, "Microsoft.VisualC") == 0 ||
1668 strcmp (image->assembly_name, "Microsoft.Vsa") == 0 ||
1669 strcmp (image->assembly_name, "System.Configuration.Install") == 0 ||
1670 strcmp (image->assembly_name, "System.DirectoryServices") == 0 ||
1671 strcmp (image->assembly_name, "System.Design") == 0 ||
1672 strcmp (image->assembly_name, "System.Drawing") == 0 ||
1673 strcmp (image->assembly_name, "System.Drawing.Design") == 0 ||
1674 strcmp (image->assembly_name, "System.EnterpriseServices") == 0 ||
1675 strcmp (image->assembly_name, "System.Management") == 0 ||
1676 strcmp (image->assembly_name, "System.Messaging") == 0 ||
1677 strcmp (image->assembly_name, "System.Runtime.Serialization.Formatters.Soap") == 0 ||
1678 strcmp (image->assembly_name, "System.Security") == 0 ||
1679 strcmp (image->assembly_name, "System.ServiceProcess") == 0 ||
1680 strcmp (image->assembly_name, "System.Web.Services") == 0 ||
1681 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
1682 strcmp (image->assembly_name, "System.Web") == 0) {
1683 static const guchar ptoken [9] = {8, '\xb0', '\x3f', '\x5f', '\x7f', '\x11', '\xd5', '\x0a', '\x3a'};
1684 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1685 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1686 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1688 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1691 token <<= RESOLTION_SCOPE_BITS;
1692 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1693 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1698 create_typespec (MonoDynamicImage *assembly, MonoType *type)
1700 MonoDynamicTable *table;
1706 char *b = blob_size;
1708 switch (type->type) {
1709 case MONO_TYPE_FNPTR:
1711 case MONO_TYPE_SZARRAY:
1712 case MONO_TYPE_ARRAY:
1714 case MONO_TYPE_MVAR:
1715 case MONO_TYPE_GENERICINST:
1716 encode_type (assembly, type, p, &p);
1718 case MONO_TYPE_CLASS:
1719 case MONO_TYPE_VALUETYPE: {
1720 MonoClass *k = mono_class_from_mono_type (type);
1721 if (!k || !k->generic_inst)
1723 encode_type (assembly, k->generic_inst, p, &p);
1730 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1731 if (assembly->save) {
1732 g_assert (p-sig < 128);
1733 mono_metadata_encode_value (p-sig, b, &b);
1734 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
1735 alloc_table (table, table->rows + 1);
1736 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1737 values [MONO_TYPESPEC_SIGNATURE] = token;
1740 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1741 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1747 * Despite the name, we handle also TypeSpec (with the above helper).
1750 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
1752 MonoDynamicTable *table;
1754 guint32 token, scope, enclosing;
1757 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1760 token = create_typespec (assembly, type);
1763 klass = my_mono_class_from_mono_type (type);
1765 klass = mono_class_from_mono_type (type);
1768 * If it's in the same module and not a generic type parameter:
1770 if ((klass->image == &assembly->image) &&
1771 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
1772 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1773 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1774 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
1778 if (klass->nested_in) {
1779 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1780 /* get the typeref idx of the enclosing type */
1781 enclosing >>= TYPEDEFORREF_BITS;
1782 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1784 scope = resolution_scope_from_image (assembly, klass->image);
1786 table = &assembly->tables [MONO_TABLE_TYPEREF];
1787 if (assembly->save) {
1788 alloc_table (table, table->rows + 1);
1789 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1790 values [MONO_TYPEREF_SCOPE] = scope;
1791 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1792 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1794 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1795 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1797 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
1802 * Insert a memberef row into the metadata: the token that point to the memberref
1803 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1804 * mono_image_get_fieldref_token()).
1805 * The sig param is an index to an already built signature.
1808 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
1810 MonoDynamicTable *table;
1812 guint32 token, pclass;
1815 parent = mono_image_typedef_or_ref (assembly, type);
1816 switch (parent & TYPEDEFORREF_MASK) {
1817 case TYPEDEFORREF_TYPEREF:
1818 pclass = MEMBERREF_PARENT_TYPEREF;
1820 case TYPEDEFORREF_TYPESPEC:
1821 pclass = MEMBERREF_PARENT_TYPESPEC;
1823 case TYPEDEFORREF_TYPEDEF:
1824 pclass = MEMBERREF_PARENT_TYPEDEF;
1827 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
1830 /* extract the index */
1831 parent >>= TYPEDEFORREF_BITS;
1833 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1835 if (assembly->save) {
1836 alloc_table (table, table->rows + 1);
1837 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1838 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1839 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1840 values [MONO_MEMBERREF_SIGNATURE] = sig;
1843 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1850 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
1854 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1857 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1858 method->name, method_encode_signature (assembly, method->signature));
1859 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1864 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1867 ReflectionMethodBuilder rmb;
1869 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
1873 reflection_methodbuilder_from_method_builder (&rmb, mb);
1876 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
1877 mono_string_to_utf8 (rmb.name),
1878 method_builder_encode_signature (assembly, &rmb));
1879 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
1884 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
1887 ReflectionMethodBuilder rmb;
1889 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
1893 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1895 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
1896 mono_string_to_utf8 (rmb.name),
1897 method_builder_encode_signature (assembly, &rmb));
1898 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
1903 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoClassField *field, MonoClass *klass)
1907 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1910 field->parent = klass;
1911 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
1912 field->name, fieldref_encode_signature (assembly, field->type));
1913 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1918 field_encode_inflated_field (MonoDynamicImage *assembly, MonoReflectionInflatedField *field)
1924 klass = field->rfield.klass;
1925 name = field->rfield.field->name;
1926 sig = fieldref_encode_signature (assembly, field->declaring->type);
1927 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
1933 mono_image_get_inflated_field_token (MonoDynamicImage *assembly, MonoReflectionInflatedField *field)
1937 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field->rfield.field));
1940 token = field_encode_inflated_field (assembly, field);
1941 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1946 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericInst *ginst)
1951 guint32 nparams = ginst->type_argc;
1952 guint32 size = 10 + nparams * 10;
1955 char *b = blob_size;
1957 if (!assembly->save)
1960 p = buf = g_malloc (size);
1962 * FIXME: vararg, explicit_this, differenc call_conv values...
1964 mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
1965 mono_metadata_encode_value (nparams, p, &p);
1967 for (i = 0; i < nparams; i++)
1968 encode_type (assembly, ginst->type_argv [i], p, &p);
1971 g_assert (p - buf < size);
1972 mono_metadata_encode_value (p-buf, b, &b);
1973 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1979 method_encode_methodspec (MonoDynamicImage *assembly, MonoGenericInst *ginst)
1981 MonoDynamicTable *table;
1983 guint32 token, mtoken, sig;
1985 table = &assembly->tables [MONO_TABLE_METHODSPEC];
1988 if (ginst->generic_method) {
1989 MonoMethod *gm = ginst->generic_method;
1990 MonoClass *k = ginst->klass ? ginst->klass : gm->klass;
1992 sig = method_encode_signature (assembly, gm->signature);
1993 mtoken = mono_image_get_memberref_token (assembly, &k->byval_arg, gm->name, sig);
1995 if (!ginst->generic_method->signature->generic_param_count)
1999 g_assert_not_reached ();
2001 switch (mono_metadata_token_table (mtoken)) {
2002 case MONO_TABLE_MEMBERREF:
2003 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2005 case MONO_TABLE_METHOD:
2006 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2009 g_assert_not_reached ();
2012 sig = encode_generic_method_sig (assembly, ginst);
2014 if (assembly->save) {
2015 alloc_table (table, table->rows + 1);
2016 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2017 values [MONO_METHODSPEC_METHOD] = mtoken;
2018 values [MONO_METHODSPEC_SIGNATURE] = sig;
2021 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2028 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method, MonoGenericInst *ginst)
2032 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2035 token = method_encode_methodspec (assembly, ginst);
2036 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2041 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2043 MonoDynamicTable *table;
2050 char *b = blob_size;
2053 g_assert (tb->generic_params);
2054 klass = mono_class_from_mono_type (tb->type.type);
2056 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2057 encode_type (assembly, &klass->byval_arg, p, &p);
2059 count = mono_array_length (tb->generic_params);
2060 mono_metadata_encode_value (count, p, &p);
2061 for (i = 0; i < count; i++) {
2062 MonoReflectionGenericParam *gparam;
2065 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2067 t.type = MONO_TYPE_VAR;
2068 t.data.generic_param = gparam->param;
2070 encode_type (assembly, &t, p, &p);
2073 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2074 if (assembly->save) {
2075 g_assert (p-sig < 128);
2076 mono_metadata_encode_value (p-sig, b, &b);
2077 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2078 alloc_table (table, table->rows + 1);
2079 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2080 values [MONO_TYPESPEC_SIGNATURE] = token;
2083 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2084 g_hash_table_insert (assembly->typeref, tb->type.type, GUINT_TO_POINTER(token));
2090 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2092 MonoDynamicTable *table;
2095 guint32 token, pclass, parent, sig;
2098 klass = mono_class_from_mono_type (fb->typeb->type);
2099 name = mono_string_to_utf8 (fb->name);
2101 sig = fieldref_encode_signature (assembly, fb->type->type);
2103 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2104 g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2106 pclass = MEMBERREF_PARENT_TYPESPEC;
2107 parent >>= TYPEDEFORREF_BITS;
2109 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2111 if (assembly->save) {
2112 alloc_table (table, table->rows + 1);
2113 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2114 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2115 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2116 values [MONO_MEMBERREF_SIGNATURE] = sig;
2119 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2126 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2134 char *b = blob_size;
2136 if (!assembly->save)
2140 g_assert (helper->type == 2);
2142 if (helper->arguments)
2143 nargs = mono_array_length (helper->arguments);
2147 size = 10 + (nargs * 10);
2149 p = buf = g_malloc (size);
2151 /* Encode calling convention */
2152 /* Change Any to Standard */
2153 if ((helper->call_conv & 0x03) == 0x03)
2154 helper->call_conv = 0x01;
2155 /* explicit_this implies has_this */
2156 if (helper->call_conv & 0x40)
2157 helper->call_conv &= 0x20;
2159 if (helper->call_conv == 0) /* Unmanaged */
2160 *p = helper->unmanaged_call_conv - 1;
2163 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2164 if (helper->call_conv & 0x02) /* varargs */
2169 mono_metadata_encode_value (nargs, p, &p);
2170 encode_reflection_type (assembly, helper->return_type, p, &p);
2171 for (i = 0; i < nargs; ++i) {
2172 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2173 encode_reflection_type (assembly, pt, p, &p);
2176 g_assert (p - buf < size);
2177 mono_metadata_encode_value (p-buf, b, &b);
2178 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2185 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2188 MonoDynamicTable *table;
2191 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2192 idx = table->next_idx ++;
2194 alloc_table (table, table->rows);
2195 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2197 values [MONO_STAND_ALONE_SIGNATURE] =
2198 mono_reflection_encode_sighelper (assembly, helper);
2204 reflection_cc_to_file (int call_conv) {
2205 switch (call_conv & 0x3) {
2207 case 1: return MONO_CALL_DEFAULT;
2208 case 2: return MONO_CALL_VARARG;
2210 g_assert_not_reached ();
2217 MonoMethodSignature *sig;
2223 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2228 MonoMethodSignature *sig;
2231 name = mono_string_to_utf8 (m->name);
2232 nparams = mono_array_length (m->parameters);
2233 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2235 sig->call_convention = reflection_cc_to_file (m->call_conv);
2236 sig->param_count = nparams;
2237 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2238 for (i = 0; i < nparams; ++i) {
2239 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2240 sig->params [i] = t->type;
2243 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2245 if (strcmp (name, am->name) == 0 &&
2246 mono_metadata_type_equal (am->parent, m->parent->type) &&
2247 mono_metadata_signature_equal (am->sig, sig)) {
2250 m->table_idx = am->token & 0xffffff;
2254 am = g_new0 (ArrayMethod, 1);
2257 am->parent = m->parent->type;
2258 am->token = mono_image_get_memberref_token (assembly, am->parent,
2259 name, method_encode_signature (assembly, sig));
2260 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2261 m->table_idx = am->token & 0xffffff;
2266 * Insert into the metadata tables all the info about the TypeBuilder tb.
2267 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2270 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2272 MonoDynamicTable *table;
2274 int i, is_object = 0, is_system = 0;
2277 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2278 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2279 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2280 n = mono_string_to_utf8 (tb->name);
2281 if (strcmp (n, "Object") == 0)
2283 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2285 n = mono_string_to_utf8 (tb->nspace);
2286 if (strcmp (n, "System") == 0)
2288 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2290 if (tb->parent && !(is_system && is_object) &&
2291 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2292 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2294 values [MONO_TYPEDEF_EXTENDS] = 0;
2295 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2296 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2299 * if we have explicitlayout or sequentiallayouts, output data in the
2300 * ClassLayout table.
2302 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2303 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2305 alloc_table (table, table->rows);
2306 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2307 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2308 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2309 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2312 /* handle interfaces */
2313 if (tb->interfaces) {
2314 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2316 table->rows += mono_array_length (tb->interfaces);
2317 alloc_table (table, table->rows);
2318 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2319 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2320 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2321 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2322 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2323 values += MONO_INTERFACEIMPL_SIZE;
2327 /* handle generic parameters */
2328 if (tb->generic_params) {
2329 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2330 table->rows += mono_array_length (tb->generic_params);
2331 alloc_table (table, table->rows);
2332 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2333 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2335 mono_image_get_generic_param_info (
2336 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2342 table = &assembly->tables [MONO_TABLE_FIELD];
2343 table->rows += mono_array_length (tb->fields);
2344 alloc_table (table, table->rows);
2345 for (i = 0; i < mono_array_length (tb->fields); ++i)
2346 mono_image_get_field_info (
2347 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2350 /* handle constructors */
2352 table = &assembly->tables [MONO_TABLE_METHOD];
2353 table->rows += mono_array_length (tb->ctors);
2354 alloc_table (table, table->rows);
2355 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2356 mono_image_get_ctor_info (domain,
2357 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2360 /* handle methods */
2362 table = &assembly->tables [MONO_TABLE_METHOD];
2363 table->rows += mono_array_length (tb->methods);
2364 alloc_table (table, table->rows);
2365 for (i = 0; i < mono_array_length (tb->methods); ++i)
2366 mono_image_get_method_info (
2367 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2370 /* Do the same with properties etc.. */
2371 if (tb->events && mono_array_length (tb->events)) {
2372 table = &assembly->tables [MONO_TABLE_EVENT];
2373 table->rows += mono_array_length (tb->events);
2374 alloc_table (table, table->rows);
2375 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2377 alloc_table (table, table->rows);
2378 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2379 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2380 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2381 for (i = 0; i < mono_array_length (tb->events); ++i)
2382 mono_image_get_event_info (
2383 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2385 if (tb->properties && mono_array_length (tb->properties)) {
2386 table = &assembly->tables [MONO_TABLE_PROPERTY];
2387 table->rows += mono_array_length (tb->properties);
2388 alloc_table (table, table->rows);
2389 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2391 alloc_table (table, table->rows);
2392 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2393 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2394 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2395 for (i = 0; i < mono_array_length (tb->properties); ++i)
2396 mono_image_get_property_info (
2397 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2400 MonoDynamicTable *ntable;
2402 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2403 ntable->rows += mono_array_length (tb->subtypes);
2404 alloc_table (ntable, ntable->rows);
2405 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2407 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2408 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2410 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2411 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2412 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2413 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2414 mono_string_to_utf8 (tb->name), tb->table_idx,
2415 ntable->next_idx, ntable->rows);*/
2416 values += MONO_NESTED_CLASS_SIZE;
2423 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2427 g_ptr_array_add (types, type);
2429 if (!type->subtypes)
2432 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2433 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2434 collect_types (types, subtype);
2439 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2440 MonoReflectionTypeBuilder **type2)
2442 if ((*type1)->table_idx < (*type2)->table_idx)
2445 if ((*type1)->table_idx > (*type2)->table_idx)
2452 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2457 for (i = 0; i < mono_array_length (pinfo); ++i) {
2458 MonoReflectionParamBuilder *pb;
2459 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2462 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2467 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2470 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2472 for (i = 0; i < mono_array_length (tb->fields); ++i) {
2473 MonoReflectionFieldBuilder* fb;
2474 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2475 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2479 for (i = 0; i < mono_array_length (tb->events); ++i) {
2480 MonoReflectionEventBuilder* eb;
2481 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2482 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2485 if (tb->properties) {
2486 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2487 MonoReflectionPropertyBuilder* pb;
2488 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2489 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2493 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2494 MonoReflectionCtorBuilder* cb;
2495 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2496 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2497 params_add_cattrs (assembly, cb->pinfo);
2502 for (i = 0; i < mono_array_length (tb->methods); ++i) {
2503 MonoReflectionMethodBuilder* mb;
2504 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2505 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2506 params_add_cattrs (assembly, mb->pinfo);
2511 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2512 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2517 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2520 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2522 /* no types in the module */
2526 for (i = 0; i < mono_array_length (mb->types); ++i)
2527 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2531 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb,
2532 MonoDynamicImage *assembly)
2534 MonoDynamicTable *table;
2538 char *b = blob_size;
2541 table = &assembly->tables [MONO_TABLE_FILE];
2543 alloc_table (table, table->rows);
2544 values = table->values + table->next_idx * MONO_FILE_SIZE;
2545 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2546 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, mb->dynamic_image->image.module_name);
2547 /* This depends on the fact that the main module is emitted last */
2548 dir = mono_string_to_utf8 (mb->assemblyb->dir);
2549 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, mb->dynamic_image->image.module_name);
2550 mono_sha1_get_digest_from_file (path, hash);
2553 mono_metadata_encode_value (20, b, &b);
2554 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2555 mono_image_add_stream_data (&assembly->blob, hash, 20);
2560 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2562 MonoDynamicTable *table;
2566 table = &assembly->tables [MONO_TABLE_MODULE];
2567 mb->table_idx = table->next_idx ++;
2568 name = mono_string_to_utf8 (mb->module.name);
2569 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2571 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2574 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2575 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2576 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2580 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
2581 guint32 module_index, guint32 parent_index,
2582 MonoDynamicImage *assembly)
2584 MonoDynamicTable *table;
2591 visib = tb->attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2592 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
2595 name = mono_string_to_utf8 (tb->name);
2596 name_space = mono_string_to_utf8 (tb->nspace);
2598 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
2600 alloc_table (table, table->rows);
2601 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
2603 values [MONO_EXP_TYPE_FLAGS] = tb->attrs;
2604 values [MONO_EXP_TYPE_TYPEDEF] = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
2605 if (tb->nesting_type) {
2606 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
2609 values [MONO_EXP_TYPE_TYPEDEF] = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
2610 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
2612 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, name);
2613 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, name_space);
2616 g_free (name_space);
2620 /* Emit nested types */
2622 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2623 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, table->next_idx - 1, assembly);
2627 #define align_pointer(base,p)\
2629 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
2631 (p) += 4 - (__diff & 3);\
2635 compare_semantics (const void *a, const void *b)
2637 const guint32 *a_values = a;
2638 const guint32 *b_values = b;
2639 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
2642 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
2646 compare_custom_attrs (const void *a, const void *b)
2648 const guint32 *a_values = a;
2649 const guint32 *b_values = b;
2651 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
2655 compare_field_marshal (const void *a, const void *b)
2657 const guint32 *a_values = a;
2658 const guint32 *b_values = b;
2660 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
2664 compare_nested (const void *a, const void *b)
2666 const guint32 *a_values = a;
2667 const guint32 *b_values = b;
2669 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
2673 * build_compressed_metadata() fills in the blob of data that represents the
2674 * raw metadata as it will be saved in the PE file. The five streams are output
2675 * and the metadata tables are comnpressed from the guint32 array representation,
2676 * to the compressed on-disk format.
2679 build_compressed_metadata (MonoDynamicImage *assembly)
2681 MonoDynamicTable *table;
2683 guint64 valid_mask = 0;
2684 guint64 sorted_mask;
2685 guint32 heapt_size = 0;
2686 guint32 meta_size = 256; /* allow for header and other stuff */
2687 guint32 table_offset;
2688 guint32 ntables = 0;
2697 MonoDynamicStream *stream;
2700 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
2701 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
2702 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
2703 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
2704 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
2706 /* tables that are sorted */
2707 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
2708 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
2709 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
2710 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
2711 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
2712 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
2714 /* Compute table sizes */
2715 /* the MonoImage has already been created in mono_image_basic_init() */
2716 meta = &assembly->image;
2718 /* Setup the info used by compute_sizes () */
2719 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
2720 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
2721 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
2723 meta_size += assembly->blob.index;
2724 meta_size += assembly->guid.index;
2725 meta_size += assembly->sheap.index;
2726 meta_size += assembly->us.index;
2728 for (i=0; i < 64; ++i)
2729 meta->tables [i].rows = assembly->tables [i].rows;
2731 for (i = 0; i < 64; i++){
2732 if (meta->tables [i].rows == 0)
2734 valid_mask |= (guint64)1 << i;
2736 meta->tables [i].row_size = mono_metadata_compute_size (
2737 meta, i, &meta->tables [i].size_bitfield);
2738 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
2740 heapt_size += 24; /* #~ header size */
2741 heapt_size += ntables * 4;
2742 meta_size += heapt_size;
2743 meta->raw_metadata = g_malloc0 (meta_size);
2744 p = meta->raw_metadata;
2745 /* the metadata signature */
2746 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
2747 /* version numbers and 4 bytes reserved */
2748 int16val = (guint16*)p;
2749 *int16val++ = GUINT16_TO_LE (1);
2750 *int16val = GUINT16_TO_LE (1);
2752 /* version string */
2753 int32val = (guint32*)p;
2754 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
2756 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
2757 p += GUINT32_FROM_LE (*int32val);
2758 align_pointer (meta->raw_metadata, p);
2759 int16val = (guint16*)p;
2760 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
2761 *int16val = GUINT16_TO_LE (5); /* number of streams */
2765 * write the stream info.
2767 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
2768 table_offset += 3; table_offset &= ~3;
2770 assembly->tstream.index = heapt_size;
2771 for (i = 0; i < 5; ++i) {
2772 int32val = (guint32*)p;
2773 stream_desc [i].stream->offset = table_offset;
2774 *int32val++ = GUINT32_TO_LE (table_offset);
2775 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
2776 table_offset += GUINT32_FROM_LE (*int32val);
2777 table_offset += 3; table_offset &= ~3;
2779 strcpy (p, stream_desc [i].name);
2780 p += strlen (stream_desc [i].name) + 1;
2781 align_pointer (meta->raw_metadata, p);
2784 * now copy the data, the table stream header and contents goes first.
2786 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
2787 p = meta->raw_metadata + assembly->tstream.offset;
2788 int32val = (guint32*)p;
2789 *int32val = GUINT32_TO_LE (0); /* reserved */
2791 *p++ = 1; /* version */
2793 if (meta->idx_string_wide)
2795 if (meta->idx_guid_wide)
2797 if (meta->idx_blob_wide)
2800 *p++ = 0; /* reserved */
2801 int64val = (guint64*)p;
2802 *int64val++ = GUINT64_TO_LE (valid_mask);
2803 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
2805 int32val = (guint32*)p;
2806 for (i = 0; i < 64; i++){
2807 if (meta->tables [i].rows == 0)
2809 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
2811 p = (unsigned char*)int32val;
2813 /* sort the tables that still need sorting */
2814 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2816 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
2817 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2819 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
2820 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2822 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
2823 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2825 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
2827 /* compress the tables */
2828 for (i = 0; i < 64; i++){
2831 guint32 bitfield = meta->tables [i].size_bitfield;
2832 if (!meta->tables [i].rows)
2834 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
2835 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
2836 meta->tables [i].base = p;
2837 for (row = 1; row <= meta->tables [i].rows; ++row) {
2838 values = assembly->tables [i].values + row * assembly->tables [i].columns;
2839 for (col = 0; col < assembly->tables [i].columns; ++col) {
2840 switch (mono_metadata_table_size (bitfield, col)) {
2842 *p++ = values [col];
2845 *p++ = values [col] & 0xff;
2846 *p++ = (values [col] >> 8) & 0xff;
2849 *p++ = values [col] & 0xff;
2850 *p++ = (values [col] >> 8) & 0xff;
2851 *p++ = (values [col] >> 16) & 0xff;
2852 *p++ = (values [col] >> 24) & 0xff;
2855 g_assert_not_reached ();
2859 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
2862 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
2863 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
2864 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
2865 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
2866 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
2868 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
2872 * Some tables in metadata need to be sorted according to some criteria, but
2873 * when methods and fields are first created with reflection, they may be assigned a token
2874 * that doesn't correspond to the final token they will get assigned after the sorting.
2875 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
2876 * with the reflection objects that represent them. Once all the tables are set up, the
2877 * reflection objects will contains the correct table index. fixup_method() will fixup the
2878 * tokens for the method with ILGenerator @ilgen.
2881 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
2882 guint32 code_idx = GPOINTER_TO_UINT (value);
2883 MonoReflectionILTokenInfo *iltoken;
2884 MonoReflectionFieldBuilder *field;
2885 MonoReflectionCtorBuilder *ctor;
2886 MonoReflectionMethodBuilder *method;
2887 MonoReflectionTypeBuilder *tb;
2888 MonoReflectionArrayMethod *am;
2890 unsigned char *target;
2892 for (i = 0; i < ilgen->num_token_fixups; ++i) {
2893 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
2894 target = assembly->code.data + code_idx + iltoken->code_pos;
2895 switch (target [3]) {
2896 case MONO_TABLE_FIELD:
2897 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
2898 field = (MonoReflectionFieldBuilder *)iltoken->member;
2899 idx = field->table_idx;
2900 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
2901 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
2902 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
2904 g_assert_not_reached ();
2907 case MONO_TABLE_METHOD:
2908 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
2909 method = (MonoReflectionMethodBuilder *)iltoken->member;
2910 idx = method->table_idx;
2911 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
2912 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
2913 idx = ctor->table_idx;
2914 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
2915 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
2916 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
2918 g_assert_not_reached ();
2921 case MONO_TABLE_TYPEDEF:
2922 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
2923 g_assert_not_reached ();
2924 tb = (MonoReflectionTypeBuilder *)iltoken->member;
2925 idx = tb->table_idx;
2927 case MONO_TABLE_MEMBERREF:
2928 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
2929 am = (MonoReflectionArrayMethod*)iltoken->member;
2930 idx = am->table_idx;
2931 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
2932 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
2933 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
2934 g_assert (m->klass->generic_inst);
2936 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoInflatedMethod") ||
2937 !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedCtor") ||
2938 !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedField")) {
2940 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
2943 g_assert_not_reached ();
2946 case MONO_TABLE_METHODSPEC:
2947 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
2948 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
2949 g_assert (m->signature->generic_param_count);
2951 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoInflatedMethod") ||
2952 !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedCtor")) {
2955 g_assert_not_reached ();
2959 g_error ("got unexpected table 0x%02x in fixup", target [3]);
2961 target [0] = idx & 0xff;
2962 target [1] = (idx >> 8) & 0xff;
2963 target [2] = (idx >> 16) & 0xff;
2968 assembly_add_resource (MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
2970 MonoDynamicTable *table;
2974 char *b = blob_size;
2976 guint32 idx, offset;
2978 if (rsrc->filename) {
2979 name = mono_string_to_utf8 (rsrc->filename);
2980 sname = g_path_get_basename (name);
2982 table = &assembly->tables [MONO_TABLE_FILE];
2984 alloc_table (table, table->rows);
2985 values = table->values + table->next_idx * MONO_FILE_SIZE;
2986 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
2987 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
2990 mono_sha1_get_digest_from_file (name, hash);
2991 mono_metadata_encode_value (20, b, &b);
2992 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2993 mono_image_add_stream_data (&assembly->blob, hash, 20);
2995 idx = table->next_idx++;
2996 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3000 offset = mono_array_length (rsrc->data);
3001 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3002 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3003 offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3004 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3008 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3010 alloc_table (table, table->rows);
3011 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3012 values [MONO_MANIFEST_OFFSET] = offset;
3013 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3014 name = mono_string_to_utf8 (rsrc->name);
3015 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3017 values [MONO_MANIFEST_IMPLEMENTATION] = idx;
3022 set_version_from_string (MonoString *version, guint32 *values)
3024 gchar *ver, *p, *str;
3027 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3028 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3029 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3030 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3033 ver = str = mono_string_to_utf8 (version);
3034 for (i = 0; i < 4; ++i) {
3035 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3041 /* handle Revision and Build */
3051 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3055 char *b = blob_size;
3060 len = mono_array_length (pkey);
3061 mono_metadata_encode_value (len, b, &b);
3062 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3063 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3065 /* need to get the actual value from the key type... */
3066 assembly->strong_name_size = 128;
3067 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3073 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3074 * for the modulebuilder @moduleb.
3075 * At the end of the process, method and field tokens are fixed up and the
3076 * on-disk compressed metadata representation is created.
3079 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3081 MonoDynamicTable *table;
3082 MonoDynamicImage *assembly;
3083 MonoReflectionAssemblyBuilder *assemblyb;
3088 guint32 module_index;
3090 assemblyb = moduleb->assemblyb;
3091 assembly = moduleb->dynamic_image;
3092 domain = mono_object_domain (assemblyb);
3094 if (assembly->text_rva)
3097 assembly->text_rva = START_TEXT_RVA;
3099 if (moduleb->is_main) {
3100 /* Emit the manifest */
3101 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3102 alloc_table (table, 1);
3103 values = table->values + MONO_ASSEMBLY_SIZE;
3104 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3105 name = mono_string_to_utf8 (assemblyb->name);
3106 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3108 if (assemblyb->culture) {
3109 name = mono_string_to_utf8 (assemblyb->culture);
3110 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3113 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3115 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3116 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3117 set_version_from_string (assemblyb->version, values);
3119 /* Emit FILE + EXPORTED_TYPE table */
3121 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3123 MonoReflectionModuleBuilder *file_module =
3124 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3125 if (file_module != moduleb) {
3126 mono_image_fill_file_table (domain, file_module, assembly);
3128 if (file_module->types) {
3129 for (j = 0; j < mono_array_length (file_module->types); ++j) {
3130 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3131 mono_image_fill_export_table (domain, tb, module_index, 0,
3139 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3140 table->rows = 1; /* .<Module> */
3142 alloc_table (table, table->rows);
3144 * Set the first entry.
3146 values = table->values + table->columns;
3147 values [MONO_TYPEDEF_FLAGS] = 0;
3148 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3149 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3150 values [MONO_TYPEDEF_EXTENDS] = 0;
3151 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3152 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3155 * handle global methods
3156 * FIXME: test what to do when global methods are defined in multiple modules.
3158 if (moduleb->global_methods) {
3159 table = &assembly->tables [MONO_TABLE_METHOD];
3160 table->rows += mono_array_length (moduleb->global_methods);
3161 alloc_table (table, table->rows);
3162 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3163 mono_image_get_method_info (
3164 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3166 if (moduleb->global_fields) {
3167 table = &assembly->tables [MONO_TABLE_FIELD];
3168 table->rows += mono_array_length (moduleb->global_fields);
3169 alloc_table (table, table->rows);
3170 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3171 mono_image_get_field_info (
3172 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3175 table = &assembly->tables [MONO_TABLE_MODULE];
3176 alloc_table (table, 1);
3177 mono_image_fill_module_table (domain, moduleb, assembly);
3181 /* Collect all types into a list sorted by their table_idx */
3182 GPtrArray *types = g_ptr_array_new ();
3185 for (i = 0; i < mono_array_length (moduleb->types); ++i) {
3186 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3187 collect_types (types, type);
3190 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3191 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3192 table->rows += types->len;
3193 alloc_table (table, table->rows);
3195 for (i = 0; i < types->len; ++i) {
3196 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3197 mono_image_get_type_info (domain, type, assembly);
3199 g_ptr_array_free (types, TRUE);
3203 * table->rows is already set above and in mono_image_fill_module_table.
3205 /* add all the custom attributes at the end, once all the indexes are stable */
3206 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3208 module_add_cattrs (assembly, moduleb);
3211 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3215 * mono_image_insert_string:
3216 * @module: module builder object
3219 * Insert @str into the user string stream of @module.
3222 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3224 MonoDynamicImage *assembly;
3229 MONO_ARCH_SAVE_REGS;
3231 if (!module->dynamic_image)
3232 mono_image_module_basic_init (module);
3234 assembly = module->dynamic_image;
3236 if (assembly->save) {
3237 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3238 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3239 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3241 char *swapped = g_malloc (2 * mono_string_length (str));
3242 const char *p = (const char*)mono_string_chars (str);
3244 swap_with_size (swapped, p, 2, mono_string_length (str));
3245 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3249 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3251 mono_image_add_stream_data (&assembly->us, "", 1);
3254 idx = assembly->us.index ++;
3256 mono_g_hash_table_insert (assembly->tokens,
3257 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3259 return MONO_TOKEN_STRING | idx;
3263 * mono_image_create_token:
3264 * @assembly: a dynamic assembly
3267 * Get a token to insert in the IL code stream for the given MemberInfo.
3268 * @obj can be one of:
3269 * ConstructorBuilder
3279 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3284 klass = obj->vtable->klass;
3285 if (strcmp (klass->name, "MethodBuilder") == 0) {
3286 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3288 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3289 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3291 token = mono_image_get_methodbuilder_token (assembly, mb);
3292 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3294 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3295 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3297 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3298 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3300 token = mono_image_get_ctorbuilder_token (assembly, mb);
3301 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3303 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3304 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3305 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3306 if (tb->generic_params) {
3307 token = mono_image_get_generic_field_token (assembly, fb);
3309 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3312 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3313 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3314 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3316 else if (strcmp (klass->name, "MonoType") == 0) {
3317 MonoReflectionType *tb = (MonoReflectionType *)obj;
3318 token = mono_metadata_token_from_dor (
3319 mono_image_typedef_or_ref (assembly, tb->type));
3321 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3322 strcmp (klass->name, "MonoMethod") == 0) {
3323 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3324 if (m->method->signature->generic_param_count) {
3325 g_assert_not_reached ();
3326 token = mono_image_get_methodspec_token (assembly, m->method, NULL);
3327 } else if ((m->method->klass->image == &assembly->image) &&
3328 !m->method->klass->generic_inst) {
3329 static guint32 method_table_idx = 0xffffff;
3331 * Each token should have a unique index, but the indexes are
3332 * assigned by managed code, so we don't know about them. An
3333 * easy solution is to count backwards...
3335 method_table_idx --;
3336 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3338 token = mono_image_get_methodref_token (assembly, m->method);
3339 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3341 else if (strcmp (klass->name, "MonoInflatedMethod") == 0 ||
3342 strcmp (klass->name, "MonoInflatedCtor") == 0) {
3343 MonoReflectionInflatedMethod *m = (MonoReflectionInflatedMethod *)obj;
3344 token = mono_image_get_methodspec_token (assembly, m->rmethod.method, m->ginst);
3346 else if (strcmp (klass->name, "MonoInflatedField") == 0) {
3347 MonoReflectionInflatedField *f = (MonoReflectionInflatedField *)obj;
3348 token = mono_image_get_inflated_field_token (assembly, f);
3350 else if (strcmp (klass->name, "MonoField") == 0) {
3351 MonoReflectionField *f = (MonoReflectionField *)obj;
3352 if (f->klass->image == &assembly->image) {
3353 static guint32 field_table_idx = 0xffffff;
3355 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3357 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
3358 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3360 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
3361 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
3362 token = mono_image_get_array_token (assembly, m);
3364 else if (strcmp (klass->name, "SignatureHelper") == 0) {
3365 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
3366 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
3369 g_error ("requested token for %s\n", klass->name);
3371 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
3378 guint32 import_lookup_table;
3382 guint32 import_address_table_rva;
3390 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
3392 static MonoDynamicImage*
3393 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
3394 char *assembly_name, char *module_name)
3396 static const guchar entrycode [16] = {0xff, 0x25, 0};
3397 MonoDynamicImage *image;
3401 * We need to use the current ms version or the ms runtime it won't find
3402 * the support dlls. D'oh!
3403 * const char *version = "mono-" VERSION;
3405 const char *version = "v1.0.3705";
3408 image = GC_MALLOC (sizeof (MonoDynamicImage));
3410 image = g_new0 (MonoDynamicImage, 1);
3413 /* keep in sync with image.c */
3414 image->image.name = assembly_name;
3415 image->image.assembly_name = image->image.name; /* they may be different */
3416 image->image.module_name = module_name;
3417 image->image.version = g_strdup (version);
3419 image->image.references = g_new0 (MonoAssembly*, 1);
3420 image->image.references [0] = NULL;
3422 mono_image_init (&image->image);
3424 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
3425 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3426 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3427 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
3428 image->handleref = g_hash_table_new (NULL, NULL);
3429 image->tokens = mono_g_hash_table_new (NULL, NULL);
3430 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3431 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
3433 string_heap_init (&image->sheap);
3434 mono_image_add_stream_data (&image->us, "", 1);
3435 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
3436 /* import tables... */
3437 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
3438 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
3439 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
3440 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
3441 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
3442 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
3443 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
3444 stream_data_align (&image->code);
3446 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
3448 for (i=0; i < 64; ++i) {
3449 image->tables [i].next_idx = 1;
3450 image->tables [i].columns = table_sizes [i];
3453 image->image.assembly = (MonoAssembly*)assembly;
3454 image->run = assembly->run;
3455 image->save = assembly->save;
3461 * mono_image_basic_init:
3462 * @assembly: an assembly builder object
3464 * Create the MonoImage that represents the assembly builder and setup some
3465 * of the helper hash table and the basic metadata streams.
3468 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
3470 MonoDynamicAssembly *assembly;
3471 MonoDynamicImage *image;
3473 MONO_ARCH_SAVE_REGS;
3475 if (assemblyb->dynamic_assembly)
3479 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicImage));
3481 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
3484 assembly->assembly.dynamic = TRUE;
3485 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
3486 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
3487 if (assemblyb->culture)
3488 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
3490 assembly->assembly.aname.culture = g_strdup ("");
3492 assembly->run = assemblyb->access != 2;
3493 assembly->save = assemblyb->access != 1;
3495 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
3496 assembly->assembly.aname.name = image->image.name;
3497 assembly->assembly.image = &image->image;
3499 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
3500 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
3504 calc_section_size (MonoDynamicImage *assembly)
3508 /* alignment constraints */
3509 assembly->code.index += 3;
3510 assembly->code.index &= ~3;
3511 assembly->meta_size += 3;
3512 assembly->meta_size &= ~3;
3513 assembly->resources.index += 3;
3514 assembly->resources.index &= ~3;
3516 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
3517 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
3520 assembly->sections [MONO_SECTION_RELOC].size = 12;
3521 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
3528 * mono_image_create_pefile:
3529 * @mb: a module builder object
3531 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
3532 * assembly->pefile where it can be easily retrieved later in chunks.
3535 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
3536 MonoMSDOSHeader *msdos;
3537 MonoDotNetHeader *header;
3538 MonoSectionTable *section;
3539 MonoCLIHeader *cli_header;
3540 guint32 size, image_size, virtual_base, text_offset;
3541 guint32 header_start, section_start, file_offset, virtual_offset;
3542 MonoDynamicImage *assembly;
3543 MonoReflectionAssemblyBuilder *assemblyb;
3544 MonoDynamicStream *pefile;
3546 guint32 *rva, value;
3549 static const unsigned char msheader[] = {
3550 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
3551 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
3554 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
3555 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
3556 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
3557 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3560 assemblyb = mb->assemblyb;
3562 mono_image_basic_init (assemblyb);
3563 assembly = mb->dynamic_image;
3565 /* already created */
3566 if (assembly->pefile.index)
3569 mono_image_build_metadata (mb);
3571 if (assemblyb->resources) {
3572 int len = mono_array_length (assemblyb->resources);
3573 for (i = 0; i < len; ++i)
3574 assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
3578 build_compressed_metadata (assembly);
3580 nsections = calc_section_size (assembly);
3582 pefile = &assembly->pefile;
3584 /* The DOS header and stub */
3585 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
3586 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
3588 /* the dotnet header */
3589 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
3591 /* the section tables */
3592 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
3594 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
3595 virtual_offset = VIRT_ALIGN;
3598 for (i = 0; i < MONO_SECTION_MAX; ++i) {
3599 if (!assembly->sections [i].size)
3602 file_offset += FILE_ALIGN - 1;
3603 file_offset &= ~(FILE_ALIGN - 1);
3604 virtual_offset += VIRT_ALIGN - 1;
3605 virtual_offset &= ~(VIRT_ALIGN - 1);
3607 assembly->sections [i].offset = file_offset;
3608 assembly->sections [i].rva = virtual_offset;
3610 file_offset += assembly->sections [i].size;
3611 virtual_offset += assembly->sections [i].size;
3612 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
3615 file_offset += FILE_ALIGN - 1;
3616 file_offset &= ~(FILE_ALIGN - 1);
3617 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
3619 image_size += section_start + sizeof (MonoSectionTable) * nsections;
3621 /* back-patch info */
3622 msdos = (MonoMSDOSHeader*)pefile->data;
3623 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
3624 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
3625 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
3627 header = (MonoDotNetHeader*)(pefile->data + header_start);
3628 header->pesig [0] = 'P';
3629 header->pesig [1] = 'E';
3631 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
3632 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
3633 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
3634 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
3635 if (assemblyb->pekind == 1) {
3637 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
3640 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
3643 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
3645 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
3646 header->pe.pe_major = 6;
3647 header->pe.pe_minor = 0;
3648 size = assembly->sections [MONO_SECTION_TEXT].size;
3649 size += FILE_ALIGN - 1;
3650 size &= ~(FILE_ALIGN - 1);
3651 header->pe.pe_code_size = GUINT32_FROM_LE(size);
3652 size = assembly->sections [MONO_SECTION_RSRC].size;
3653 size += FILE_ALIGN - 1;
3654 size &= ~(FILE_ALIGN - 1);
3655 header->pe.pe_data_size = GUINT32_FROM_LE(size);
3656 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
3657 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
3658 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
3659 /* pe_rva_entry_point always at the beginning of the text section */
3660 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
3662 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
3663 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
3664 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
3665 header->nt.pe_os_major = GUINT16_FROM_LE (4);
3666 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
3667 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
3668 size = section_start;
3669 size += FILE_ALIGN - 1;
3670 size &= ~(FILE_ALIGN - 1);
3671 header->nt.pe_header_size = GUINT32_FROM_LE (size);
3673 size += VIRT_ALIGN - 1;
3674 size &= ~(VIRT_ALIGN - 1);
3675 header->nt.pe_image_size = GUINT32_FROM_LE (size);
3678 // Translate the PEFileKind value to the value expected by the Windows loader
3681 short kind = assemblyb->pekind;
3684 // PEFileKinds.ConsoleApplication == 2
3685 // PEFileKinds.WindowApplication == 3
3688 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
3689 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
3695 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
3697 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
3698 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
3699 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
3700 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
3701 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
3702 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
3704 /* fill data directory entries */
3706 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
3707 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
3709 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
3710 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
3712 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
3713 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
3714 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
3715 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
3716 /* patch imported function RVA name */
3717 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
3718 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
3720 /* the import table */
3721 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
3722 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
3723 /* patch imported dll RVA name and other entries in the dir */
3724 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
3725 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
3726 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
3727 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
3728 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
3729 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
3731 p = (assembly->code.data + assembly->ilt_offset);
3732 value = (assembly->text_rva + assembly->imp_names_offset - 2);
3733 *p++ = (value) & 0xff;
3734 *p++ = (value >> 8) & (0xff);
3735 *p++ = (value >> 16) & (0xff);
3736 *p++ = (value >> 24) & (0xff);
3738 /* the CLI header info */
3739 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
3740 cli_header->ch_size = GUINT32_FROM_LE (72);
3741 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
3742 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
3743 if (assemblyb->entry_point)
3744 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
3746 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
3747 /* The embedded managed resources */
3748 text_offset = assembly->text_rva + assembly->code.index;
3749 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
3750 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
3751 text_offset += assembly->resources.index;
3752 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
3753 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
3754 text_offset += assembly->meta_size;
3755 if (assembly->strong_name_size) {
3756 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
3757 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
3758 text_offset += assembly->strong_name_size;
3761 /* write the section tables and section content */
3762 section = (MonoSectionTable*)(pefile->data + section_start);
3763 for (i = 0; i < MONO_SECTION_MAX; ++i) {
3764 static const char *section_names [] = {
3765 ".text", ".rsrc", ".reloc"
3767 if (!assembly->sections [i].size)
3769 strcpy (section->st_name, section_names [i]);
3770 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
3771 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
3772 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
3773 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
3774 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
3775 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
3776 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
3778 case MONO_SECTION_TEXT:
3779 /* patch entry point */
3780 p = (assembly->code.data + 2);
3781 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
3782 *p++ = (value) & 0xff;
3783 *p++ = (value >> 8) & 0xff;
3784 *p++ = (value >> 16) & 0xff;
3785 *p++ = (value >> 24) & 0xff;
3787 text_offset = assembly->sections [i].offset;
3788 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
3789 text_offset += assembly->code.index;
3790 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
3791 text_offset += assembly->resources.index;
3792 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
3793 text_offset += assembly->meta_size;
3794 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
3796 g_free (assembly->image.raw_metadata);
3798 case MONO_SECTION_RELOC:
3799 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
3800 *rva = GUINT32_FROM_LE (assembly->text_rva);
3802 *rva = GUINT32_FROM_LE (12);
3804 data16 = (guint16*)rva;
3806 * the entrypoint is always at the start of the text section
3807 * 3 is IMAGE_REL_BASED_HIGHLOW
3808 * 2 is patch_size_rva - text_rva
3810 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
3812 *data16 = 0; /* terminate */
3814 case MONO_SECTION_RSRC:
3816 g_assert_not_reached ();
3821 /* check that the file is properly padded */
3824 FILE *f = fopen ("mypetest.exe", "w");
3825 fwrite (pefile->data, pefile->index, 1, f);
3832 * We need to return always the same object for MethodInfo, FieldInfo etc..
3833 * but we need to consider the reflected type.
3834 * type uses a different hash, since it uses custom hash/equal functions.
3839 MonoClass *refclass;
3843 reflected_equal (gconstpointer a, gconstpointer b) {
3844 const ReflectedEntry *ea = a;
3845 const ReflectedEntry *eb = b;
3847 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
3851 reflected_hash (gconstpointer a) {
3852 const ReflectedEntry *ea = a;
3853 return GPOINTER_TO_UINT (ea->item);
3856 #define CHECK_OBJECT(t,p,k) \
3862 mono_domain_lock (domain); \
3863 if (!domain->refobject_hash) \
3864 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
3865 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
3866 mono_domain_unlock (domain); \
3872 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
3874 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
3877 #define CACHE_OBJECT(p,o,k) \
3879 ReflectedEntry *e = ALLOC_REFENTRY; \
3881 e->refclass = (k); \
3882 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
3883 mono_domain_unlock (domain); \
3887 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
3889 /* this is done only once */
3890 mono_domain_lock (domain);
3891 CACHE_OBJECT (assembly, res, NULL);
3895 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
3897 /* this is done only once */
3898 mono_domain_lock (domain);
3899 CACHE_OBJECT (module, res, NULL);
3903 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
3905 MonoDynamicImage *image = moduleb->dynamic_image;
3906 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
3909 * FIXME: we already created an image in mono_image_basic_init (), but
3910 * we don't know which module it belongs to, since that is only
3911 * determined at assembly save time.
3913 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
3914 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
3916 moduleb->module.image = &image->image;
3917 moduleb->dynamic_image = image;
3918 register_module (mono_object_domain (moduleb), moduleb, image);
3923 * mono_assembly_get_object:
3924 * @domain: an app domain
3925 * @assembly: an assembly
3927 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
3929 MonoReflectionAssembly*
3930 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
3932 static MonoClass *System_Reflection_Assembly;
3933 MonoReflectionAssembly *res;
3935 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
3936 if (!System_Reflection_Assembly)
3937 System_Reflection_Assembly = mono_class_from_name (
3938 mono_defaults.corlib, "System.Reflection", "Assembly");
3939 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
3940 res->assembly = assembly;
3941 CACHE_OBJECT (assembly, res, NULL);
3947 MonoReflectionModule*
3948 mono_module_get_object (MonoDomain *domain, MonoImage *image)
3950 static MonoClass *System_Reflection_Module;
3951 MonoReflectionModule *res;
3953 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
3954 if (!System_Reflection_Module)
3955 System_Reflection_Module = mono_class_from_name (
3956 mono_defaults.corlib, "System.Reflection", "Module");
3957 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
3960 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
3962 res->fqname = mono_string_new (domain, image->name);
3963 res->name = mono_string_new (domain, image->name);
3964 res->scopename = mono_string_new (domain, image->module_name);
3966 CACHE_OBJECT (image, res, NULL);
3970 MonoReflectionModule*
3971 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
3973 static MonoClass *System_Reflection_Module;
3974 MonoReflectionModule *res;
3975 MonoTableInfo *table;
3976 guint32 cols [MONO_FILE_SIZE];
3978 guint32 i, name_idx;
3981 if (!System_Reflection_Module)
3982 System_Reflection_Module = mono_class_from_name (
3983 mono_defaults.corlib, "System.Reflection", "Module");
3984 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
3986 table = &image->tables [MONO_TABLE_FILE];
3987 g_assert (table_index < table->rows);
3988 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
3991 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
3992 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
3994 // Check whenever the row has a corresponding row in the moduleref table
3995 table = &image->tables [MONO_TABLE_MODULEREF];
3996 for (i = 0; i < table->rows; ++i) {
3997 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
3998 val = mono_metadata_string_heap (image, name_idx);
3999 if (strcmp (val, name) == 0)
4000 res->image = image->modules [i];
4003 res->fqname = mono_string_new (domain, name);
4004 res->name = mono_string_new (domain, name);
4005 res->scopename = mono_string_new (domain, name);
4006 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4012 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4014 if ((t1->type != t2->type) ||
4015 (t1->byref != t2->byref))
4019 case MONO_TYPE_VOID:
4020 case MONO_TYPE_BOOLEAN:
4021 case MONO_TYPE_CHAR:
4032 case MONO_TYPE_STRING:
4035 case MONO_TYPE_OBJECT:
4036 case MONO_TYPE_TYPEDBYREF:
4038 case MONO_TYPE_VALUETYPE:
4039 case MONO_TYPE_CLASS:
4040 case MONO_TYPE_SZARRAY:
4041 return t1->data.klass == t2->data.klass;
4043 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4044 case MONO_TYPE_ARRAY:
4045 if (t1->data.array->rank != t2->data.array->rank)
4047 return t1->data.array->eklass == t2->data.array->eklass;
4048 case MONO_TYPE_GENERICINST: {
4050 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4052 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4054 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4055 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4061 case MONO_TYPE_MVAR:
4062 return t1->data.generic_param == t2->data.generic_param;
4064 g_error ("implement type compare for %0x!", t1->type);
4072 mymono_metadata_type_hash (MonoType *t1)
4078 hash |= t1->byref << 6; /* do not collide with t1->type values */
4080 case MONO_TYPE_VALUETYPE:
4081 case MONO_TYPE_CLASS:
4082 case MONO_TYPE_SZARRAY:
4083 /* check if the distribution is good enough */
4084 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
4086 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
4092 * mono_type_get_object:
4093 * @domain: an app domain
4096 * Return an System.MonoType object representing the type @type.
4099 mono_type_get_object (MonoDomain *domain, MonoType *type)
4101 MonoReflectionType *res;
4102 MonoClass *klass = mono_class_from_mono_type (type);
4104 mono_domain_lock (domain);
4105 if (!domain->type_hash)
4106 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
4107 (GCompareFunc)mymono_metadata_type_equal);
4108 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
4109 mono_domain_unlock (domain);
4112 if (klass->reflection_info && !klass->wastypebuilder) {
4113 //g_assert_not_reached ();
4114 /* should this be considered an error condition? */
4116 mono_domain_unlock (domain);
4117 return klass->reflection_info;
4120 mono_class_init (klass);
4121 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
4123 mono_g_hash_table_insert (domain->type_hash, type, res);
4124 mono_domain_unlock (domain);
4129 * mono_method_get_object:
4130 * @domain: an app domain
4132 * @refclass: the reflected type (can be NULL)
4134 * Return an System.Reflection.MonoMethod object representing the method @method.
4136 MonoReflectionMethod*
4137 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
4140 * We use the same C representation for methods and constructors, but the type
4141 * name in C# is different.
4145 MonoReflectionMethod *ret;
4148 refclass = method->klass;
4150 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
4151 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
4152 cname = "MonoCMethod";
4154 cname = "MonoMethod";
4155 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
4157 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
4158 ret->method = method;
4159 ret->name = mono_string_new (domain, method->name);
4160 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
4161 CACHE_OBJECT (method, ret, refclass);
4166 * mono_field_get_object:
4167 * @domain: an app domain
4171 * Return an System.Reflection.MonoField object representing the field @field
4174 MonoReflectionField*
4175 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
4177 MonoReflectionField *res;
4180 CHECK_OBJECT (MonoReflectionField *, field, klass);
4181 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
4182 res = (MonoReflectionField *)mono_object_new (domain, oklass);
4185 res->name = mono_string_new (domain, field->name);
4186 res->attrs = field->type->attrs;
4187 res->type = mono_type_get_object (domain, field->type);
4188 CACHE_OBJECT (field, res, klass);
4193 * mono_property_get_object:
4194 * @domain: an app domain
4196 * @property: a property
4198 * Return an System.Reflection.MonoProperty object representing the property @property
4201 MonoReflectionProperty*
4202 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
4204 MonoReflectionProperty *res;
4207 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
4208 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
4209 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
4211 res->property = property;
4212 CACHE_OBJECT (property, res, klass);
4217 * mono_event_get_object:
4218 * @domain: an app domain
4222 * Return an System.Reflection.MonoEvent object representing the event @event
4225 MonoReflectionEvent*
4226 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
4228 MonoReflectionEvent *res;
4231 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
4232 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
4233 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
4236 CACHE_OBJECT (event, res, klass);
4241 * mono_param_get_objects:
4242 * @domain: an app domain
4245 * Return an System.Reflection.ParameterInfo array object representing the parameters
4246 * in the method @method.
4249 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
4251 static MonoClass *System_Reflection_ParameterInfo;
4252 MonoArray *res = NULL;
4253 MonoReflectionMethod *member = NULL;
4254 MonoReflectionParameter *param = NULL;
4258 if (!System_Reflection_ParameterInfo)
4259 System_Reflection_ParameterInfo = mono_class_from_name (
4260 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
4262 if (!method->signature->param_count)
4263 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
4265 /* Note: the cache is based on the address of the signature into the method
4266 * since we already cache MethodInfos with the method as keys.
4268 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
4270 member = mono_method_get_object (domain, method, NULL);
4271 names = g_new (char *, method->signature->param_count);
4272 mono_method_get_param_names (method, (const char **) names);
4274 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
4275 for (i = 0; i < method->signature->param_count; ++i) {
4276 param = (MonoReflectionParameter *)mono_object_new (domain,
4277 System_Reflection_ParameterInfo);
4278 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
4279 param->DefaultValueImpl = NULL; /* FIXME */
4280 param->MemberImpl = (MonoObject*)member;
4281 param->NameImpl = mono_string_new (domain, names [i]);
4282 param->PositionImpl = i;
4283 param->AttrsImpl = method->signature->params [i]->attrs;
4284 mono_array_set (res, gpointer, i, param);
4287 CACHE_OBJECT (&(method->signature), res, NULL);
4292 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
4296 memset (assembly, 0, sizeof (MonoAssemblyName));
4298 assembly->culture = "";
4300 while (*p && (isalnum (*p) || *p == '.' || *p == '-'))
4303 while (*p == ' ' || *p == ',') {
4312 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
4314 assembly->major = strtoul (p, &s, 10);
4315 if (s == p || *s != '.')
4318 assembly->minor = strtoul (p, &s, 10);
4319 if (s == p || *s != '.')
4322 assembly->build = strtoul (p, &s, 10);
4323 if (s == p || *s != '.')
4326 assembly->revision = strtoul (p, &s, 10);
4329 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
4331 if (strncmp (p, "neutral", 7) == 0) {
4332 assembly->culture = "";
4335 assembly->culture = p;
4336 while (*p && *p != ',') {
4340 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
4343 while (*s && isxdigit (*s)) {
4347 assembly->hash_len = s - p;
4348 if (!(s-p) || ((s-p) & 1))
4350 assembly->hash_value = s = p;
4351 while (*s && isxdigit (*s)) {
4353 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
4356 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
4361 while (*p && *p != ',')
4365 while (*p == ' ' || *p == ',') {
4379 * mono_reflection_parse_type:
4382 * Parse a type name as accepted by the GetType () method and output the info
4383 * extracted in the info structure.
4384 * the name param will be mangled, so, make a copy before passing it to this function.
4385 * The fields in info will be valid until the memory pointed to by name is valid.
4386 * Returns 0 on parse error.
4387 * See also mono_type_get_name () below.
4390 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
4392 char *start, *p, *w, *last_point, *startn;
4393 int in_modifiers = 0;
4394 int isbyref = 0, rank;
4396 start = p = w = name;
4398 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
4399 info->name = info->name_space = NULL;
4400 info->nested = NULL;
4401 info->modifiers = NULL;
4403 /* last_point separates the namespace from the name */
4409 *p = 0; /* NULL terminate the name */
4411 info->nested = g_list_append (info->nested, startn);
4412 /* we have parsed the nesting namespace + name */
4416 info->name_space = start;
4418 info->name = last_point + 1;
4420 info->name_space = (char *)"";
4446 info->name_space = start;
4448 info->name = last_point + 1;
4450 info->name_space = (char *)"";
4457 if (isbyref) /* only one level allowed by the spec */
4460 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
4464 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
4475 else if (*p != '*') /* '*' means unknown lower bound */
4481 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
4493 return 0; /* missing assembly name */
4494 if (!assembly_name_to_aname (&info->assembly, p))
4501 if (info->assembly.name)
4504 *w = 0; /* terminate class name */
4505 if (!info->name || !*info->name)
4507 /* add other consistency checks */
4512 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
4519 image = mono_defaults.corlib;
4522 klass = mono_class_from_name_case (image, info->name_space, info->name);
4524 klass = mono_class_from_name (image, info->name_space, info->name);
4527 for (mod = info->nested; mod; mod = mod->next) {
4530 mono_class_init (klass);
4531 nested = klass->nested_classes;
4534 klass = nested->data;
4536 if (g_strcasecmp (klass->name, mod->data) == 0)
4539 if (strcmp (klass->name, mod->data) == 0)
4543 nested = nested->next;
4550 mono_class_init (klass);
4551 for (mod = info->modifiers; mod; mod = mod->next) {
4552 modval = GPOINTER_TO_UINT (mod->data);
4553 if (!modval) { /* byref: must be last modifier */
4554 return &klass->this_arg;
4555 } else if (modval == -1) {
4556 klass = mono_ptr_class_get (&klass->byval_arg);
4557 } else { /* array rank */
4558 klass = mono_array_class_get (klass, modval);
4560 mono_class_init (klass);
4563 return &klass->byval_arg;
4567 * mono_reflection_get_type:
4568 * @image: a metadata context
4569 * @info: type description structure
4570 * @ignorecase: flag for case-insensitive string compares
4572 * Build a MonoType from the type description in @info.
4577 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
4580 MonoReflectionAssembly *assembly;
4584 type = mono_reflection_get_type_internal (image, info, ignorecase);
4587 if (!mono_domain_has_type_resolve (mono_domain_get ()))
4590 // Reconstruct the type name
4591 fullName = g_string_new ("");
4592 if (info->name_space && (info->name_space [0] != '\0'))
4593 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
4595 g_string_printf (fullName, info->name);
4596 for (mod = info->nested; mod; mod = mod->next)
4597 g_string_append_printf (fullName, "+%s", (char*)mod->data);
4600 mono_domain_try_type_resolve (
4601 mono_domain_get (), fullName->str, NULL);
4602 if (assembly && (!image || (assembly->assembly->image == image)))
4603 type = mono_reflection_get_type_internal (assembly->assembly->image,
4605 g_string_free (fullName, TRUE);
4610 * mono_reflection_type_from_name:
4612 * @image: a metadata context (can be NULL).
4614 * Retrieves a MonoType from its @name. If the name is not fully qualified,
4615 * it defaults to get the type from @image or, if @image is NULL or loading
4616 * from it fails, uses corlib.
4620 mono_reflection_type_from_name (char *name, MonoImage *image)
4623 MonoTypeNameParse info;
4625 /*g_print ("requested type %s\n", str);*/
4626 if (!mono_reflection_parse_type (name, &info)) {
4627 g_list_free (info.modifiers);
4628 g_list_free (info.nested);
4632 if (info.assembly.name) {
4633 image = mono_image_loaded (info.assembly.name);
4634 /* do we need to load if it's not already loaded? */
4636 g_list_free (info.modifiers);
4637 g_list_free (info.nested);
4640 } else if (image == NULL) {
4641 image = mono_defaults.corlib;
4644 type = mono_reflection_get_type (image, &info, FALSE);
4645 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
4646 image = mono_defaults.corlib;
4647 type = mono_reflection_get_type (image, &info, FALSE);
4650 g_list_free (info.modifiers);
4651 g_list_free (info.nested);
4656 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
4658 int slen, type = t->type;
4663 case MONO_TYPE_BOOLEAN: {
4664 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
4669 case MONO_TYPE_CHAR:
4671 case MONO_TYPE_I2: {
4672 guint16 *val = g_malloc (sizeof (guint16));
4677 #if SIZEOF_VOID_P == 4
4683 case MONO_TYPE_I4: {
4684 guint32 *val = g_malloc (sizeof (guint32));
4689 #if SIZEOF_VOID_P == 8
4690 case MONO_TYPE_U: /* error out instead? this should probably not happen */
4695 case MONO_TYPE_I8: {
4696 guint64 *val = g_malloc (sizeof (guint64));
4701 case MONO_TYPE_VALUETYPE:
4702 if (t->data.klass->enumtype) {
4703 type = t->data.klass->enum_basetype->type;
4706 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
4709 case MONO_TYPE_STRING:
4710 if (*p == (char)0xFF) {
4714 slen = mono_metadata_decode_value (p, &p);
4716 return mono_string_new_len (mono_domain_get (), p, slen);
4717 case MONO_TYPE_CLASS: {
4720 if (*p == (char)0xFF) {
4725 slen = mono_metadata_decode_value (p, &p);
4726 n = g_memdup (p, slen + 1);
4728 t = mono_reflection_type_from_name (n, image);
4730 g_warning ("Cannot load type '%s'", n);
4733 return mono_type_get_object (mono_domain_get (), t);
4735 case MONO_TYPE_OBJECT: {
4743 } else if (subt == 0x0E) {
4744 type = MONO_TYPE_STRING;
4746 } else if (subt == 0x55) {
4749 slen = mono_metadata_decode_value (p, &p);
4750 n = g_memdup (p, slen + 1);
4752 t = mono_reflection_type_from_name (n, image);
4754 g_warning ("Cannot load type '%s'", n);
4757 subc = mono_class_from_mono_type (t);
4758 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
4759 MonoType simple_type = {{0}};
4760 simple_type.type = subt;
4761 subc = mono_class_from_mono_type (&simple_type);
4763 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
4765 val = load_cattr_value (image, &subc->byval_arg, p, end);
4766 obj = mono_object_new (mono_domain_get (), subc);
4767 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
4771 case MONO_TYPE_SZARRAY:
4774 guint32 i, alen, basetype;
4777 if (alen == 0xffffffff) {
4781 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
4782 basetype = t->data.klass->byval_arg.type;
4787 case MONO_TYPE_BOOLEAN:
4788 for (i=0;i<alen;i++)
4790 MonoBoolean val=*p++;
4791 mono_array_set(arr,MonoBoolean,i,val);
4794 case MONO_TYPE_CHAR:
4797 for (i=0;i<alen;i++)
4799 guint16 val=read16(p);
4800 mono_array_set(arr,guint16,i,val);
4807 for (i=0;i<alen;i++)
4809 guint32 val=read32(p);
4810 mono_array_set(arr,guint32,i,val);
4817 for (i=0;i<alen;i++)
4819 guint64 val=read64(p);
4820 mono_array_set(arr,guint64,i,val);
4824 case MONO_TYPE_CLASS:
4825 case MONO_TYPE_STRING:
4826 for (i = 0; i < alen; i++) {
4827 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
4828 mono_array_set (arr, gpointer, i, item);
4832 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
4838 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
4844 type_is_reference (MonoType *type)
4846 switch (type->type) {
4847 case MONO_TYPE_BOOLEAN:
4848 case MONO_TYPE_CHAR:
4861 case MONO_TYPE_VALUETYPE:
4869 free_param_data (MonoMethodSignature *sig, void **params) {
4871 for (i = 0; i < sig->param_count; ++i) {
4872 if (!type_is_reference (sig->params [i]))
4873 g_free (params [i]);
4878 * Find the method index in the metadata methodDef table.
4879 * Later put these three helper methods in metadata and export them.
4882 find_method_index (MonoMethod *method) {
4883 MonoClass *klass = method->klass;
4886 for (i = 0; i < klass->method.count; ++i) {
4887 if (method == klass->methods [i])
4888 return klass->method.first + 1 + i;
4894 * Find the field index in the metadata FieldDef table.
4897 find_field_index (MonoClass *klass, MonoClassField *field) {
4900 for (i = 0; i < klass->field.count; ++i) {
4901 if (field == &klass->fields [i])
4902 return klass->field.first + 1 + i;
4908 * Find the property index in the metadata Property table.
4911 find_property_index (MonoClass *klass, MonoProperty *property) {
4914 for (i = 0; i < klass->property.count; ++i) {
4915 if (property == &klass->properties [i])
4916 return klass->property.first + 1 + i;
4922 * Find the event index in the metadata Event table.
4925 find_event_index (MonoClass *klass, MonoEvent *event) {
4928 for (i = 0; i < klass->event.count; ++i) {
4929 if (event == &klass->events [i])
4930 return klass->event.first + 1 + i;
4936 create_custom_attr (MonoImage *image, MonoMethod *method,
4937 const char *data, guint32 len)
4939 const char *p = data;
4941 guint32 i, j, num_named;
4945 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
4948 mono_class_init (method->klass);
4949 /*g_print ("got attr %s\n", method->klass->name);*/
4951 params = g_new (void*, method->signature->param_count);
4955 for (i = 0; i < method->signature->param_count; ++i) {
4956 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
4960 attr = mono_object_new (mono_domain_get (), method->klass);
4961 mono_runtime_invoke (method, attr, params, NULL);
4962 free_param_data (method->signature, params);
4964 num_named = read16 (named);
4966 for (j = 0; j < num_named; j++) {
4968 char *name, named_type, data_type;
4969 named_type = *named++;
4970 data_type = *named++; /* type of data */
4971 if (data_type == 0x55) {
4974 type_len = mono_metadata_decode_blob_size (named, &named);
4975 type_name = g_malloc (type_len + 1);
4976 memcpy (type_name, named, type_len);
4977 type_name [type_len] = 0;
4979 /* FIXME: lookup the type and check type consistency */
4981 name_len = mono_metadata_decode_blob_size (named, &named);
4982 name = g_malloc (name_len + 1);
4983 memcpy (name, named, name_len);
4984 name [name_len] = 0;
4986 if (named_type == 0x53) {
4987 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
4988 void *val = load_cattr_value (image, field->type, named, &named);
4989 mono_field_set_value (attr, field, val);
4990 if (!type_is_reference (field->type))
4992 } else if (named_type == 0x54) {
4995 MonoType *prop_type;
4997 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
4998 /* can we have more that 1 arg in a custom attr named property? */
4999 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
5000 pparams [0] = load_cattr_value (image, prop_type, named, &named);
5001 mono_property_set_value (prop, attr, pparams, NULL);
5002 if (!type_is_reference (prop_type))
5003 g_free (pparams [0]);
5012 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
5019 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5020 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
5021 for (i = 0; i < cinfo->num_attrs; ++i) {
5022 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
5023 mono_array_set (result, gpointer, i, attr);
5029 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
5031 guint32 mtoken, i, len;
5032 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
5034 MonoCustomAttrInfo *ainfo;
5035 GList *tmp, *list = NULL;
5038 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
5040 i = mono_metadata_custom_attrs_from_index (image, idx);
5044 while (i < ca->rows) {
5045 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
5047 list = g_list_prepend (list, GUINT_TO_POINTER (i));
5050 len = g_list_length (list);
5053 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
5054 ainfo->num_attrs = len;
5055 ainfo->image = image;
5056 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
5057 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
5058 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
5059 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
5060 case CUSTOM_ATTR_TYPE_METHODDEF:
5061 mtoken |= MONO_TOKEN_METHOD_DEF;
5063 case CUSTOM_ATTR_TYPE_MEMBERREF:
5064 mtoken |= MONO_TOKEN_MEMBER_REF;
5067 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
5070 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
5071 if (!ainfo->attrs [i].ctor)
5072 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
5073 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
5074 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
5075 ainfo->attrs [i].data = data;
5083 mono_custom_attrs_from_method (MonoMethod *method)
5085 MonoCustomAttrInfo *cinfo;
5088 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
5090 idx = find_method_index (method);
5091 idx <<= CUSTOM_ATTR_BITS;
5092 idx |= CUSTOM_ATTR_METHODDEF;
5093 return mono_custom_attrs_from_index (method->klass->image, idx);
5097 mono_custom_attrs_from_class (MonoClass *klass)
5099 MonoCustomAttrInfo *cinfo;
5102 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
5104 idx = mono_metadata_token_index (klass->type_token);
5105 idx <<= CUSTOM_ATTR_BITS;
5106 idx |= CUSTOM_ATTR_TYPEDEF;
5107 return mono_custom_attrs_from_index (klass->image, idx);
5111 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
5113 MonoCustomAttrInfo *cinfo;
5116 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
5118 idx = 1; /* there is only one assembly */
5119 idx <<= CUSTOM_ATTR_BITS;
5120 idx |= CUSTOM_ATTR_ASSEMBLY;
5121 return mono_custom_attrs_from_index (assembly->image, idx);
5125 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
5127 MonoCustomAttrInfo *cinfo;
5130 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
5132 idx = find_property_index (klass, property);
5133 idx <<= CUSTOM_ATTR_BITS;
5134 idx |= CUSTOM_ATTR_PROPERTY;
5135 return mono_custom_attrs_from_index (klass->image, idx);
5139 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
5141 MonoCustomAttrInfo *cinfo;
5144 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
5146 idx = find_event_index (klass, event);
5147 idx <<= CUSTOM_ATTR_BITS;
5148 idx |= CUSTOM_ATTR_EVENT;
5149 return mono_custom_attrs_from_index (klass->image, idx);
5153 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
5155 MonoCustomAttrInfo *cinfo;
5158 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
5160 idx = find_field_index (klass, field);
5161 idx <<= CUSTOM_ATTR_BITS;
5162 idx |= CUSTOM_ATTR_FIELDDEF;
5163 return mono_custom_attrs_from_index (klass->image, idx);
5167 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
5170 guint32 i, idx, method_index;
5171 guint32 param_list, param_last, param_pos, found;
5174 /* FIXME: handle dynamic custom attrs for parameters */
5175 /*if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
5177 image = method->klass->image;
5178 method_index = find_method_index (method);
5179 ca = &image->tables [MONO_TABLE_METHOD];
5181 if (method->klass->generic_inst || method->klass->gen_params ||
5182 method->signature->generic_param_count) {
5183 // FIXME FIXME FIXME
5187 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
5188 if (method_index == ca->rows) {
5189 ca = &image->tables [MONO_TABLE_PARAM];
5190 param_last = ca->rows + 1;
5192 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
5193 ca = &image->tables [MONO_TABLE_PARAM];
5196 for (i = param_list; i < param_last; ++i) {
5197 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
5198 if (param_pos == param) {
5206 idx <<= CUSTOM_ATTR_BITS;
5207 idx |= CUSTOM_ATTR_PARAMDEF;
5208 return mono_custom_attrs_from_index (image, idx);
5212 * mono_reflection_get_custom_attrs:
5213 * @obj: a reflection object handle
5215 * Return an array with all the custom attributes defined of the
5216 * reflection handle @obj. The objects are fully build.
5219 mono_reflection_get_custom_attrs (MonoObject *obj)
5223 MonoCustomAttrInfo *cinfo;
5225 MONO_ARCH_SAVE_REGS;
5227 klass = obj->vtable->klass;
5228 /* FIXME: need to handle: Module */
5229 if (klass == mono_defaults.monotype_class) {
5230 MonoReflectionType *rtype = (MonoReflectionType*)obj;
5231 klass = mono_class_from_mono_type (rtype->type);
5232 cinfo = mono_custom_attrs_from_class (klass);
5233 } else if (strcmp ("Assembly", klass->name) == 0) {
5234 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
5235 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
5236 } else if (strcmp ("MonoProperty", klass->name) == 0) {
5237 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
5238 cinfo = mono_custom_attrs_from_property (rprop->klass, rprop->property);
5239 } else if (strcmp ("MonoEvent", klass->name) == 0) {
5240 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
5241 cinfo = mono_custom_attrs_from_event (revent->klass, revent->event);
5242 } else if (strcmp ("MonoField", klass->name) == 0) {
5243 MonoReflectionField *rfield = (MonoReflectionField*)obj;
5244 cinfo = mono_custom_attrs_from_field (rfield->klass, rfield->field);
5245 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
5246 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
5247 cinfo = mono_custom_attrs_from_method (rmethod->method);
5248 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
5249 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
5250 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
5251 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
5252 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
5253 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
5254 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
5255 } else { /* handle other types here... */
5256 g_error ("get custom attrs not yet supported for %s", klass->name);
5260 result = mono_custom_attrs_construct (cinfo);
5262 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5263 result = mono_array_new (mono_domain_get (), klass, 0);
5269 static MonoMethodSignature*
5270 parameters_to_signature (MonoArray *parameters) {
5271 MonoMethodSignature *sig;
5274 count = parameters? mono_array_length (parameters): 0;
5276 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
5277 sig->param_count = count;
5278 sig->sentinelpos = -1; /* FIXME */
5279 for (i = 0; i < count; ++i) {
5280 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
5281 sig->params [i] = pt->type;
5286 static MonoMethodSignature*
5287 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
5288 MonoMethodSignature *sig;
5290 sig = parameters_to_signature (ctor->parameters);
5291 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
5292 sig->ret = &mono_defaults.void_class->byval_arg;
5296 static MonoMethodSignature*
5297 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
5298 MonoMethodSignature *sig;
5300 sig = parameters_to_signature (method->parameters);
5301 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
5302 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
5303 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
5308 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
5310 MonoClass *klass = mono_object_class (prop);
5311 if (strcmp (klass->name, "PropertyBuilder") == 0) {
5312 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
5313 *name = mono_string_to_utf8 (pb->name);
5314 *type = pb->type->type;
5316 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
5317 *name = g_strdup (p->property->name);
5318 if (p->property->get)
5319 *type = p->property->get->signature->ret;
5321 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
5326 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
5328 MonoClass *klass = mono_object_class (field);
5329 if (strcmp (klass->name, "FieldBuilder") == 0) {
5330 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
5331 *name = mono_string_to_utf8 (fb->name);
5332 *type = fb->type->type;
5334 MonoReflectionField *f = (MonoReflectionField *)field;
5335 *name = g_strdup (f->field->name);
5336 *type = f->field->type;
5341 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
5342 char *name, *result;
5346 name = mono_type_get_name (type);
5347 klass = my_mono_class_from_mono_type (type);
5348 ta = klass->image->assembly;
5349 if (ta == ass || klass->image == mono_defaults.corlib)
5352 /* missing public key */
5353 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
5354 name, ta->aname.name,
5355 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
5356 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
5362 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
5365 MonoTypeEnum simple_type;
5367 if ((p-buffer) + 10 >= *buflen) {
5370 newbuf = g_realloc (buffer, *buflen);
5371 p = newbuf + (p-buffer);
5374 argval = ((char*)arg + sizeof (MonoObject));
5375 simple_type = type->type;
5377 switch (simple_type) {
5378 case MONO_TYPE_BOOLEAN:
5383 case MONO_TYPE_CHAR:
5386 swap_with_size (p, argval, 2, 1);
5392 swap_with_size (p, argval, 4, 1);
5398 swap_with_size (p, argval, 8, 1);
5401 case MONO_TYPE_VALUETYPE:
5402 if (type->data.klass->enumtype) {
5403 simple_type = type->data.klass->enum_basetype->type;
5406 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
5409 case MONO_TYPE_STRING: {
5416 str = mono_string_to_utf8 ((MonoString*)arg);
5417 slen = strlen (str);
5418 if ((p-buffer) + 10 + slen >= *buflen) {
5422 newbuf = g_realloc (buffer, *buflen);
5423 p = newbuf + (p-buffer);
5426 mono_metadata_encode_value (slen, p, &p);
5427 memcpy (p, str, slen);
5432 case MONO_TYPE_CLASS: {
5440 k = mono_object_class (arg);
5441 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
5442 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
5443 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
5445 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
5446 slen = strlen (str);
5447 if ((p-buffer) + 10 + slen >= *buflen) {
5451 newbuf = g_realloc (buffer, *buflen);
5452 p = newbuf + (p-buffer);
5455 mono_metadata_encode_value (slen, p, &p);
5456 memcpy (p, str, slen);
5461 case MONO_TYPE_SZARRAY: {
5466 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
5469 len = mono_array_length ((MonoArray*)arg);
5471 *p++ = (len >> 8) & 0xff;
5472 *p++ = (len >> 16) & 0xff;
5473 *p++ = (len >> 24) & 0xff;
5475 *retbuffer = buffer;
5476 eclass = type->data.klass;
5477 for (i = 0; i < len; ++i) {
5478 encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
5482 /* it may be a boxed value or a Type */
5483 case MONO_TYPE_OBJECT: {
5484 MonoClass *klass = mono_object_class (arg);
5488 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
5491 } else if (klass->enumtype) {
5493 } else if (klass == mono_defaults.string_class) {
5494 simple_type = MONO_TYPE_STRING;
5497 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
5498 *p++ = simple_type = klass->byval_arg.type;
5501 g_error ("unhandled type in custom attr");
5503 str = type_get_qualified_name (klass->enum_basetype, NULL);
5504 slen = strlen (str);
5505 if ((p-buffer) + 10 + slen >= *buflen) {
5509 newbuf = g_realloc (buffer, *buflen);
5510 p = newbuf + (p-buffer);
5513 mono_metadata_encode_value (slen, p, &p);
5514 memcpy (p, str, slen);
5517 simple_type = klass->enum_basetype->type;
5521 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
5524 *retbuffer = buffer;
5528 * mono_reflection_get_custom_attrs_blob:
5529 * @ctor: custom attribute constructor
5530 * @ctorArgs: arguments o the constructor
5536 * Creates the blob of data that needs to be saved in the metadata and that represents
5537 * the custom attributed described by @ctor, @ctorArgs etc.
5538 * Returns: a Byte array representing the blob of data.
5541 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
5544 MonoMethodSignature *sig;
5549 MONO_ARCH_SAVE_REGS;
5551 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
5552 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
5554 sig = ((MonoReflectionMethod*)ctor)->method->signature;
5556 g_assert (mono_array_length (ctorArgs) == sig->param_count);
5558 p = buffer = g_malloc (buflen);
5559 /* write the prolog */
5562 for (i = 0; i < sig->param_count; ++i) {
5563 arg = mono_array_get (ctorArgs, MonoObject*, i);
5564 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
5568 i += mono_array_length (properties);
5570 i += mono_array_length (fields);
5572 *p++ = (i >> 8) & 0xff;
5575 for (i = 0; i < mono_array_length (properties); ++i) {
5580 prop = mono_array_get (properties, gpointer, i);
5581 get_prop_name_and_type (prop, &pname, &ptype);
5582 *p++ = 0x54; /* PROPERTY signature */
5584 /* Preallocate a large enough buffer */
5585 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
5586 char *str = type_get_qualified_name (ptype, NULL);
5592 len += strlen (pname);
5594 if ((p-buffer) + 20 + len >= buflen) {
5598 newbuf = g_realloc (buffer, buflen);
5599 p = newbuf + (p-buffer);
5603 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
5604 char *str = type_get_qualified_name (ptype, NULL);
5605 int slen = strlen (str);
5609 * This seems to be optional...
5612 mono_metadata_encode_value (slen, p, &p);
5613 memcpy (p, str, slen);
5617 mono_metadata_encode_value (ptype->type, p, &p);
5619 len = strlen (pname);
5620 mono_metadata_encode_value (len, p, &p);
5621 memcpy (p, pname, len);
5623 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
5630 for (i = 0; i < mono_array_length (fields); ++i) {
5635 field = mono_array_get (fields, gpointer, i);
5636 get_field_name_and_type (field, &fname, &ftype);
5637 *p++ = 0x53; /* FIELD signature */
5638 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
5639 char *str = type_get_qualified_name (ftype, NULL);
5640 int slen = strlen (str);
5641 if ((p-buffer) + 10 + slen >= buflen) {
5645 newbuf = g_realloc (buffer, buflen);
5646 p = newbuf + (p-buffer);
5651 * This seems to be optional...
5654 mono_metadata_encode_value (slen, p, &p);
5655 memcpy (p, str, slen);
5659 mono_metadata_encode_value (ftype->type, p, &p);
5661 len = strlen (fname);
5662 mono_metadata_encode_value (len, p, &p);
5663 memcpy (p, fname, len);
5665 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
5670 g_assert (p - buffer <= buflen);
5671 buflen = p - buffer;
5672 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5673 p = mono_array_addr (result, char, 0);
5674 memcpy (p, buffer, buflen);
5676 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
5682 * mono_reflection_setup_internal_class:
5683 * @tb: a TypeBuilder object
5685 * Creates a MonoClass that represents the TypeBuilder.
5686 * This is a trick that lets us simplify a lot of reflection code
5687 * (and will allow us to support Build and Run assemblies easier).
5690 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
5692 MonoClass *klass, *parent;
5694 MONO_ARCH_SAVE_REGS;
5696 klass = g_new0 (MonoClass, 1);
5698 klass->image = &tb->module->dynamic_image->image;
5701 /* check so we can compile corlib correctly */
5702 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
5703 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
5704 parent = tb->parent->type->data.klass;
5706 parent = my_mono_class_from_mono_type (tb->parent->type);
5710 klass->inited = 1; /* we lie to the runtime */
5711 klass->name = mono_string_to_utf8 (tb->name);
5712 klass->name_space = mono_string_to_utf8 (tb->nspace);
5713 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
5714 klass->flags = tb->attrs;
5716 klass->element_class = klass;
5717 klass->reflection_info = tb; /* need to pin. */
5719 /* Put into cache so mono_class_get () will find it */
5720 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
5723 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
5724 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
5728 mono_class_setup_parent (klass, parent);
5729 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
5730 const char *old_n = klass->name;
5731 /* trick to get relative numbering right when compiling corlib */
5732 klass->name = "BuildingObject";
5733 mono_class_setup_parent (klass, mono_defaults.object_class);
5734 klass->name = old_n;
5736 mono_class_setup_mono_type (klass);
5738 mono_class_setup_supertypes (klass);
5741 * FIXME: handle interfaces.
5744 tb->type.type = &klass->byval_arg;
5746 if (tb->nesting_type) {
5747 g_assert (tb->nesting_type->type);
5748 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
5751 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
5755 * mono_reflection_setup_generic_class:
5756 * @tb: a TypeBuilder object
5758 * Setup the generic class after all generic parameters have been added.
5761 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
5766 MONO_ARCH_SAVE_REGS;
5768 klass = my_mono_class_from_mono_type (tb->type.type);
5770 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
5772 if (klass->gen_params || (count == 0))
5775 klass->num_gen_params = count;
5776 klass->gen_params = g_new0 (MonoGenericParam, count);
5778 for (i = 0; i < count; i++) {
5779 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
5780 klass->gen_params [i] = *gparam->param;
5783 ensure_runtime_vtable (klass);
5787 * mono_reflection_create_internal_class:
5788 * @tb: a TypeBuilder object
5790 * Actually create the MonoClass that is associated with the TypeBuilder.
5793 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
5797 MONO_ARCH_SAVE_REGS;
5799 klass = my_mono_class_from_mono_type (tb->type.type);
5801 if (klass->enumtype && klass->enum_basetype == NULL) {
5802 MonoReflectionFieldBuilder *fb;
5804 g_assert (tb->fields != NULL);
5805 g_assert (mono_array_length (tb->fields) >= 1);
5807 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
5809 klass->enum_basetype = fb->type->type;
5810 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
5811 if (!klass->element_class)
5812 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
5813 klass->instance_size = klass->element_class->instance_size;
5814 klass->size_inited = 1;
5816 * this is almost safe to do with enums and it's needed to be able
5817 * to create objects of the enum type (for use in SetConstant).
5819 /* FIXME: Does this mean enums can't have method overrides ? */
5820 mono_class_setup_vtable (klass, NULL, 0);
5824 static MonoMarshalSpec*
5825 mono_marshal_spec_from_builder (MonoAssembly *assembly,
5826 MonoReflectionMarshal *minfo)
5828 MonoMarshalSpec *res;
5830 res = g_new0 (MonoMarshalSpec, 1);
5831 res->native = minfo->type;
5833 switch (minfo->type) {
5834 case MONO_NATIVE_LPARRAY:
5835 res->data.array_data.elem_type = minfo->eltype;
5836 res->data.array_data.param_num = 0; /* Not yet */
5837 res->data.array_data.num_elem = minfo->count;
5840 case MONO_NATIVE_BYVALTSTR:
5841 case MONO_NATIVE_BYVALARRAY:
5842 res->data.array_data.num_elem = minfo->count;
5845 case MONO_NATIVE_CUSTOM:
5846 if (minfo->marshaltyperef)
5847 res->data.custom_data.custom_name =
5848 type_get_qualified_name (minfo->marshaltyperef->type,
5851 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
5862 reflection_methodbuilder_to_mono_method (MonoClass *klass,
5863 ReflectionMethodBuilder *rmb,
5864 MonoMethodSignature *sig)
5867 MonoMethodNormal *pm;
5868 MonoMarshalSpec **specs;
5869 MonoReflectionMethodAux *method_aux;
5872 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5873 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5874 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
5876 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
5878 pm = (MonoMethodNormal*)m;
5881 m->flags = rmb->attrs;
5882 m->iflags = rmb->iattrs;
5883 m->name = mono_string_to_utf8 (rmb->name);
5886 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
5888 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
5889 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
5892 m->signature->pinvoke = 1;
5893 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
5895 m->signature->pinvoke = 1;
5897 } else if (!m->klass->dummy &&
5898 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
5899 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
5900 MonoMethodHeader *header;
5902 gint32 max_stack, i;
5903 gint32 num_locals = 0;
5904 gint32 num_clauses = 0;
5908 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
5909 code_size = rmb->ilgen->code_len;
5910 max_stack = rmb->ilgen->max_stack;
5911 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
5912 if (rmb->ilgen->ex_handlers)
5913 num_clauses = method_count_clauses (rmb->ilgen);
5916 code = mono_array_addr (rmb->code, guint8, 0);
5917 code_size = mono_array_length (rmb->code);
5918 /* we probably need to run a verifier on the code... */
5928 header = g_malloc0 (sizeof (MonoMethodHeader) +
5929 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
5930 header->code_size = code_size;
5931 header->code = g_malloc (code_size);
5932 memcpy ((char*)header->code, code, code_size);
5933 header->max_stack = max_stack;
5934 header->init_locals = rmb->init_locals;
5935 header->num_locals = num_locals;
5937 for (i = 0; i < num_locals; ++i) {
5938 MonoReflectionLocalBuilder *lb =
5939 mono_array_get (rmb->ilgen->locals,
5940 MonoReflectionLocalBuilder*, i);
5942 header->locals [i] = g_new0 (MonoType, 1);
5943 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
5946 header->num_clauses = num_clauses;
5948 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
5953 pm->header = header;
5956 method_aux = g_new0 (MonoReflectionMethodAux, 1);
5958 /* Parameter names */
5959 if (rmb->parameters) {
5960 method_aux->param_names = g_new0 (char *, m->signature->param_count);
5961 for (i = 0; i < m->signature->param_count; ++i) {
5962 MonoReflectionParamBuilder *pb;
5963 if ((pb = mono_array_get (rmb->parameters, MonoReflectionParamBuilder*, i))) {
5965 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
5970 /* Parameter marshalling */
5973 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
5974 MonoReflectionParamBuilder *pb;
5975 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
5976 if (pb->marshal_info) {
5978 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
5979 specs [pb->position] =
5980 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
5985 method_aux->param_marshall = specs;
5987 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
5993 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
5995 ReflectionMethodBuilder rmb;
5996 MonoMethodSignature *sig;
5998 sig = ctor_builder_to_signature (mb);
6000 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
6002 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6003 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6005 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6006 /* ilgen is no longer needed */
6014 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
6016 ReflectionMethodBuilder rmb;
6017 MonoMethodSignature *sig;
6019 sig = method_builder_to_signature (mb);
6021 reflection_methodbuilder_from_method_builder (&rmb, mb);
6023 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6024 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6026 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6027 /* ilgen is no longer needed */
6033 static MonoClassField*
6034 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
6036 MonoClassField *field;
6043 field = g_new0 (MonoClassField, 1);
6045 field->name = mono_string_to_utf8 (fb->name);
6047 /* FIXME: handle type modifiers */
6048 field->type = g_memdup (fb->type->type, sizeof (MonoType));
6049 field->type->attrs = fb->attrs;
6051 field->type = fb->type->type;
6053 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
6054 field->data = mono_array_addr (fb->rva_data, char, 0);
6055 if (fb->offset != -1)
6056 field->offset = fb->offset;
6057 field->parent = klass;
6059 mono_save_custom_attrs (klass->image, field, fb->cattrs);
6061 if (fb->def_value) {
6062 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
6063 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
6064 field->def_value = g_new0 (MonoConstant, 1);
6065 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
6066 /* Copy the data from the blob since it might get realloc-ed */
6067 p = assembly->blob.data + idx;
6068 len = mono_metadata_decode_blob_size (p, &p2);
6070 field->def_value->value = g_malloc (len);
6071 memcpy (field->def_value->value, p, len);
6077 static MonoReflectionInflatedMethod*
6078 inflated_method_get_object (MonoDomain *domain, MonoMethod *method, MonoReflectionMethod *declaring,
6079 MonoGenericInst *ginst)
6082 MonoClass *klass, *refclass;
6083 MonoReflectionInflatedMethod *ret;
6085 refclass = method->klass;
6087 CHECK_OBJECT (MonoReflectionInflatedMethod *, method, refclass);
6088 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
6089 cname = "MonoInflatedCtor";
6091 cname = "MonoInflatedMethod";
6092 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
6095 ret = (MonoReflectionInflatedMethod*)mono_object_new (domain, klass);
6096 ret->rmethod.method = method;
6097 ret->rmethod.name = mono_string_new (domain, method->name);
6098 ret->rmethod.reftype = mono_type_get_object (domain, &refclass->byval_arg);
6099 ret->declaring = declaring;
6101 CACHE_OBJECT (method, ret, refclass);
6105 MonoReflectionGenericInst*
6106 mono_reflection_bind_generic_parameters (MonoReflectionType *type, MonoArray *types)
6108 static MonoClass *System_Reflection_MonoGenericInst;
6111 MonoGenericInst *ginst;
6112 MonoArray *ifaces = NULL;
6113 MonoReflectionType *ptype = NULL;
6114 MonoClass *klass, *iklass, *pklass = NULL;
6115 MonoReflectionGenericInst *res, *parent = NULL;
6116 MonoReflectionTypeBuilder *tb = NULL;
6119 domain = mono_object_domain (type);
6121 klass = mono_class_from_mono_type (type->type);
6122 if (!klass->gen_params && !klass->generic_inst)
6125 if (!System_Reflection_MonoGenericInst) {
6126 System_Reflection_MonoGenericInst = mono_class_from_name (
6127 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
6128 g_assert (System_Reflection_MonoGenericInst);
6131 if (klass->wastypebuilder && klass->reflection_info) {
6132 tb = klass->reflection_info;
6136 pklass = mono_class_from_mono_type (ptype->type);
6138 pklass = klass->parent;
6140 ptype = mono_type_get_object (domain, &pklass->byval_arg);
6143 if (pklass && pklass->generic_inst)
6144 parent = mono_reflection_bind_generic_parameters (ptype, types);
6148 pklass = mono_defaults.object_class;
6150 icount = klass->interface_count;
6151 ifaces = mono_array_new (domain, System_Reflection_MonoGenericInst, icount);
6153 for (i = 0; i < icount; i++) {
6154 MonoReflectionGenericInst *iface;
6155 MonoReflectionType *itype;
6158 itype = mono_array_get (tb->interfaces, gpointer, i);
6160 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
6161 iface = mono_reflection_bind_generic_parameters (itype, types);
6163 mono_array_set (ifaces, gpointer, i, iface);
6167 geninst = g_new0 (MonoType, 1);
6168 geninst->type = MONO_TYPE_GENERICINST;
6169 geninst->data.generic_inst = ginst = g_new0 (MonoGenericInst, 1);
6171 if (klass->gen_params) {
6172 ginst->type_argc = mono_array_length (types);
6173 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
6175 for (i = 0; i < ginst->type_argc; ++i) {
6176 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
6178 ginst->type_argv [i] = garg->type;
6180 if (!ginst->is_open)
6181 ginst->is_open = mono_class_is_open_constructed_type (garg->type);
6184 ginst->generic_type = &klass->byval_arg;
6186 MonoGenericInst *kginst = klass->generic_inst->data.generic_inst;
6188 ginst->type_argc = kginst->type_argc;
6189 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
6191 for (i = 0; i < ginst->type_argc; i++) {
6192 MonoType *t = kginst->type_argv [i];
6194 if (t->type == MONO_TYPE_VAR) {
6195 int num = t->data.generic_param->num;
6196 MonoReflectionType *garg = mono_array_get (types, gpointer, num);
6201 if (!ginst->is_open)
6202 ginst->is_open = mono_class_is_open_constructed_type (t);
6204 ginst->type_argv [i] = t;
6207 ginst->generic_type = kginst->generic_type;
6210 iklass = mono_class_from_generic (geninst, FALSE);
6212 mono_class_setup_parent (iklass, parent ? parent->klass : pklass);
6213 mono_class_setup_mono_type (iklass);
6215 res = (MonoReflectionGenericInst *)mono_object_new (domain, System_Reflection_MonoGenericInst);
6217 res->type.type = iklass->generic_inst;
6218 res->klass = iklass;
6219 res->parent = parent;
6220 res->generic_type = type;
6221 res->interfaces = ifaces;
6226 MonoReflectionInflatedMethod*
6227 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
6229 MonoMethod *method, *inflated;
6230 MonoReflectionMethodBuilder *mb = NULL;
6231 MonoGenericInst *ginst;
6234 MONO_ARCH_SAVE_REGS;
6235 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
6236 MonoReflectionTypeBuilder *tb;
6239 mb = (MonoReflectionMethodBuilder *) rmethod;
6240 tb = (MonoReflectionTypeBuilder *) mb->type;
6241 klass = mono_class_from_mono_type (tb->type.type);
6243 method = methodbuilder_to_mono_method (klass, mb);
6245 method = rmethod->method;
6247 count = method->signature->generic_param_count;
6248 if (count != mono_array_length (types))
6251 ginst = g_new0 (MonoGenericInst, 1);
6252 ginst->generic_method = method;
6253 ginst->type_argc = count;
6254 ginst->type_argv = g_new0 (MonoType *, count);
6255 for (i = 0; i < count; i++) {
6256 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
6257 ginst->type_argv [i] = garg->type;
6260 inflated = mono_class_inflate_generic_method (method, ginst);
6262 return inflated_method_get_object (mono_object_domain (rmethod), inflated, rmethod, ginst);
6265 MonoReflectionInflatedMethod*
6266 mono_reflection_inflate_method_or_ctor (MonoReflectionGenericInst *declaring_type,
6267 MonoReflectionGenericInst *reflected_type,
6270 MonoGenericInst *ginst, *type_ginst;
6271 MonoMethod *method, *inflated;
6272 MonoReflectionInflatedMethod *res;
6275 MONO_ARCH_SAVE_REGS;
6277 klass = mono_class_from_mono_type (reflected_type->type.type);
6278 type_ginst = reflected_type->type.type->data.generic_inst;
6280 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
6281 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
6282 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
6283 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
6284 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
6285 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
6286 method = ((MonoReflectionMethod *) obj)->method;
6287 else if (!strcmp (obj->vtable->klass->name, "MonoInflatedMethod") ||
6288 !strcmp (obj->vtable->klass->name, "MonoInflatedCtor"))
6289 method = ((MonoReflectionInflatedMethod *) obj)->rmethod.method;
6291 g_assert_not_reached ();
6293 ginst = g_new0 (MonoGenericInst, 1);
6294 ginst->generic_method = method;
6295 ginst->generic_type = reflected_type->type.type;
6296 ginst->type_argc = type_ginst->type_argc;
6297 ginst->type_argv = type_ginst->type_argv;
6298 ginst->is_open = type_ginst->is_open;
6300 ginst->klass = mono_class_from_generic (ginst->generic_type, FALSE);
6302 if (type_ginst->is_open)
6305 inflated = mono_class_inflate_generic_method (method, ginst);
6307 res = inflated_method_get_object (
6308 mono_object_domain (reflected_type), inflated, (MonoReflectionMethod *) obj, ginst);
6310 res->declaring_type = declaring_type;
6311 res->reflected_type = reflected_type;
6316 MonoReflectionInflatedField*
6317 mono_reflection_inflate_field (MonoReflectionGenericInst *declaring_type,
6318 MonoReflectionGenericInst *reflected_type,
6321 static MonoClass *System_Reflection_MonoInflatedField;
6322 MonoGenericInst *ginst, *type_ginst;
6323 MonoClassField *field, *inflated;
6324 MonoReflectionInflatedField *res;
6328 MONO_ARCH_SAVE_REGS;
6330 if (!System_Reflection_MonoInflatedField) {
6331 System_Reflection_MonoInflatedField = mono_class_from_name (
6332 mono_defaults.corlib, "System.Reflection", "MonoInflatedField");
6333 g_assert (System_Reflection_MonoInflatedField);
6336 klass = mono_class_from_mono_type (reflected_type->type.type);
6337 type_ginst = reflected_type->type.type->data.generic_inst;
6339 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
6340 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
6341 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
6342 field = ((MonoReflectionField *) obj)->field;
6344 g_assert_not_reached ();
6346 ginst = g_new0 (MonoGenericInst, 1);
6347 ginst->generic_type = reflected_type->type.type;
6348 ginst->type_argc = type_ginst->type_argc;
6349 ginst->type_argv = type_ginst->type_argv;
6351 inflated = g_new0 (MonoClassField, 1);
6353 inflated->type = mono_class_inflate_generic_type (field->type, ginst);
6355 domain = mono_object_domain (obj);
6357 res = (MonoReflectionInflatedField *)mono_object_new (domain, System_Reflection_MonoInflatedField);
6358 res->declaring = field;
6359 res->declaring_type = declaring_type;
6360 res->reflected_type = reflected_type;
6361 res->rfield.klass = klass;
6362 res->rfield.field = inflated;
6363 res->rfield.name = mono_string_new (domain, inflated->name);
6364 res->rfield.attrs = inflated->type->attrs;
6365 res->rfield.type = mono_type_get_object (domain, inflated->type);
6366 CACHE_OBJECT (inflated, res, field->parent);
6371 ensure_runtime_vtable (MonoClass *klass)
6373 MonoReflectionTypeBuilder *tb = klass->reflection_info;
6374 int i, num, j, onum;
6375 MonoMethod **overrides;
6377 if (!tb || klass->wastypebuilder)
6380 ensure_runtime_vtable (klass->parent);
6382 num = tb->ctors? mono_array_length (tb->ctors): 0;
6383 num += tb->methods? mono_array_length (tb->methods): 0;
6384 klass->method.count = num;
6385 klass->methods = g_new (MonoMethod*, num);
6386 num = tb->ctors? mono_array_length (tb->ctors): 0;
6387 for (i = 0; i < num; ++i)
6388 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
6389 num = tb->methods? mono_array_length (tb->methods): 0;
6391 for (i = 0; i < num; ++i)
6392 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
6394 klass->wastypebuilder = TRUE;
6395 if (tb->interfaces) {
6396 klass->interface_count = mono_array_length (tb->interfaces);
6397 klass->interfaces = g_new (MonoClass*, klass->interface_count);
6398 for (i = 0; i < klass->interface_count; ++i) {
6399 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
6400 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
6404 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
6405 for (i = 0; i < klass->method.count; ++i)
6406 klass->methods [i]->slot = i;
6411 for (i = 0; i < mono_array_length (tb->methods); ++i) {
6412 MonoReflectionMethodBuilder *mb =
6413 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
6414 if (mb->override_method)
6419 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
6423 for (i = 0; i < mono_array_length (tb->methods); ++i) {
6424 MonoReflectionMethodBuilder *mb =
6425 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
6426 if (mb->override_method) {
6427 /* FIXME: What if 'override_method' is a MethodBuilder ? */
6428 overrides [onum * 2] =
6429 mb->override_method->method;
6430 overrides [onum * 2 + 1] =
6433 g_assert (mb->mhandle);
6440 mono_class_setup_vtable (klass, overrides, onum);
6444 typebuilder_setup_fields (MonoClass *klass)
6446 MonoReflectionTypeBuilder *tb = klass->reflection_info;
6447 MonoReflectionFieldBuilder *fb;
6448 MonoClassField *field;
6453 klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
6454 klass->field.first = 0;
6455 klass->field.last = klass->field.count;
6457 if (!klass->field.count)
6460 klass->fields = g_new0 (MonoClassField, klass->field.count);
6462 for (i = 0; i < klass->field.count; ++i) {
6463 fb = mono_array_get (tb->fields, gpointer, i);
6464 field = &klass->fields [i];
6465 field->name = mono_string_to_utf8 (fb->name);
6467 /* FIXME: handle type modifiers */
6468 field->type = g_memdup (fb->type->type, sizeof (MonoType));
6469 field->type->attrs = fb->attrs;
6471 field->type = fb->type->type;
6473 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
6474 field->data = mono_array_addr (fb->rva_data, char, 0);
6475 if (fb->offset != -1)
6476 field->offset = fb->offset;
6477 field->parent = klass;
6479 mono_save_custom_attrs (klass->image, field, fb->cattrs);
6481 if (fb->def_value) {
6482 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
6483 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
6484 field->def_value = g_new0 (MonoConstant, 1);
6485 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
6486 /* Copy the data from the blob since it might get realloc-ed */
6487 p = assembly->blob.data + idx;
6488 len = mono_metadata_decode_blob_size (p, &p2);
6490 field->def_value->value = g_malloc (len);
6491 memcpy (field->def_value->value, p, len);
6494 mono_class_layout_fields (klass);
6498 typebuilder_setup_properties (MonoClass *klass)
6500 MonoReflectionTypeBuilder *tb = klass->reflection_info;
6501 MonoReflectionPropertyBuilder *pb;
6504 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
6505 klass->property.first = 0;
6506 klass->property.last = klass->property.count;
6508 klass->properties = g_new0 (MonoProperty, klass->property.count);
6509 for (i = 0; i < klass->property.count; ++i) {
6510 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
6511 klass->properties [i].attrs = pb->attrs;
6512 klass->properties [i].name = mono_string_to_utf8 (pb->name);
6514 klass->properties [i].get = pb->get_method->mhandle;
6516 klass->properties [i].set = pb->set_method->mhandle;
6521 typebuilder_setup_events (MonoClass *klass)
6523 MonoReflectionTypeBuilder *tb = klass->reflection_info;
6524 MonoReflectionEventBuilder *eb;
6527 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
6528 klass->event.first = 0;
6529 klass->event.last = klass->event.count;
6531 klass->events = g_new0 (MonoEvent, klass->event.count);
6532 for (i = 0; i < klass->event.count; ++i) {
6533 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
6534 klass->events [i].attrs = eb->attrs;
6535 klass->events [i].name = mono_string_to_utf8 (eb->name);
6537 klass->events [i].add = eb->add_method->mhandle;
6538 if (eb->remove_method)
6539 klass->events [i].remove = eb->remove_method->mhandle;
6540 if (eb->raise_method)
6541 klass->events [i].raise = eb->raise_method->mhandle;
6543 if (eb->other_methods) {
6544 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
6545 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
6546 MonoReflectionMethodBuilder *mb =
6547 mono_array_get (eb->other_methods,
6548 MonoReflectionMethodBuilder*, j);
6549 klass->events [i].other [j] = mb->mhandle;
6556 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
6559 MonoReflectionType* res;
6561 MONO_ARCH_SAVE_REGS;
6563 klass = my_mono_class_from_mono_type (tb->type.type);
6565 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
6568 * Fields to set in klass:
6569 * the various flags: delegate/unicode/contextbound etc.
6572 klass->flags = tb->attrs;
6573 klass->element_class = klass;
6575 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
6576 /* No need to fully construct the type */
6577 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
6579 /* enums are done right away */
6580 if (!klass->enumtype)
6581 ensure_runtime_vtable (klass);
6583 /* fields and object layout */
6584 if (klass->parent) {
6585 if (!klass->parent->size_inited)
6586 mono_class_init (klass->parent);
6587 klass->instance_size += klass->parent->instance_size;
6588 klass->class_size += klass->parent->class_size;
6589 klass->min_align = klass->parent->min_align;
6591 klass->instance_size = sizeof (MonoObject);
6592 klass->min_align = 1;
6595 /* FIXME: handle packing_size and instance_size */
6596 typebuilder_setup_fields (klass);
6598 typebuilder_setup_properties (klass);
6600 typebuilder_setup_events (klass);
6602 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
6603 /* with enums res == tb: need to fix that. */
6604 if (!klass->enumtype)
6605 g_assert (res != (MonoReflectionType*)tb);
6609 MonoReflectionType *
6610 mono_reflection_define_generic_parameter (MonoReflectionTypeBuilder *tb, MonoReflectionMethodBuilder *mb, guint32 index, MonoReflectionGenericParam *gparam)
6614 MonoGenericParam *param;
6617 param = gparam->param = g_new0 (MonoGenericParam, 1);
6620 tb = (MonoReflectionTypeBuilder *) mb->type;
6622 image = (MonoImage*)tb->module->dynamic_image;
6624 param->method = NULL;
6625 param->name = mono_string_to_utf8 (gparam->name);
6628 count = gparam->constraints ? mono_array_length (gparam->constraints) : 0;
6629 param->constraints = g_new0 (MonoClass *, count + 1);
6630 for (i = 0; i < count; i++) {
6631 MonoReflectionType *constraint = mono_array_get (gparam->constraints, MonoReflectionType *, i);
6633 param->constraints [i] = mono_class_from_mono_type (constraint->type);
6636 klass = mono_class_from_generic_parameter (param, image, mb != NULL);
6638 gparam->type = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
6640 return gparam->type;
6644 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
6646 MonoDynamicImage *assembly = sig->module->dynamic_image;
6647 guint32 na = mono_array_length (sig->arguments);
6652 MONO_ARCH_SAVE_REGS;
6654 p = buf = g_malloc (10 + na * 10);
6656 mono_metadata_encode_value (0x07, p, &p);
6657 mono_metadata_encode_value (na, p, &p);
6658 for (i = 0; i < na; ++i) {
6659 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
6660 encode_reflection_type (assembly, type, p, &p);
6664 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6665 p = mono_array_addr (result, char, 0);
6666 memcpy (p, buf, buflen);
6673 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
6675 MonoDynamicImage *assembly = sig->module->dynamic_image;
6676 guint32 na = mono_array_length (sig->arguments);
6681 MONO_ARCH_SAVE_REGS;
6683 p = buf = g_malloc (10 + na * 10);
6685 mono_metadata_encode_value (0x06, p, &p);
6686 for (i = 0; i < na; ++i) {
6687 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
6688 encode_reflection_type (assembly, type, p, &p);
6692 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6693 p = mono_array_addr (result, char, 0);
6694 memcpy (p, buf, buflen);
6701 * mono_reflection_lookup_dynamic_token:
6703 * Finish the Builder object pointed to by TOKEN and return the corresponding
6704 * runtime structure.
6707 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
6709 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
6713 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
6716 if (strcmp (obj->vtable->klass->name, "String") == 0) {
6717 result = mono_string_intern ((MonoString*)obj);
6720 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
6721 MonoReflectionType *tb = (MonoReflectionType*)obj;
6722 result = mono_class_from_mono_type (tb->type);
6725 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
6726 result = ((MonoReflectionMethod*)obj)->method;
6729 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
6730 result = ((MonoReflectionMethod*)obj)->method;
6733 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
6734 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
6735 result = mb->mhandle;
6737 /* Type is not yet created */
6738 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
6740 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
6743 * Hopefully this has been filled in by calling CreateType() on the
6747 * TODO: This won't work if the application finishes another
6748 * TypeBuilder instance instead of this one.
6750 result = mb->mhandle;
6753 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
6754 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
6756 result = cb->mhandle;
6758 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
6760 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
6761 result = cb->mhandle;
6764 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
6765 result = ((MonoReflectionField*)obj)->field;
6768 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
6769 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
6770 result = fb->handle;
6773 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
6775 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
6776 result = fb->handle;
6779 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
6780 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6783 klass = tb->type.type->data.klass;
6784 if (klass->wastypebuilder) {
6785 /* Already created */
6789 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
6790 result = tb->type.type->data.klass;
6794 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
6795 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
6796 MonoMethodSignature *sig;
6799 if (helper->arguments)
6800 nargs = mono_array_length (helper->arguments);
6804 sig = mono_metadata_signature_alloc (image, nargs);
6805 sig->explicit_this = helper->call_conv & 64;
6806 sig->hasthis = helper->call_conv & 32;
6808 if (helper->call_conv == 0) /* unmanaged */
6809 sig->call_convention = helper->unmanaged_call_conv - 1;
6811 if (helper->call_conv & 0x02)
6812 sig->call_convention = MONO_CALL_VARARG;
6814 sig->call_convention = MONO_CALL_DEFAULT;
6816 sig->param_count = nargs;
6817 /* TODO: Copy type ? */
6818 sig->ret = helper->return_type->type;
6819 for (i = 0; i < nargs; ++i) {
6820 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
6821 sig->params [i] = rt->type;
6827 g_print (obj->vtable->klass->name);
6828 g_assert_not_reached ();