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;
47 guint32 *table_idx; /* note: it's a pointer */
51 MonoBoolean init_locals;
53 } ReflectionMethodBuilder;
55 const unsigned char table_sizes [64] = {
65 MONO_INTERFACEIMPL_SIZE,
66 MONO_MEMBERREF_SIZE, /* 0x0A */
68 MONO_CUSTOM_ATTR_SIZE,
69 MONO_FIELD_MARSHAL_SIZE,
70 MONO_DECL_SECURITY_SIZE,
71 MONO_CLASS_LAYOUT_SIZE,
72 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
73 MONO_STAND_ALONE_SIGNATURE_SIZE,
77 MONO_PROPERTY_MAP_SIZE,
80 MONO_METHOD_SEMA_SIZE,
82 MONO_MODULEREF_SIZE, /* 0x1A */
88 MONO_ASSEMBLY_SIZE, /* 0x20 */
89 MONO_ASSEMBLY_PROCESSOR_SIZE,
91 MONO_ASSEMBLYREF_SIZE,
92 MONO_ASSEMBLYREFPROC_SIZE,
93 MONO_ASSEMBLYREFOS_SIZE,
97 MONO_NESTED_CLASS_SIZE,
102 * These macros can be used to allocate long living atomic data so it won't be
103 * tracked by the garbage collector. We use libgc because it's apparently faster
107 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
108 #define FREE_ATOMIC(ptr)
109 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
111 #define ALLOC_ATOMIC(size) g_malloc (size)
112 #define FREE_ATOMIC(ptr) g_free (ptr)
113 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
116 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
117 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
118 static guint32 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper);
119 static guint32 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo);
120 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
123 alloc_table (MonoDynamicTable *table, guint nrows)
126 g_assert (table->columns);
127 if (nrows + 1 >= table->alloc_rows) {
128 while (nrows + 1 >= table->alloc_rows)
129 if (table->alloc_rows == 0)
130 table->alloc_rows = 16;
132 table->alloc_rows *= 2;
135 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
137 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
142 make_room_in_stream (MonoDynamicStream *stream, int size)
144 while (stream->alloc_size <= size) {
145 if (stream->alloc_size < 4096)
146 stream->alloc_size = 4096;
148 stream->alloc_size *= 2;
151 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
153 stream->data = ALLOC_ATOMIC (stream->alloc_size);
157 string_heap_insert (MonoDynamicStream *sh, const char *str)
161 gpointer oldkey, oldval;
163 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
164 return GPOINTER_TO_UINT (oldval);
166 len = strlen (str) + 1;
168 if (idx + len > sh->alloc_size)
169 make_room_in_stream (sh, idx + len);
172 * We strdup the string even if we already copy them in sh->data
173 * so that the string pointers in the hash remain valid even if
174 * we need to realloc sh->data. We may want to avoid that later.
176 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
177 memcpy (sh->data + idx, str, len);
183 string_heap_init (MonoDynamicStream *sh)
186 sh->alloc_size = 4096;
187 sh->data = ALLOC_ATOMIC (4096);
188 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
189 string_heap_insert (sh, "");
192 #if 0 /* never used */
194 string_heap_free (MonoDynamicStream *sh)
196 FREE_ATOMIC (sh->data);
197 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
198 g_hash_table_destroy (sh->hash);
203 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
206 if (stream->alloc_size < stream->index + len)
207 make_room_in_stream (stream, stream->index + len);
208 memcpy (stream->data + stream->index, data, len);
210 stream->index += len;
212 * align index? Not without adding an additional param that controls it since
213 * we may store a blob value in pieces.
219 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
222 if (stream->alloc_size < stream->index + len)
223 make_room_in_stream (stream, stream->index + len);
224 memset (stream->data + stream->index, 0, len);
226 stream->index += len;
231 stream_data_align (MonoDynamicStream *stream)
234 guint32 count = stream->index % 4;
236 /* we assume the stream data will be aligned */
238 mono_image_add_stream_data (stream, buf, 4 - count);
242 mono_blob_entry_hash (const char* str)
246 len = mono_metadata_decode_blob_size (str, &str);
250 for (str += 1; str < end; str++)
251 h = (h << 5) - h + *str;
259 mono_blob_entry_equal (const char *str1, const char *str2) {
263 len = mono_metadata_decode_blob_size (str1, &end1);
264 len2 = mono_metadata_decode_blob_size (str2, &end2);
267 return memcmp (end1, end2, len) == 0;
271 add_to_blob_cached (MonoDynamicAssembly *assembly, char *b1, int s1, char *b2, int s2)
275 gpointer oldkey, oldval;
277 copy = ALLOC_ATOMIC (s1+s2);
278 memcpy (copy, b1, s1);
279 memcpy (copy + s1, b2, s2);
280 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
282 idx = GPOINTER_TO_UINT (oldval);
284 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
285 mono_image_add_stream_data (&assembly->blob, b2, s2);
286 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
291 /* modified version needed to handle building corlib */
293 my_mono_class_from_mono_type (MonoType *type) {
294 switch (type->type) {
295 case MONO_TYPE_ARRAY:
297 case MONO_TYPE_SZARRAY:
298 return mono_class_from_mono_type (type);
300 /* should be always valid when we reach this case... */
301 return type->data.klass;
306 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
309 g_assert_not_reached ();
314 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
318 case MONO_TYPE_BOOLEAN:
332 case MONO_TYPE_STRING:
333 case MONO_TYPE_OBJECT:
334 case MONO_TYPE_TYPEDBYREF:
335 mono_metadata_encode_value (type->type, p, &p);
338 mono_metadata_encode_value (type->type, p, &p);
339 encode_type (assembly, type->data.type, p, &p);
341 case MONO_TYPE_SZARRAY:
342 mono_metadata_encode_value (type->type, p, &p);
343 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
345 case MONO_TYPE_VALUETYPE:
346 case MONO_TYPE_CLASS:
347 mono_metadata_encode_value (type->type, p, &p);
348 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
351 case MONO_TYPE_VALUETYPE:
352 case MONO_TYPE_CLASS: {
353 MonoClass *k = mono_class_from_mono_type (type);
354 mono_metadata_encode_value (type->type, p, &p);
355 /* ensure only non-byref gets passed to mono_image_typedef_or_ref() */
356 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
360 case MONO_TYPE_ARRAY:
361 mono_metadata_encode_value (type->type, p, &p);
362 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
363 mono_metadata_encode_value (type->data.array->rank, p, &p);
364 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
365 mono_metadata_encode_value (0, p, &p);
367 case MONO_TYPE_GENERICINST: {
369 mono_metadata_encode_value (type->type, p, &p);
370 encode_type (assembly, type->data.generic_inst->generic_type, p, &p);
371 mono_metadata_encode_value (type->data.generic_inst->type_argc, p, &p);
372 for (i = 0; i < type->data.generic_inst->type_argc; ++i) {
373 encode_type (assembly, type->data.generic_inst->type_argv [i], p, &p);
378 g_error ("need to encode type %x", type->type);
384 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
387 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
391 encode_type (assembly, type->type, p, endbuf);
395 g_assert_not_reached ();
400 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
405 guint32 nparams = sig->param_count;
406 guint32 size = 10 + nparams * 10;
414 p = buf = g_malloc (size);
416 * FIXME: vararg, explicit_this, differenc call_conv values...
418 *p = sig->call_convention;
420 *p |= 0x20; /* hasthis */
422 mono_metadata_encode_value (nparams, p, &p);
423 encode_type (assembly, sig->ret, p, &p);
424 for (i = 0; i < nparams; ++i)
425 encode_type (assembly, sig->params [i], p, &p);
427 g_assert (p - buf < size);
428 mono_metadata_encode_value (p-buf, b, &b);
429 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
435 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
438 * FIXME: reuse code from method_encode_signature().
443 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
444 guint32 size = 10 + nparams * 10;
449 p = buf = g_malloc (size);
450 /* LAMESPEC: all the call conv spec is foobared */
451 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
452 if (mb->call_conv & 2)
453 *p |= 0x5; /* vararg */
454 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
455 *p |= 0x20; /* hasthis */
457 mono_metadata_encode_value (nparams, p, &p);
458 encode_reflection_type (assembly, mb->rtype, p, &p);
459 for (i = 0; i < nparams; ++i) {
460 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
461 encode_reflection_type (assembly, pt, p, &p);
464 g_assert (p - buf < size);
465 mono_metadata_encode_value (p-buf, b, &b);
466 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
472 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
474 MonoDynamicTable *table;
477 guint32 idx, sig_idx, size;
478 guint nl = mono_array_length (ilgen->locals);
485 p = buf = g_malloc (size);
486 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
487 idx = table->next_idx ++;
489 alloc_table (table, table->rows);
490 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
492 mono_metadata_encode_value (0x07, p, &p);
493 mono_metadata_encode_value (nl, p, &p);
494 for (i = 0; i < nl; ++i) {
495 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
496 encode_reflection_type (assembly, lb->type, p, &p);
498 g_assert (p - buf < size);
499 mono_metadata_encode_value (p-buf, b, &b);
500 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
503 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
509 method_count_clauses (MonoReflectionILGen *ilgen)
511 guint32 num_clauses = 0;
514 MonoILExceptionInfo *ex_info;
515 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
516 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
517 if (ex_info->handlers)
518 num_clauses += mono_array_length (ex_info->handlers);
526 static MonoExceptionClause*
527 method_encode_clauses (MonoDynamicAssembly *assembly,
528 MonoReflectionILGen *ilgen, guint32 num_clauses)
530 MonoExceptionClause *clauses;
531 MonoExceptionClause *clause;
532 MonoILExceptionInfo *ex_info;
533 MonoILExceptionBlock *ex_block;
534 guint32 finally_start;
535 int i, j, clause_index;;
537 clauses = g_new0 (MonoExceptionClause, num_clauses);
540 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
541 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
542 finally_start = ex_info->start + ex_info->len;
543 g_assert (ex_info->handlers);
544 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
545 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
546 clause = &(clauses [clause_index]);
548 clause->flags = ex_block->type;
549 clause->try_offset = ex_info->start;
551 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
552 clause->try_len = finally_start - ex_info->start;
554 clause->try_len = ex_info->len;
555 clause->handler_offset = ex_block->start;
556 clause->handler_len = ex_block->len;
557 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
558 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
559 if (ex_block->extype) {
560 mono_g_hash_table_insert (assembly->tokens,
561 GUINT_TO_POINTER (clause->token_or_filter),
564 finally_start = ex_block->start + ex_block->len;
574 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
580 gint32 num_locals = 0;
581 gint32 num_exception = 0;
584 char fat_header [12];
587 guint32 local_sig = 0;
588 guint32 header_size = 12;
591 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
592 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
593 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
594 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
598 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
600 code = mb->ilgen->code;
601 code_size = mb->ilgen->code_len;
602 max_stack = mb->ilgen->max_stack;
603 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
604 if (mb->ilgen->ex_handlers)
605 num_exception = method_count_clauses (mb->ilgen);
609 mono_raise_exception (mono_get_exception_argument (NULL, "a method does not have any IL associated"));
611 code_size = mono_array_length (code);
612 max_stack = 8; /* we probably need to run a verifier on the code... */
615 /* check for exceptions, maxstack, locals */
616 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
618 if (code_size < 64 && !(code_size & 1)) {
619 flags = (code_size << 2) | 0x2;
620 } else if (code_size < 32 && (code_size & 1)) {
621 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
625 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
626 /* add to the fixup todo list */
627 if (mb->ilgen && mb->ilgen->num_token_fixups)
628 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
629 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
630 return assembly->text_rva + idx;
634 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
636 * FIXME: need to set also the header size in fat_flags.
637 * (and more sects and init locals flags)
641 fat_flags |= METHOD_HEADER_MORE_SECTS;
643 fat_flags |= METHOD_HEADER_INIT_LOCALS;
644 fat_header [0] = fat_flags;
645 fat_header [1] = (header_size / 4 ) << 4;
646 shortp = (guint16*)(fat_header + 2);
647 *shortp = GUINT16_TO_LE (max_stack);
648 intp = (guint32*)(fat_header + 4);
649 *intp = GUINT32_TO_LE (code_size);
650 intp = (guint32*)(fat_header + 8);
651 *intp = GUINT32_TO_LE (local_sig);
652 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
653 /* add to the fixup todo list */
654 if (mb->ilgen && mb->ilgen->num_token_fixups)
655 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
657 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
659 unsigned char sheader [4];
660 MonoExceptionClause clause;
661 MonoILExceptionInfo * ex_info;
662 MonoILExceptionBlock * ex_block;
665 stream_data_align (&assembly->code);
666 /* always use fat format for now */
667 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
668 num_exception *= sizeof (MonoExceptionClause);
669 num_exception += 4; /* include the size of the header */
670 sheader [1] = num_exception & 0xff;
671 sheader [2] = (num_exception >> 8) & 0xff;
672 sheader [3] = (num_exception >> 16) & 0xff;
673 mono_image_add_stream_data (&assembly->code, sheader, 4);
674 /* fat header, so we are already aligned */
676 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
677 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
678 if (ex_info->handlers) {
679 int finally_start = ex_info->start + ex_info->len;
680 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
681 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
682 clause.flags = GUINT32_TO_LE (ex_block->type);
683 clause.try_offset = GUINT32_TO_LE (ex_info->start);
684 /* need fault, too, probably */
685 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
686 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
688 clause.try_len = GUINT32_TO_LE (ex_info->len);
689 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
690 clause.handler_len = GUINT32_TO_LE (ex_block->len);
691 finally_start = ex_block->start + ex_block->len;
692 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
693 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
694 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
695 /*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",
696 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);*/
697 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
700 g_error ("No clauses for ex info block %d", i);
704 return assembly->text_rva + idx;
708 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 token)
711 MonoDynamicTable *table;
714 table = &assembly->tables [table_idx];
716 g_assert (col < table->columns);
718 values = table->values + table->columns;
719 for (i = 1; i <= table->rows; ++i) {
720 if (values [col] == token)
722 values += table->columns;
727 static GHashTable *dynamic_custom_attrs = NULL;
729 static MonoCustomAttrInfo*
730 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
733 MonoCustomAttrInfo *ainfo;
734 MonoReflectionCustomAttr *cattr;
738 /* FIXME: check in assembly the Run flag is set */
740 count = mono_array_length (cattrs);
742 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
744 ainfo->image = image;
745 ainfo->num_attrs = count;
746 for (i = 0; i < count; ++i) {
747 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
748 ainfo->attrs [i].ctor = cattr->ctor->method;
749 /* FIXME: might want to memdup the data here */
750 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
751 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
758 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
760 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
765 if (!dynamic_custom_attrs)
766 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
768 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
772 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
774 /* they are cached, so we don't free them */
775 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
781 * idx is the table index of the object
782 * type is one of CUSTOM_ATTR_*
785 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
787 MonoDynamicTable *table;
788 MonoReflectionCustomAttr *cattr;
790 guint32 count, i, token;
794 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
797 count = mono_array_length (cattrs);
798 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
799 table->rows += count;
800 alloc_table (table, table->rows);
801 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
802 idx <<= CUSTOM_ATTR_BITS;
804 for (i = 0; i < count; ++i) {
805 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
806 values [MONO_CUSTOM_ATTR_PARENT] = idx;
807 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
808 type = mono_metadata_token_index (token);
809 type <<= CUSTOM_ATTR_TYPE_BITS;
810 switch (mono_metadata_token_table (token)) {
811 case MONO_TABLE_METHOD:
812 type |= CUSTOM_ATTR_TYPE_METHODDEF;
814 case MONO_TABLE_MEMBERREF:
815 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
818 g_warning ("got wrong token in custom attr");
821 values [MONO_CUSTOM_ATTR_TYPE] = type;
823 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
824 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
825 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
826 values += MONO_CUSTOM_ATTR_SIZE;
832 * Fill in the MethodDef and ParamDef tables for a method.
833 * This is used for both normal methods and constructors.
836 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
838 MonoDynamicTable *table;
843 /* room in this table is already allocated */
844 table = &assembly->tables [MONO_TABLE_METHOD];
845 *mb->table_idx = table->next_idx ++;
846 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
847 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
849 name = mono_string_to_utf8 (mb->name);
850 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
852 } else { /* a constructor */
853 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
854 // MS.NET adds this automatically
855 mb->attrs |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
857 values [MONO_METHOD_FLAGS] = mb->attrs;
858 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
859 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
860 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
862 table = &assembly->tables [MONO_TABLE_PARAM];
863 values [MONO_METHOD_PARAMLIST] = table->next_idx;
866 MonoDynamicTable *mtable;
869 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
870 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
873 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
874 if (mono_array_get (mb->pinfo, gpointer, i))
877 table->rows += count;
878 alloc_table (table, table->rows);
879 values = table->values + table->next_idx * MONO_PARAM_SIZE;
880 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
881 MonoReflectionParamBuilder *pb;
882 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
883 values [MONO_PARAM_FLAGS] = pb->attrs;
884 values [MONO_PARAM_SEQUENCE] = i;
885 if (pb->name != NULL) {
886 name = mono_string_to_utf8 (pb->name);
887 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
891 values [MONO_PARAM_NAME] = 0;
892 values += MONO_PARAM_SIZE;
893 if (pb->marshal_info) {
895 alloc_table (mtable, mtable->rows);
896 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
897 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
898 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
900 pb->table_idx = table->next_idx++;
907 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
909 MonoDynamicTable *table;
912 ReflectionMethodBuilder rmb;
914 rmb.ilgen = mb->ilgen;
915 rmb.rtype = mb->rtype;
916 rmb.parameters = mb->parameters;
917 rmb.pinfo = mb->pinfo;
918 rmb.attrs = mb->attrs;
919 rmb.iattrs = mb->iattrs;
920 rmb.call_conv = mb->call_conv;
924 rmb.table_idx = &mb->table_idx;
925 rmb.init_locals = mb->init_locals;
926 rmb.mhandle = mb->mhandle;
928 mono_image_basic_method (&rmb, assembly);
930 if (mb->dll) { /* It's a P/Invoke method */
932 int charset = mb->charset & 0xf;
933 int lasterr = mb->charset & 0x40;
934 table = &assembly->tables [MONO_TABLE_IMPLMAP];
936 alloc_table (table, table->rows);
937 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
938 /* map CharSet values to on-disk values */
940 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
941 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
942 name = mono_string_to_utf8 (mb->dllentry);
943 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
945 name = mono_string_to_utf8 (mb->dll);
946 moduleref = string_heap_insert (&assembly->sheap, name);
948 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
949 table = &assembly->tables [MONO_TABLE_MODULEREF];
951 alloc_table (table, table->rows);
952 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
953 values [MONO_IMPLMAP_SCOPE] = table->rows;
957 if (mb->override_method) {
958 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
960 table = &assembly->tables [MONO_TABLE_METHODIMPL];
962 alloc_table (table, table->rows);
963 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
964 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
965 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
966 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
967 switch (mono_metadata_token_table (tok)) {
968 case MONO_TABLE_MEMBERREF:
969 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
971 case MONO_TABLE_METHOD:
972 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
975 g_assert_not_reached ();
977 values [MONO_METHODIMPL_DECLARATION] = tok;
982 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
984 ReflectionMethodBuilder rmb;
986 rmb.ilgen = mb->ilgen;
987 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
988 rmb.parameters = mb->parameters;
989 rmb.pinfo = mb->pinfo;
990 rmb.attrs = mb->attrs;
991 rmb.iattrs = mb->iattrs;
992 rmb.call_conv = mb->call_conv;
996 rmb.table_idx = &mb->table_idx;
997 rmb.init_locals = mb->init_locals;
998 rmb.mhandle = mb->mhandle;
1000 mono_image_basic_method (&rmb, assembly);
1005 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
1007 char blob_size [64];
1008 char *b = blob_size;
1013 if (!assembly->save)
1016 p = buf = g_malloc (64);
1018 mono_metadata_encode_value (0x06, p, &p);
1019 /* encode custom attributes before the type */
1020 encode_type (assembly, field->type, p, &p);
1021 g_assert (p-buf < 64);
1022 mono_metadata_encode_value (p-buf, b, &b);
1023 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1029 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
1031 char blob_size [64];
1032 char *b = blob_size;
1037 p = buf = g_malloc (64);
1039 mono_metadata_encode_value (0x06, p, &p);
1040 /* encode custom attributes before the type */
1041 encode_reflection_type (assembly, fb->type, p, &p);
1042 g_assert (p-buf < 64);
1043 mono_metadata_encode_value (p-buf, b, &b);
1044 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1050 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
1051 * dest may be misaligned.
1054 swap_with_size (char *dest, const char* val, int len, int nelem) {
1055 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1058 for (elem = 0; elem < nelem; ++elem) {
1084 g_assert_not_reached ();
1090 memcpy (dest, val, len * nelem);
1095 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
1096 char blob_size [64];
1097 char *b = blob_size;
1100 guint32 idx, len, dummy = 0;
1102 p = buf = g_malloc (64);
1104 *ret_type = MONO_TYPE_CLASS;
1106 box_val = (char*)&dummy;
1108 box_val = ((char*)val) + sizeof (MonoObject);
1109 *ret_type = val->vtable->klass->byval_arg.type;
1112 switch (*ret_type) {
1113 case MONO_TYPE_BOOLEAN:
1118 case MONO_TYPE_CHAR:
1133 case MONO_TYPE_VALUETYPE:
1134 if (val->vtable->klass->enumtype) {
1135 *ret_type = val->vtable->klass->enum_basetype->type;
1138 g_error ("we can't encode valuetypes");
1139 case MONO_TYPE_CLASS:
1141 case MONO_TYPE_STRING: {
1142 MonoString *str = (MonoString*)val;
1143 /* there is no signature */
1144 len = str->length * 2;
1145 mono_metadata_encode_value (len, b, &b);
1146 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1148 char *swapped = g_malloc (2 * mono_string_length (str));
1149 const char *p = (const char*)mono_string_chars (str);
1151 swap_with_size (swapped, p, 2, mono_string_length (str));
1152 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1156 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1163 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1166 /* there is no signature */
1167 mono_metadata_encode_value (len, b, &b);
1168 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1169 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1170 swap_with_size (blob_size, box_val, len, 1);
1171 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1173 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1181 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo) {
1182 char blob_size [64];
1183 char *b = blob_size;
1184 char *p, *buf, *str;
1185 guint32 idx, len, bufsize = 256;
1187 p = buf = g_malloc (bufsize);
1189 switch (minfo->type) {
1190 case MONO_NATIVE_BYVALTSTR:
1191 case MONO_NATIVE_BYVALARRAY:
1192 mono_metadata_encode_value (minfo->type, p, &p);
1193 mono_metadata_encode_value (minfo->count, p, &p);
1195 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
1196 case MONO_NATIVE_CUSTOM:
1197 mono_metadata_encode_value (minfo->type, p, &p);
1199 str = mono_string_to_utf8 (minfo->guid);
1201 mono_metadata_encode_value (len, p, &p);
1202 memcpy (p, str, len);
1206 mono_metadata_encode_value (0, p, &p);
1208 if (minfo->marshaltype) {
1209 str = mono_string_to_utf8 (minfo->marshaltype);
1211 mono_metadata_encode_value (len, p, &p);
1212 if (p + len >= buf + bufsize) {
1215 buf = g_realloc (buf, bufsize);
1218 memcpy (p, str, len);
1222 mono_metadata_encode_value (0, p, &p);
1224 if (minfo->marshaltyperef) {
1225 str = type_get_qualified_name (minfo->marshaltyperef->type, &assembly->assembly);
1227 mono_metadata_encode_value (len, p, &p);
1228 if (p + len >= buf + bufsize) {
1231 buf = g_realloc (buf, bufsize);
1234 memcpy (p, str, len);
1238 mono_metadata_encode_value (0, p, &p);
1240 if (minfo->mcookie) {
1241 str = mono_string_to_utf8 (minfo->mcookie);
1243 mono_metadata_encode_value (len, p, &p);
1244 if (p + len >= buf + bufsize) {
1247 buf = g_realloc (buf, bufsize);
1250 memcpy (p, str, len);
1254 mono_metadata_encode_value (0, p, &p);
1258 mono_metadata_encode_value (minfo->type, p, &p);
1262 mono_metadata_encode_value (len, b, &b);
1263 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1269 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
1271 MonoDynamicTable *table;
1275 /* maybe this fixup should be done in the C# code */
1276 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1277 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1278 table = &assembly->tables [MONO_TABLE_FIELD];
1279 fb->table_idx = table->next_idx ++;
1280 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1281 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1282 name = mono_string_to_utf8 (fb->name);
1283 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1285 values [MONO_FIELD_FLAGS] = fb->attrs;
1286 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1288 if (fb->offset != -1) {
1289 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1291 alloc_table (table, table->rows);
1292 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1293 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1294 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1296 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1297 guint32 field_type = 0;
1298 table = &assembly->tables [MONO_TABLE_CONSTANT];
1300 alloc_table (table, table->rows);
1301 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1302 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1303 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1304 values [MONO_CONSTANT_TYPE] = field_type;
1305 values [MONO_CONSTANT_PADDING] = 0;
1309 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1311 alloc_table (table, table->rows);
1312 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1313 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1315 * We store it in the code section because it's simpler for now.
1317 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1318 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1320 if (fb->marshal_info) {
1321 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1323 alloc_table (table, table->rows);
1324 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1325 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1326 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1331 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
1335 char *b = blob_size;
1336 guint32 nparams = 0;
1337 MonoReflectionMethodBuilder *mb = fb->get_method;
1338 MonoReflectionMethodBuilder *smb = fb->set_method;
1339 guint32 idx, i, size;
1341 if (mb && mb->parameters)
1342 nparams = mono_array_length (mb->parameters);
1343 if (!mb && smb && smb->parameters)
1344 nparams = mono_array_length (smb->parameters) - 1;
1345 size = 24 + nparams * 10;
1346 buf = p = g_malloc (size);
1349 mono_metadata_encode_value (nparams, p, &p);
1351 encode_reflection_type (assembly, mb->rtype, p, &p);
1352 for (i = 0; i < nparams; ++i) {
1353 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1354 encode_reflection_type (assembly, pt, p, &p);
1357 /* the property type is the last param */
1358 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1359 for (i = 0; i < nparams; ++i) {
1360 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1361 encode_reflection_type (assembly, pt, p, &p);
1365 g_assert (p - buf < size);
1366 mono_metadata_encode_value (p-buf, b, &b);
1367 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1373 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
1375 MonoDynamicTable *table;
1378 guint num_methods = 0;
1382 * we need to set things in the following tables:
1383 * PROPERTYMAP (info already filled in _get_type_info ())
1384 * PROPERTY (rows already preallocated in _get_type_info ())
1385 * METHOD (method info already done with the generic method code)
1388 table = &assembly->tables [MONO_TABLE_PROPERTY];
1389 pb->table_idx = table->next_idx ++;
1390 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1391 name = mono_string_to_utf8 (pb->name);
1392 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1394 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1395 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1397 /* FIXME: we still don't handle 'other' methods */
1398 if (pb->get_method) num_methods ++;
1399 if (pb->set_method) num_methods ++;
1401 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1402 table->rows += num_methods;
1403 alloc_table (table, table->rows);
1405 if (pb->get_method) {
1406 semaidx = table->next_idx ++;
1407 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1408 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1409 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1410 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1412 if (pb->set_method) {
1413 semaidx = table->next_idx ++;
1414 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1415 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1416 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1417 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1422 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
1424 MonoDynamicTable *table;
1427 guint num_methods = 0;
1431 * we need to set things in the following tables:
1432 * EVENTMAP (info already filled in _get_type_info ())
1433 * EVENT (rows already preallocated in _get_type_info ())
1434 * METHOD (method info already done with the generic method code)
1437 table = &assembly->tables [MONO_TABLE_EVENT];
1438 eb->table_idx = table->next_idx ++;
1439 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1440 name = mono_string_to_utf8 (eb->name);
1441 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1443 values [MONO_EVENT_FLAGS] = eb->attrs;
1444 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1447 * FIXME: we still don't handle 'other' methods
1449 if (eb->add_method) num_methods ++;
1450 if (eb->remove_method) num_methods ++;
1451 if (eb->raise_method) num_methods ++;
1453 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1454 table->rows += num_methods;
1455 alloc_table (table, table->rows);
1457 if (eb->add_method) {
1458 semaidx = table->next_idx ++;
1459 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1460 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1461 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1462 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1464 if (eb->remove_method) {
1465 semaidx = table->next_idx ++;
1466 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1467 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1468 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1469 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1471 if (eb->raise_method) {
1472 semaidx = table->next_idx ++;
1473 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1474 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1475 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1476 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1481 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
1483 MonoDynamicTable *table;
1486 guint32 cols [MONO_ASSEMBLY_SIZE];
1490 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1493 if (image->assembly->dynamic)
1495 memset (cols, 0, sizeof (cols));
1497 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1499 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1500 token = table->next_idx ++;
1502 alloc_table (table, table->rows);
1503 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1504 if (strcmp ("corlib", image->assembly_name) == 0)
1505 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1507 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1508 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1509 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1510 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1511 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1512 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1513 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1514 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1516 if ((pubkey = mono_image_get_public_key (image, &publen))) {
1517 guchar pubtoken [9];
1519 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
1520 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
1523 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
1524 * This is currently only a problem with references to System.Xml (see bug#27706),
1525 * but there may be other cases that makes this necessary. Note, we need to set
1526 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
1527 * recognized by ms, yuck!
1528 * FIXME: need to add more assembly names, as needed.
1530 if (strcmp (image->assembly_name, "corlib") == 0 ||
1531 strcmp (image->assembly_name, "mscorlib") == 0 ||
1532 strcmp (image->assembly_name, "System") == 0 ||
1533 strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 ||
1534 strcmp (image->assembly_name, "System.Xml") == 0 ||
1535 strcmp (image->assembly_name, "System.Data") == 0 ||
1536 strcmp (image->assembly_name, "System.Windows.Forms") == 0) {
1537 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
1538 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1539 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1540 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1541 } else if (strcmp (image->assembly_name, "Accessibility") == 0 ||
1542 strcmp (image->assembly_name, "cscompmgd") == 0 ||
1543 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
1544 strcmp (image->assembly_name, "Microsoft.JScript") == 0 ||
1545 strcmp (image->assembly_name, "Microsoft.VisualBasic") == 0 ||
1546 strcmp (image->assembly_name, "Microsoft.VisualBasic.Vsa") == 0 ||
1547 strcmp (image->assembly_name, "Microsoft.VisualC") == 0 ||
1548 strcmp (image->assembly_name, "Microsoft.Vsa") == 0 ||
1549 strcmp (image->assembly_name, "System.Configuration.Install") == 0 ||
1550 strcmp (image->assembly_name, "System.DirectoryServices") == 0 ||
1551 strcmp (image->assembly_name, "System.Design") == 0 ||
1552 strcmp (image->assembly_name, "System.Drawing") == 0 ||
1553 strcmp (image->assembly_name, "System.Drawing.Design") == 0 ||
1554 strcmp (image->assembly_name, "System.EnterpriseServices") == 0 ||
1555 strcmp (image->assembly_name, "System.Management") == 0 ||
1556 strcmp (image->assembly_name, "System.Messaging") == 0 ||
1557 strcmp (image->assembly_name, "System.Runtime.Serialization.Formatters.Soap") == 0 ||
1558 strcmp (image->assembly_name, "System.Security") == 0 ||
1559 strcmp (image->assembly_name, "System.ServiceProcess") == 0 ||
1560 strcmp (image->assembly_name, "System.Web.Services") == 0 ||
1561 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
1562 strcmp (image->assembly_name, "System.Web") == 0) {
1563 static const guchar ptoken [9] = {8, '\xb0', '\x3f', '\x5f', '\x7f', '\x11', '\xd5', '\x0a', '\x3a'};
1564 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1565 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1566 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1568 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1571 token <<= RESOLTION_SCOPE_BITS;
1572 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1573 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1578 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1580 MonoDynamicTable *table;
1586 char *b = blob_size;
1588 switch (type->type) {
1589 case MONO_TYPE_FNPTR:
1591 case MONO_TYPE_SZARRAY:
1592 case MONO_TYPE_ARRAY:
1593 encode_type (assembly, type, p, &p);
1595 case MONO_TYPE_CLASS:
1596 case MONO_TYPE_VALUETYPE: {
1597 MonoClass *k = mono_class_from_mono_type (type);
1598 if (!k || !k->generic_inst)
1600 encode_type (assembly, k->generic_inst, p, &p);
1607 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1608 if (assembly->save) {
1609 g_assert (p-sig < 128);
1610 mono_metadata_encode_value (p-sig, b, &b);
1611 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
1612 alloc_table (table, table->rows + 1);
1613 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1614 values [MONO_TYPESPEC_SIGNATURE] = token;
1617 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1618 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1624 * Despite the name, we handle also TypeSpec (with the above helper).
1627 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1629 MonoDynamicTable *table;
1631 guint32 token, scope, enclosing;
1634 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1637 token = create_typespec (assembly, type);
1640 klass = my_mono_class_from_mono_type (type);
1642 klass = mono_class_from_mono_type (type);
1645 * If it's in the same module:
1647 if (klass->image == assembly->assembly.image) {
1648 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1649 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1650 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
1654 if (klass->nested_in) {
1655 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1656 /* get the typeref idx of the enclosing type */
1657 enclosing >>= TYPEDEFORREF_BITS;
1658 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1660 scope = resolution_scope_from_image (assembly, klass->image);
1662 table = &assembly->tables [MONO_TABLE_TYPEREF];
1663 if (assembly->save) {
1664 alloc_table (table, table->rows + 1);
1665 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1666 values [MONO_TYPEREF_SCOPE] = scope;
1667 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1668 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1670 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1671 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1673 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
1678 * Insert a memberef row into the metadata: the token that point to the memberref
1679 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1680 * mono_image_get_fieldref_token()).
1681 * The sig param is an index to an already built signature.
1684 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1686 MonoDynamicTable *table;
1688 guint32 token, pclass;
1691 parent = mono_image_typedef_or_ref (assembly, type);
1692 switch (parent & TYPEDEFORREF_MASK) {
1693 case TYPEDEFORREF_TYPEREF:
1694 pclass = MEMBERREF_PARENT_TYPEREF;
1696 case TYPEDEFORREF_TYPESPEC:
1697 pclass = MEMBERREF_PARENT_TYPESPEC;
1699 case TYPEDEFORREF_TYPEDEF:
1700 /* should never get here */
1702 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
1705 /* extract the index */
1706 parent >>= TYPEDEFORREF_BITS;
1708 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1710 if (assembly->save) {
1711 alloc_table (table, table->rows + 1);
1712 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1713 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1714 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1715 values [MONO_MEMBERREF_SIGNATURE] = sig;
1718 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1725 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1729 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1732 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1733 method->name, method_encode_signature (assembly, method->signature));
1734 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1739 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1743 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1746 field->parent = klass;
1747 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
1748 field->name, fieldref_encode_signature (assembly, field));
1749 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1754 mono_reflection_encode_sighelper (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1762 char *b = blob_size;
1764 if (!assembly->save)
1768 g_assert (helper->type == 2);
1770 if (helper->arguments)
1771 nargs = mono_array_length (helper->arguments);
1775 size = 10 + (nargs * 10);
1777 p = buf = g_malloc (size);
1779 /* Encode calling convention */
1780 /* Change Any to Standard */
1781 if ((helper->call_conv & 0x03) == 0x03)
1782 helper->call_conv = 0x01;
1783 /* explicit_this implies has_this */
1784 if (helper->call_conv & 0x40)
1785 helper->call_conv &= 0x20;
1787 if (helper->call_conv == 0) /* Unmanaged */
1788 *p = helper->unmanaged_call_conv - 1;
1791 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
1792 if (helper->call_conv & 0x02) /* varargs */
1797 mono_metadata_encode_value (nargs, p, &p);
1798 encode_reflection_type (assembly, helper->return_type, p, &p);
1799 for (i = 0; i < nargs; ++i) {
1800 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
1801 encode_reflection_type (assembly, pt, p, &p);
1804 g_assert (p - buf < size);
1805 mono_metadata_encode_value (p-buf, b, &b);
1806 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1813 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1816 MonoDynamicTable *table;
1819 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1820 idx = table->next_idx ++;
1822 alloc_table (table, table->rows);
1823 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1825 values [MONO_STAND_ALONE_SIGNATURE] =
1826 mono_reflection_encode_sighelper (assembly, helper);
1832 reflection_cc_to_file (int call_conv) {
1833 switch (call_conv & 0x3) {
1835 case 1: return MONO_CALL_DEFAULT;
1836 case 2: return MONO_CALL_VARARG;
1838 g_assert_not_reached ();
1845 MonoMethodSignature *sig;
1851 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1856 MonoMethodSignature *sig;
1859 name = mono_string_to_utf8 (m->name);
1860 nparams = mono_array_length (m->parameters);
1861 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1863 sig->call_convention = reflection_cc_to_file (m->call_conv);
1864 sig->param_count = nparams;
1865 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1866 for (i = 0; i < nparams; ++i) {
1867 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1868 sig->params [i] = t->type;
1871 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1873 if (strcmp (name, am->name) == 0 &&
1874 mono_metadata_type_equal (am->parent, m->parent->type) &&
1875 mono_metadata_signature_equal (am->sig, sig)) {
1878 m->table_idx = am->token & 0xffffff;
1882 am = g_new0 (ArrayMethod, 1);
1885 am->parent = m->parent->type;
1886 am->token = mono_image_get_memberref_token (assembly, am->parent,
1887 name, method_encode_signature (assembly, sig));
1888 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1889 m->table_idx = am->token & 0xffffff;
1894 * Insert into the metadata tables all the info about the TypeBuilder tb.
1895 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1898 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1900 MonoDynamicTable *table;
1902 int i, is_object = 0, is_system = 0;
1905 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1906 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1907 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1908 n = mono_string_to_utf8 (tb->name);
1909 if (strcmp (n, "Object") == 0)
1911 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1913 n = mono_string_to_utf8 (tb->nspace);
1914 if (strcmp (n, "System") == 0)
1916 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1918 if (tb->parent && !(is_system && is_object) &&
1919 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
1920 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1922 values [MONO_TYPEDEF_EXTENDS] = 0;
1923 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1924 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1927 * if we have explicitlayout or sequentiallayouts, output data in the
1928 * ClassLayout table.
1930 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1931 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1933 alloc_table (table, table->rows);
1934 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1935 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1936 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1937 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1940 /* handle interfaces */
1941 if (tb->interfaces) {
1942 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1944 table->rows += mono_array_length (tb->interfaces);
1945 alloc_table (table, table->rows);
1946 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1947 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1948 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1949 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1950 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1951 values += MONO_INTERFACEIMPL_SIZE;
1957 table = &assembly->tables [MONO_TABLE_FIELD];
1958 table->rows += mono_array_length (tb->fields);
1959 alloc_table (table, table->rows);
1960 for (i = 0; i < mono_array_length (tb->fields); ++i)
1961 mono_image_get_field_info (
1962 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1965 /* handle constructors */
1967 table = &assembly->tables [MONO_TABLE_METHOD];
1968 table->rows += mono_array_length (tb->ctors);
1969 alloc_table (table, table->rows);
1970 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1971 mono_image_get_ctor_info (domain,
1972 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1975 /* handle methods */
1977 table = &assembly->tables [MONO_TABLE_METHOD];
1978 table->rows += mono_array_length (tb->methods);
1979 alloc_table (table, table->rows);
1980 for (i = 0; i < mono_array_length (tb->methods); ++i)
1981 mono_image_get_method_info (
1982 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1985 /* Do the same with properties etc.. */
1986 if (tb->events && mono_array_length (tb->events)) {
1987 table = &assembly->tables [MONO_TABLE_EVENT];
1988 table->rows += mono_array_length (tb->events);
1989 alloc_table (table, table->rows);
1990 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1992 alloc_table (table, table->rows);
1993 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1994 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1995 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1996 for (i = 0; i < mono_array_length (tb->events); ++i)
1997 mono_image_get_event_info (
1998 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2000 if (tb->properties && mono_array_length (tb->properties)) {
2001 table = &assembly->tables [MONO_TABLE_PROPERTY];
2002 table->rows += mono_array_length (tb->properties);
2003 alloc_table (table, table->rows);
2004 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2006 alloc_table (table, table->rows);
2007 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2008 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2009 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2010 for (i = 0; i < mono_array_length (tb->properties); ++i)
2011 mono_image_get_property_info (
2012 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2015 MonoDynamicTable *ntable;
2017 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2018 ntable->rows += mono_array_length (tb->subtypes);
2019 alloc_table (ntable, ntable->rows);
2020 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2022 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2023 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2025 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2026 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2027 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2028 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2029 mono_string_to_utf8 (tb->name), tb->table_idx,
2030 ntable->next_idx, ntable->rows);*/
2031 values += MONO_NESTED_CLASS_SIZE;
2038 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2042 g_ptr_array_add (types, type);
2044 if (!type->subtypes)
2047 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2048 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2049 collect_types (types, subtype);
2054 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2055 MonoReflectionTypeBuilder **type2)
2057 if ((*type1)->table_idx < (*type2)->table_idx)
2060 if ((*type1)->table_idx > (*type2)->table_idx)
2067 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
2072 for (i = 0; i < mono_array_length (pinfo); ++i) {
2073 MonoReflectionParamBuilder *pb;
2074 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2077 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2082 type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
2085 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2087 for (i = 0; i < mono_array_length (tb->fields); ++i) {
2088 MonoReflectionFieldBuilder* fb;
2089 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2090 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2094 for (i = 0; i < mono_array_length (tb->events); ++i) {
2095 MonoReflectionEventBuilder* eb;
2096 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2097 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2100 if (tb->properties) {
2101 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2102 MonoReflectionPropertyBuilder* pb;
2103 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2104 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2108 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2109 MonoReflectionCtorBuilder* cb;
2110 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2111 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2112 params_add_cattrs (assembly, cb->pinfo);
2117 for (i = 0; i < mono_array_length (tb->methods); ++i) {
2118 MonoReflectionMethodBuilder* mb;
2119 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2120 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2121 params_add_cattrs (assembly, mb->pinfo);
2126 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2127 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2132 module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
2135 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2137 /* no types in the module */
2141 for (i = 0; i < mono_array_length (mb->types); ++i)
2142 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2146 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
2148 MonoDynamicTable *table;
2152 table = &assembly->tables [MONO_TABLE_MODULE];
2153 mb->table_idx = table->next_idx ++;
2154 name = mono_string_to_utf8 (mb->module.name);
2155 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2157 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2160 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2161 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2162 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2165 #define align_pointer(base,p)\
2167 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
2169 (p) += 4 - (__diff & 3);\
2173 compare_semantics (const void *a, const void *b)
2175 const guint32 *a_values = a;
2176 const guint32 *b_values = b;
2177 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
2180 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
2184 compare_custom_attrs (const void *a, const void *b)
2186 const guint32 *a_values = a;
2187 const guint32 *b_values = b;
2189 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
2193 compare_field_marshal (const void *a, const void *b)
2195 const guint32 *a_values = a;
2196 const guint32 *b_values = b;
2198 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
2202 compare_nested (const void *a, const void *b)
2204 const guint32 *a_values = a;
2205 const guint32 *b_values = b;
2207 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
2211 * build_compressed_metadata() fills in the blob of data that represents the
2212 * raw metadata as it will be saved in the PE file. The five streams are output
2213 * and the metadata tables are comnpressed from the guint32 array representation,
2214 * to the compressed on-disk format.
2217 build_compressed_metadata (MonoDynamicAssembly *assembly)
2219 MonoDynamicTable *table;
2221 guint64 valid_mask = 0;
2222 guint64 sorted_mask;
2223 guint32 heapt_size = 0;
2224 guint32 meta_size = 256; /* allow for header and other stuff */
2225 guint32 table_offset;
2226 guint32 ntables = 0;
2235 MonoDynamicStream *stream;
2238 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
2239 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
2240 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
2241 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
2242 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
2244 /* tables that are sorted */
2245 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
2246 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
2247 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
2248 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
2249 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
2250 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
2252 /* Compute table sizes */
2253 /* the MonoImage has already been created in mono_image_basic_init() */
2254 meta = assembly->assembly.image;
2256 /* Setup the info used by compute_sizes () */
2257 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
2258 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
2259 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
2261 meta_size += assembly->blob.index;
2262 meta_size += assembly->guid.index;
2263 meta_size += assembly->sheap.index;
2264 meta_size += assembly->us.index;
2266 for (i=0; i < 64; ++i)
2267 meta->tables [i].rows = assembly->tables [i].rows;
2269 for (i = 0; i < 64; i++){
2270 if (meta->tables [i].rows == 0)
2272 valid_mask |= (guint64)1 << i;
2274 meta->tables [i].row_size = mono_metadata_compute_size (
2275 meta, i, &meta->tables [i].size_bitfield);
2276 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
2278 heapt_size += 24; /* #~ header size */
2279 heapt_size += ntables * 4;
2280 meta_size += heapt_size;
2281 meta->raw_metadata = g_malloc0 (meta_size);
2282 p = meta->raw_metadata;
2283 /* the metadata signature */
2284 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
2285 /* version numbers and 4 bytes reserved */
2286 int16val = (guint16*)p;
2287 *int16val++ = GUINT16_TO_LE (1);
2288 *int16val = GUINT16_TO_LE (1);
2290 /* version string */
2291 int32val = (guint32*)p;
2292 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
2294 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
2295 p += GUINT32_FROM_LE (*int32val);
2296 align_pointer (meta->raw_metadata, p);
2297 int16val = (guint16*)p;
2298 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
2299 *int16val = GUINT16_TO_LE (5); /* number of streams */
2303 * write the stream info.
2305 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
2306 table_offset += 3; table_offset &= ~3;
2308 assembly->tstream.index = heapt_size;
2309 for (i = 0; i < 5; ++i) {
2310 int32val = (guint32*)p;
2311 stream_desc [i].stream->offset = table_offset;
2312 *int32val++ = GUINT32_TO_LE (table_offset);
2313 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
2314 table_offset += GUINT32_FROM_LE (*int32val);
2315 table_offset += 3; table_offset &= ~3;
2317 strcpy (p, stream_desc [i].name);
2318 p += strlen (stream_desc [i].name) + 1;
2319 align_pointer (meta->raw_metadata, p);
2322 * now copy the data, the table stream header and contents goes first.
2324 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
2325 p = meta->raw_metadata + assembly->tstream.offset;
2326 int32val = (guint32*)p;
2327 *int32val = GUINT32_TO_LE (0); /* reserved */
2329 *p++ = 1; /* version */
2331 if (meta->idx_string_wide)
2333 if (meta->idx_guid_wide)
2335 if (meta->idx_blob_wide)
2338 *p++ = 0; /* reserved */
2339 int64val = (guint64*)p;
2340 *int64val++ = GUINT64_TO_LE (valid_mask);
2341 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
2343 int32val = (guint32*)p;
2344 for (i = 0; i < 64; i++){
2345 if (meta->tables [i].rows == 0)
2347 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
2349 p = (unsigned char*)int32val;
2351 /* sort the tables that still need sorting */
2352 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2354 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
2355 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2357 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
2358 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2360 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
2361 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2363 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
2365 /* compress the tables */
2366 for (i = 0; i < 64; i++){
2369 guint32 bitfield = meta->tables [i].size_bitfield;
2370 if (!meta->tables [i].rows)
2372 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
2373 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
2374 meta->tables [i].base = p;
2375 for (row = 1; row <= meta->tables [i].rows; ++row) {
2376 values = assembly->tables [i].values + row * assembly->tables [i].columns;
2377 for (col = 0; col < assembly->tables [i].columns; ++col) {
2378 switch (mono_metadata_table_size (bitfield, col)) {
2380 *p++ = values [col];
2383 *p++ = values [col] & 0xff;
2384 *p++ = (values [col] >> 8) & 0xff;
2387 *p++ = values [col] & 0xff;
2388 *p++ = (values [col] >> 8) & 0xff;
2389 *p++ = (values [col] >> 16) & 0xff;
2390 *p++ = (values [col] >> 24) & 0xff;
2393 g_assert_not_reached ();
2397 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
2400 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
2401 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
2402 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
2403 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
2404 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
2406 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
2410 * Some tables in metadata need to be sorted according to some criteria, but
2411 * when methods and fields are first created with reflection, they may be assigned a token
2412 * that doesn't correspond to the final token they will get assigned after the sorting.
2413 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
2414 * with the reflection objects that represent them. Once all the tables are set up, the
2415 * reflection objects will contains the correct table index. fixup_method() will fixup the
2416 * tokens for the method with ILGenerator @ilgen.
2419 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
2420 guint32 code_idx = GPOINTER_TO_UINT (value);
2421 MonoReflectionILTokenInfo *iltoken;
2422 MonoReflectionFieldBuilder *field;
2423 MonoReflectionCtorBuilder *ctor;
2424 MonoReflectionMethodBuilder *method;
2425 MonoReflectionTypeBuilder *tb;
2426 MonoReflectionArrayMethod *am;
2428 unsigned char *target;
2430 for (i = 0; i < ilgen->num_token_fixups; ++i) {
2431 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
2432 target = assembly->code.data + code_idx + iltoken->code_pos;
2433 switch (target [3]) {
2434 case MONO_TABLE_FIELD:
2435 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
2436 field = (MonoReflectionFieldBuilder *)iltoken->member;
2437 idx = field->table_idx;
2438 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
2439 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
2440 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
2442 g_assert_not_reached ();
2445 case MONO_TABLE_METHOD:
2446 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
2447 method = (MonoReflectionMethodBuilder *)iltoken->member;
2448 idx = method->table_idx;
2449 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
2450 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
2451 idx = ctor->table_idx;
2452 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
2453 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
2454 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
2456 g_assert_not_reached ();
2459 case MONO_TABLE_TYPEDEF:
2460 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
2461 g_assert_not_reached ();
2462 tb = (MonoReflectionTypeBuilder *)iltoken->member;
2463 idx = tb->table_idx;
2465 case MONO_TABLE_MEMBERREF:
2466 if (strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod"))
2467 g_assert_not_reached ();
2468 am = (MonoReflectionArrayMethod*)iltoken->member;
2469 idx = am->table_idx;
2472 g_error ("got unexpected table 0x%02x in fixup", target [3]);
2474 target [0] = idx & 0xff;
2475 target [1] = (idx >> 8) & 0xff;
2476 target [2] = (idx >> 16) & 0xff;
2481 assembly_add_resource (MonoDynamicAssembly *assembly, MonoReflectionResource *rsrc)
2483 MonoDynamicTable *table;
2487 char *b = blob_size;
2489 guint32 idx, offset;
2491 if (rsrc->filename) {
2492 name = mono_string_to_utf8 (rsrc->filename);
2493 sname = g_path_get_basename (name);
2495 table = &assembly->tables [MONO_TABLE_FILE];
2497 alloc_table (table, table->rows);
2498 values = table->values + table->next_idx * MONO_FILE_SIZE;
2499 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
2500 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
2503 mono_sha1_get_digest_from_file (name, hash);
2504 mono_metadata_encode_value (20, b, &b);
2505 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2506 mono_image_add_stream_data (&assembly->blob, hash, 20);
2508 idx = table->next_idx++;
2509 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
2513 offset = mono_array_length (rsrc->data);
2514 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
2515 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
2516 offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
2517 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
2521 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
2523 alloc_table (table, table->rows);
2524 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
2525 values [MONO_MANIFEST_OFFSET] = offset;
2526 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
2527 name = mono_string_to_utf8 (rsrc->name);
2528 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
2530 values [MONO_MANIFEST_IMPLEMENTATION] = idx;
2535 set_version_from_string (MonoString *version, guint32 *values)
2537 gchar *ver, *p, *str;
2540 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
2541 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
2542 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
2543 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
2546 ver = str = mono_string_to_utf8 (version);
2547 for (i = 0; i < 4; ++i) {
2548 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
2554 /* handle Revision and Build */
2564 load_public_key (MonoString *fname, MonoDynamicAssembly *assembly) {
2565 char *name, *content;
2571 name = mono_string_to_utf8 (fname);
2572 if (g_file_get_contents (name, &content, &len, NULL)) {
2574 char *b = blob_size;
2575 /* check it's a public key or keypair */
2576 mono_metadata_encode_value (len, b, &b);
2577 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
2578 mono_image_add_stream_data (&assembly->blob, content, len);
2580 /* need to get the actual value from the key type... */
2581 assembly->strong_name_size = 128;
2582 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
2584 /* FIXME: how do we tell mcs if loading fails? */
2590 * mono_image_build_metadata() will fill the info in all the needed metadata tables
2591 * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
2592 * and recursively outputs the info for a module. Each module will output all the info
2593 * about it's types etc.
2594 * At the end of the process, method and field tokens are fixed up and the on-disk
2595 * compressed metadata representation is created.
2598 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
2600 MonoDynamicTable *table;
2601 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
2602 MonoDomain *domain = mono_object_domain (assemblyb);
2608 if (assembly->text_rva)
2611 assembly->text_rva = START_TEXT_RVA;
2613 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2614 alloc_table (table, 1);
2615 values = table->values + MONO_ASSEMBLY_SIZE;
2616 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2617 name = mono_string_to_utf8 (assemblyb->name);
2618 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
2620 if (assemblyb->culture) {
2621 name = mono_string_to_utf8 (assemblyb->culture);
2622 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
2625 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2627 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->keyfile, assembly);
2628 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2629 set_version_from_string (assemblyb->version, values);
2631 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2632 table->rows = 1; /* .<Module> */
2634 alloc_table (table, table->rows);
2636 * Set the first entry.
2638 values = table->values + table->columns;
2639 values [MONO_TYPEDEF_FLAGS] = 0;
2640 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2641 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2642 values [MONO_TYPEDEF_EXTENDS] = 0;
2643 values [MONO_TYPEDEF_FIELD_LIST] = 1;
2644 values [MONO_TYPEDEF_METHOD_LIST] = 1;
2647 * handle global methods
2648 * FIXME: test what to do when global methods are defined in multiple modules.
2650 if (assemblyb->modules) {
2651 MonoReflectionModuleBuilder *mod = mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, 0);
2652 if (mod->global_methods) {
2653 table = &assembly->tables [MONO_TABLE_METHOD];
2654 table->rows += mono_array_length (mod->global_methods);
2655 alloc_table (table, table->rows);
2656 for (i = 0; i < mono_array_length (mod->global_methods); ++i)
2657 mono_image_get_method_info (
2658 mono_array_get (mod->global_methods, MonoReflectionMethodBuilder*, i), assembly);
2660 if (mod->global_fields) {
2661 table = &assembly->tables [MONO_TABLE_FIELD];
2662 table->rows += mono_array_length (mod->global_fields);
2663 alloc_table (table, table->rows);
2664 for (i = 0; i < mono_array_length (mod->global_fields); ++i)
2665 mono_image_get_field_info (
2666 mono_array_get (mod->global_fields, MonoReflectionFieldBuilder*, i), assembly);
2670 if (assemblyb->modules) {
2671 len = mono_array_length (assemblyb->modules);
2672 table = &assembly->tables [MONO_TABLE_MODULE];
2673 alloc_table (table, len);
2674 for (i = 0; i < len; ++i)
2675 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
2677 table = &assembly->tables [MONO_TABLE_MODULE];
2679 alloc_table (table, table->rows);
2680 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
2685 if (assemblyb->modules) {
2686 /* Collect all types into a list sorted by their table_idx */
2687 GPtrArray *types = g_ptr_array_new ();
2689 len = mono_array_length (assemblyb->modules);
2690 for (i = 0; i < len; ++i) {
2691 MonoReflectionModuleBuilder *mb =
2692 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2694 for (i = 0; i < mono_array_length (mb->types); ++i) {
2695 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
2696 collect_types (types, type);
2700 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
2701 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2702 table->rows += types->len;
2703 alloc_table (table, table->rows);
2705 for (i = 0; i < types->len; ++i) {
2706 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
2707 mono_image_get_type_info (domain, type, assembly);
2709 g_ptr_array_free (types, TRUE);
2713 * table->rows is already set above and in mono_image_fill_module_table.
2715 /* add all the custom attributes at the end, once all the indexes are stable */
2716 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
2718 if (assemblyb->modules) {
2719 len = mono_array_length (assemblyb->modules);
2720 for (i = 0; i < len; ++i)
2721 module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
2725 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2729 * mono_image_insert_string:
2730 * @assembly: assembly builder object
2733 * Insert @str into the user string stream of @assembly.
2736 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
2742 MONO_ARCH_SAVE_REGS;
2744 if (!assembly->dynamic_assembly)
2745 mono_image_basic_init (assembly);
2747 if (assembly->dynamic_assembly->save) {
2748 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
2749 idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
2750 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2752 char *swapped = g_malloc (2 * mono_string_length (str));
2753 const char *p = (const char*)mono_string_chars (str);
2755 swap_with_size (swapped, p, 2, mono_string_length (str));
2756 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2760 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2762 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2765 idx = assembly->dynamic_assembly->us.index ++;
2767 mono_g_hash_table_insert (assembly->dynamic_assembly->tokens,
2768 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
2770 return MONO_TOKEN_STRING | idx;
2774 * mono_image_create_token:
2775 * @assembly: a dynamic assembly
2778 * Get a token to insert in the IL code stream for the given MemberInfo.
2779 * @obj can be one of:
2780 * ConstructorBuilder
2790 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2795 klass = obj->vtable->klass;
2796 if (strcmp (klass->name, "MethodBuilder") == 0) {
2797 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2798 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2799 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2801 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2802 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2803 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2804 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2806 else if (strcmp (klass->name, "FieldBuilder") == 0) {
2807 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2808 token = mb->table_idx | MONO_TOKEN_FIELD_DEF;
2810 else if (strcmp (klass->name, "TypeBuilder") == 0) {
2811 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2812 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
2814 else if (strcmp (klass->name, "MonoType") == 0) {
2815 MonoReflectionType *tb = (MonoReflectionType *)obj;
2816 token = mono_metadata_token_from_dor (
2817 mono_image_typedef_or_ref (assembly, tb->type));
2819 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
2820 strcmp (klass->name, "MonoMethod") == 0) {
2821 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2822 if (m->method->klass->image == assembly->assembly.image) {
2823 static guint32 method_table_idx = 0xffffff;
2825 * Each token should have a unique index, but the indexes are
2826 * assigned by managed code, so we don't know about them. An
2827 * easy solution is to count backwards...
2829 method_table_idx --;
2830 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
2832 token = mono_image_get_methodref_token (assembly, m->method);
2833 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2835 else if (strcmp (klass->name, "MonoField") == 0) {
2836 MonoReflectionField *f = (MonoReflectionField *)obj;
2837 if (f->klass->image == assembly->assembly.image) {
2838 static guint32 field_table_idx = 0xffffff;
2840 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
2842 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2843 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2845 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2846 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2847 token = mono_image_get_array_token (assembly, m);
2849 else if (strcmp (klass->name, "SignatureHelper") == 0) {
2850 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
2851 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
2854 g_error ("requested token for %s\n", klass->name);
2856 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
2863 guint32 import_lookup_table;
2867 guint32 import_address_table_rva;
2875 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
2878 create_dynamic_mono_image (char *assembly_name, char *module_name)
2883 * We need to use the current ms version or the ms runtime it won't find
2884 * the support dlls. D'oh!
2885 * const char *version = "mono-" VERSION;
2887 const char *version = "v1.0.3705";
2889 image = g_new0 (MonoImage, 1);
2891 /* keep in sync with image.c */
2892 image->name = assembly_name;
2893 image->assembly_name = image->name; /* they may be different */
2894 image->module_name = module_name;
2895 image->version = g_strdup (version);
2897 image->references = g_new0 (MonoAssembly*, 1);
2898 image->references [0] = NULL;
2900 image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2901 image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2902 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2903 image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2905 image->delegate_begin_invoke_cache =
2906 g_hash_table_new ((GHashFunc)mono_signature_hash,
2907 (GCompareFunc)mono_metadata_signature_equal);
2908 image->delegate_end_invoke_cache =
2909 g_hash_table_new ((GHashFunc)mono_signature_hash,
2910 (GCompareFunc)mono_metadata_signature_equal);
2911 image->delegate_invoke_cache =
2912 g_hash_table_new ((GHashFunc)mono_signature_hash,
2913 (GCompareFunc)mono_metadata_signature_equal);
2915 image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2916 image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2917 image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2918 image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2919 image->synchronized_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2925 * mono_image_basic_init:
2926 * @assembly: an assembly builder object
2928 * Create the MonoImage that represents the assembly builder and setup some
2929 * of the helper hash table and the basic metadata streams.
2932 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2934 static const guchar entrycode [16] = {0xff, 0x25, 0};
2935 MonoDynamicAssembly *assembly;
2939 MONO_ARCH_SAVE_REGS;
2941 if (assemblyb->dynamic_assembly)
2945 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
2947 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2950 assembly->assembly.dynamic = assembly;
2951 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
2952 assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2953 assembly->method_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2954 assembly->field_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2955 assembly->param_marshalling = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2956 assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2957 assembly->tokens = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2958 assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2959 assembly->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
2961 string_heap_init (&assembly->sheap);
2962 mono_image_add_stream_data (&assembly->us, "", 1);
2963 add_to_blob_cached (assembly, (char*) "", 1, NULL, 0);
2964 /* import tables... */
2965 mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2966 assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2967 assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2968 mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2969 assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2970 mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2971 assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2972 stream_data_align (&assembly->code);
2974 assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2976 for (i=0; i < 64; ++i) {
2977 assembly->tables [i].next_idx = 1;
2978 assembly->tables [i].columns = table_sizes [i];
2981 assembly->run = assemblyb->access != 2;
2982 assembly->save = assemblyb->access != 1;
2984 image = create_dynamic_mono_image (mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
2985 assembly->assembly.aname.name = image->name;
2986 image->assembly = (MonoAssembly*)assembly;
2987 assembly->assembly.image = image;
2989 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
2990 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
2994 calc_section_size (MonoDynamicAssembly *assembly)
2998 /* alignment constraints */
2999 assembly->code.index += 3;
3000 assembly->code.index &= ~3;
3001 assembly->meta_size += 3;
3002 assembly->meta_size &= ~3;
3003 assembly->resources.index += 3;
3004 assembly->resources.index &= ~3;
3006 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
3007 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
3010 assembly->sections [MONO_SECTION_RELOC].size = 12;
3011 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
3018 * mono_image_create_pefile:
3019 * @assemblyb: an assembly builder object
3021 * When we need to save an assembly, we first call this function that ensures the metadata
3022 * tables are built for all the modules in the assembly. This function creates the PE-COFF
3023 * header, the image sections, the CLI header etc. all the data is written in
3024 * assembly->pefile where it can be easily retrieved later in chunks.
3027 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
3028 MonoMSDOSHeader *msdos;
3029 MonoDotNetHeader *header;
3030 MonoSectionTable *section;
3031 MonoCLIHeader *cli_header;
3032 guint32 size, image_size, virtual_base, text_offset;
3033 guint32 header_start, section_start, file_offset, virtual_offset;
3034 MonoDynamicAssembly *assembly;
3035 MonoDynamicStream *pefile;
3037 guint32 *rva, value;
3040 static const unsigned char msheader[] = {
3041 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
3042 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3043 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3044 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
3045 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
3046 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
3047 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
3048 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3051 mono_image_basic_init (assemblyb);
3052 assembly = assemblyb->dynamic_assembly;
3054 /* already created */
3055 if (assembly->pefile.index)
3058 mono_image_build_metadata (assemblyb);
3060 if (assemblyb->resources) {
3061 int len = mono_array_length (assemblyb->resources);
3062 for (i = 0; i < len; ++i)
3063 assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
3067 build_compressed_metadata (assembly);
3069 nsections = calc_section_size (assembly);
3071 pefile = &assembly->pefile;
3073 /* The DOS header and stub */
3074 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
3075 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
3077 /* the dotnet header */
3078 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
3080 /* the section tables */
3081 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
3083 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
3084 virtual_offset = VIRT_ALIGN;
3087 for (i = 0; i < MONO_SECTION_MAX; ++i) {
3088 if (!assembly->sections [i].size)
3091 file_offset += FILE_ALIGN - 1;
3092 file_offset &= ~(FILE_ALIGN - 1);
3093 virtual_offset += VIRT_ALIGN - 1;
3094 virtual_offset &= ~(VIRT_ALIGN - 1);
3096 assembly->sections [i].offset = file_offset;
3097 assembly->sections [i].rva = virtual_offset;
3099 file_offset += assembly->sections [i].size;
3100 virtual_offset += assembly->sections [i].size;
3101 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
3104 file_offset += FILE_ALIGN - 1;
3105 file_offset &= ~(FILE_ALIGN - 1);
3106 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
3108 image_size += section_start + sizeof (MonoSectionTable) * nsections;
3110 /* back-patch info */
3111 msdos = (MonoMSDOSHeader*)pefile->data;
3112 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
3113 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
3114 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
3116 header = (MonoDotNetHeader*)(pefile->data + header_start);
3117 header->pesig [0] = 'P';
3118 header->pesig [1] = 'E';
3120 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
3121 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
3122 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
3123 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
3124 if (assemblyb->pekind == 1) {
3126 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
3129 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
3132 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
3134 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
3135 header->pe.pe_major = 6;
3136 header->pe.pe_minor = 0;
3137 size = assembly->sections [MONO_SECTION_TEXT].size;
3138 size += FILE_ALIGN - 1;
3139 size &= ~(FILE_ALIGN - 1);
3140 header->pe.pe_code_size = size;
3141 size = assembly->sections [MONO_SECTION_RSRC].size;
3142 size += FILE_ALIGN - 1;
3143 size &= ~(FILE_ALIGN - 1);
3144 header->pe.pe_data_size = size;
3145 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
3146 header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
3147 header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
3148 /* pe_rva_entry_point always at the beginning of the text section */
3149 header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
3151 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
3152 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
3153 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
3154 header->nt.pe_os_major = GUINT16_FROM_LE (4);
3155 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
3156 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
3157 size = section_start;
3158 size += FILE_ALIGN - 1;
3159 size &= ~(FILE_ALIGN - 1);
3160 header->nt.pe_header_size = GUINT32_FROM_LE (size);
3162 size += VIRT_ALIGN - 1;
3163 size &= ~(VIRT_ALIGN - 1);
3164 header->nt.pe_image_size = GUINT32_FROM_LE (size);
3167 // Translate the PEFileKind value to the value expected by the Windows loader
3170 short kind = assemblyb->pekind;
3173 // PEFileKinds.ConsoleApplication == 2
3174 // PEFileKinds.WindowApplication == 3
3177 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
3178 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
3184 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
3186 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
3187 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
3188 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
3189 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
3190 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
3191 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
3193 /* fill data directory entries */
3195 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
3196 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
3198 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
3199 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
3201 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
3202 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
3203 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
3204 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
3205 /* patch imported function RVA name */
3206 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
3207 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
3209 /* the import table */
3210 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
3211 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
3212 /* patch imported dll RVA name and other entries in the dir */
3213 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
3214 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
3215 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
3216 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
3217 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
3218 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
3220 p = (assembly->code.data + assembly->ilt_offset);
3221 value = (assembly->text_rva + assembly->imp_names_offset - 2);
3222 *p++ = (value) & 0xff;
3223 *p++ = (value >> 8) & (0xff);
3224 *p++ = (value >> 16) & (0xff);
3225 *p++ = (value >> 24) & (0xff);
3227 /* the CLI header info */
3228 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
3229 cli_header->ch_size = GUINT32_FROM_LE (72);
3230 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
3231 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
3232 if (assemblyb->entry_point)
3233 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
3235 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
3236 /* The embedded managed resources */
3237 text_offset = assembly->text_rva + assembly->code.index;
3238 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
3239 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
3240 text_offset += assembly->resources.index;
3241 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
3242 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
3243 text_offset += assembly->meta_size;
3244 if (assembly->strong_name_size) {
3245 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
3246 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
3247 text_offset += assembly->strong_name_size;
3250 /* write the section tables and section content */
3251 section = (MonoSectionTable*)(pefile->data + section_start);
3252 for (i = 0; i < MONO_SECTION_MAX; ++i) {
3253 static const char *section_names [] = {
3254 ".text", ".rsrc", ".reloc"
3256 if (!assembly->sections [i].size)
3258 strcpy (section->st_name, section_names [i]);
3259 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
3260 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
3261 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
3262 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
3263 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
3264 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
3265 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
3267 case MONO_SECTION_TEXT:
3268 /* patch entry point */
3269 p = (assembly->code.data + 2);
3270 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
3271 *p++ = (value) & 0xff;
3272 *p++ = (value >> 8) & 0xff;
3273 *p++ = (value >> 16) & 0xff;
3274 *p++ = (value >> 24) & 0xff;
3276 text_offset = assembly->sections [i].offset;
3277 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
3278 text_offset += assembly->code.index;
3279 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
3280 text_offset += assembly->resources.index;
3281 memcpy (pefile->data + text_offset, assembly->assembly.image->raw_metadata, assembly->meta_size);
3282 text_offset += assembly->meta_size;
3283 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
3285 g_free (assembly->assembly.image->raw_metadata);
3287 case MONO_SECTION_RELOC:
3288 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
3289 *rva = GUINT32_FROM_LE (assembly->text_rva);
3291 *rva = GUINT32_FROM_LE (12);
3293 data16 = (guint16*)rva;
3295 * the entrypoint is always at the start of the text section
3296 * 3 is IMAGE_REL_BASED_HIGHLOW
3297 * 2 is patch_size_rva - text_rva
3299 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
3301 *data16 = 0; /* terminate */
3303 case MONO_SECTION_RSRC:
3305 g_assert_not_reached ();
3310 /* check that the file is properly padded */
3313 FILE *f = fopen ("mypetest.exe", "w");
3314 fwrite (pefile->data, pefile->index, 1, f);
3321 * We need to return always the same object for MethodInfo, FieldInfo etc..
3322 * but we need to consider the reflected type.
3323 * type uses a different hash, since it uses custom hash/equal functions.
3328 MonoClass *refclass;
3332 reflected_equal (gconstpointer a, gconstpointer b) {
3333 const ReflectedEntry *ea = a;
3334 const ReflectedEntry *eb = b;
3336 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
3340 reflected_hash (gconstpointer a) {
3341 const ReflectedEntry *ea = a;
3342 return GPOINTER_TO_UINT (ea->item);
3345 #define CHECK_OBJECT(t,p,k) \
3351 mono_domain_lock (domain); \
3352 if (!domain->refobject_hash) \
3353 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
3354 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
3355 mono_domain_unlock (domain); \
3361 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
3363 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
3366 #define CACHE_OBJECT(p,o,k) \
3368 ReflectedEntry *e = ALLOC_REFENTRY; \
3370 e->refclass = (k); \
3371 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
3372 mono_domain_unlock (domain); \
3376 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
3378 /* this is done only once */
3379 mono_domain_lock (domain);
3380 CACHE_OBJECT (assembly, res, NULL);
3384 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoImage *module)
3386 /* this is done only once */
3387 mono_domain_lock (domain);
3388 CACHE_OBJECT (module, res, NULL);
3392 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
3394 MonoImage *image = moduleb->module.image;
3395 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
3398 /* a MonoImage was already created in mono_image_basic_init () */
3399 image = ab->dynamic_assembly->assembly.image;
3401 image = create_dynamic_mono_image (mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.name));
3403 moduleb->module.image = image;
3404 register_module (mono_object_domain (moduleb), moduleb, image);
3409 * mono_assembly_get_object:
3410 * @domain: an app domain
3411 * @assembly: an assembly
3413 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
3415 MonoReflectionAssembly*
3416 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
3418 static MonoClass *System_Reflection_Assembly;
3419 MonoReflectionAssembly *res;
3421 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
3422 if (!System_Reflection_Assembly)
3423 System_Reflection_Assembly = mono_class_from_name (
3424 mono_defaults.corlib, "System.Reflection", "Assembly");
3425 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
3426 res->assembly = assembly;
3427 CACHE_OBJECT (assembly, res, NULL);
3433 MonoReflectionModule*
3434 mono_module_get_object (MonoDomain *domain, MonoImage *image)
3436 static MonoClass *System_Reflection_Module;
3437 MonoReflectionModule *res;
3439 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
3440 if (!System_Reflection_Module)
3441 System_Reflection_Module = mono_class_from_name (
3442 mono_defaults.corlib, "System.Reflection", "Module");
3443 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
3446 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
3448 res->fqname = mono_string_new (domain, image->name);
3449 res->name = mono_string_new (domain, image->name);
3450 res->scopename = mono_string_new (domain, image->module_name);
3452 CACHE_OBJECT (image, res, NULL);
3456 MonoReflectionModule*
3457 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
3459 static MonoClass *System_Reflection_Module;
3460 MonoReflectionModule *res;
3461 MonoTableInfo *table;
3462 guint32 cols [MONO_FILE_SIZE];
3464 guint32 i, name_idx;
3467 if (!System_Reflection_Module)
3468 System_Reflection_Module = mono_class_from_name (
3469 mono_defaults.corlib, "System.Reflection", "Module");
3470 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
3472 table = &image->tables [MONO_TABLE_FILE];
3473 g_assert (table_index < table->rows);
3474 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
3477 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
3478 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
3480 // Check whenever the row has a corresponding row in the moduleref table
3481 table = &image->tables [MONO_TABLE_MODULEREF];
3482 for (i = 0; i < table->rows; ++i) {
3483 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
3484 val = mono_metadata_string_heap (image, name_idx);
3485 if (strcmp (val, name) == 0)
3486 res->image = image->modules [i];
3489 res->fqname = mono_string_new (domain, name);
3490 res->name = mono_string_new (domain, name);
3491 res->scopename = mono_string_new (domain, name);
3492 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
3498 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
3500 if ((t1->type != t2->type) ||
3501 (t1->byref != t2->byref))
3505 case MONO_TYPE_VOID:
3506 case MONO_TYPE_BOOLEAN:
3507 case MONO_TYPE_CHAR:
3518 case MONO_TYPE_STRING:
3521 case MONO_TYPE_OBJECT:
3522 case MONO_TYPE_TYPEDBYREF:
3524 case MONO_TYPE_VALUETYPE:
3525 case MONO_TYPE_CLASS:
3526 case MONO_TYPE_SZARRAY:
3527 return t1->data.klass == t2->data.klass;
3529 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3530 case MONO_TYPE_ARRAY:
3531 if (t1->data.array->rank != t2->data.array->rank)
3533 return t1->data.array->eklass == t2->data.array->eklass;
3534 case MONO_TYPE_GENERICINST: {
3536 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
3538 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
3540 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
3541 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
3547 case MONO_TYPE_MVAR:
3548 return t1->data.type_param == t2->data.type_param;
3550 g_error ("implement type compare for %0x!", t1->type);
3558 mymono_metadata_type_hash (MonoType *t1)
3564 hash |= t1->byref << 6; /* do not collide with t1->type values */
3566 case MONO_TYPE_VALUETYPE:
3567 case MONO_TYPE_CLASS:
3568 case MONO_TYPE_SZARRAY:
3569 /* check if the distribution is good enough */
3570 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
3572 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
3578 * mono_type_get_object:
3579 * @domain: an app domain
3582 * Return an System.MonoType object representing the type @type.
3585 mono_type_get_object (MonoDomain *domain, MonoType *type)
3587 MonoReflectionType *res;
3588 MonoClass *klass = mono_class_from_mono_type (type);
3590 mono_domain_lock (domain);
3591 if (!domain->type_hash)
3592 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
3593 (GCompareFunc)mymono_metadata_type_equal);
3594 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
3595 mono_domain_unlock (domain);
3598 if (klass->reflection_info && !klass->wastypebuilder) {
3599 //g_assert_not_reached ();
3600 /* should this be considered an error condition? */
3602 mono_domain_unlock (domain);
3603 return klass->reflection_info;
3606 mono_class_init (klass);
3607 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
3609 mono_g_hash_table_insert (domain->type_hash, type, res);
3610 mono_domain_unlock (domain);
3615 * mono_method_get_object:
3616 * @domain: an app domain
3618 * @refclass: the reflected type (can be NULL)
3620 * Return an System.Reflection.MonoMethod object representing the method @method.
3622 MonoReflectionMethod*
3623 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
3626 * We use the same C representation for methods and constructors, but the type
3627 * name in C# is different.
3631 MonoReflectionMethod *ret;
3634 refclass = method->klass;
3636 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
3637 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3638 cname = "MonoCMethod";
3640 cname = "MonoMethod";
3641 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
3643 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
3644 ret->method = method;
3645 ret->name = mono_string_new (domain, method->name);
3646 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
3647 CACHE_OBJECT (method, ret, refclass);
3652 * mono_field_get_object:
3653 * @domain: an app domain
3657 * Return an System.Reflection.MonoField object representing the field @field
3660 MonoReflectionField*
3661 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
3663 MonoReflectionField *res;
3666 CHECK_OBJECT (MonoReflectionField *, field, klass);
3667 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
3668 res = (MonoReflectionField *)mono_object_new (domain, oklass);
3671 res->name = mono_string_new (domain, field->name);
3672 res->attrs = field->type->attrs;
3673 res->type = mono_type_get_object (domain, field->type);
3674 CACHE_OBJECT (field, res, klass);
3679 * mono_property_get_object:
3680 * @domain: an app domain
3682 * @property: a property
3684 * Return an System.Reflection.MonoProperty object representing the property @property
3687 MonoReflectionProperty*
3688 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
3690 MonoReflectionProperty *res;
3693 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
3694 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
3695 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
3697 res->property = property;
3698 CACHE_OBJECT (property, res, klass);
3703 * mono_event_get_object:
3704 * @domain: an app domain
3708 * Return an System.Reflection.MonoEvent object representing the event @event
3711 MonoReflectionEvent*
3712 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
3714 MonoReflectionEvent *res;
3717 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
3718 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
3719 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
3722 CACHE_OBJECT (event, res, klass);
3727 * mono_param_get_objects:
3728 * @domain: an app domain
3731 * Return an System.Reflection.ParameterInfo array object representing the parameters
3732 * in the method @method.
3735 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
3737 static MonoClass *System_Reflection_ParameterInfo;
3738 MonoArray *res = NULL;
3739 MonoReflectionMethod *member = NULL;
3740 MonoReflectionParameter *param = NULL;
3744 if (!System_Reflection_ParameterInfo)
3745 System_Reflection_ParameterInfo = mono_class_from_name (
3746 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
3748 if (!method->signature->param_count)
3749 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
3751 /* Note: the cache is based on the address of the signature into the method
3752 * since we already cache MethodInfos with the method as keys.
3754 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
3756 member = mono_method_get_object (domain, method, NULL);
3757 names = g_new (char *, method->signature->param_count);
3758 mono_method_get_param_names (method, (const char **) names);
3760 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
3761 for (i = 0; i < method->signature->param_count; ++i) {
3762 param = (MonoReflectionParameter *)mono_object_new (domain,
3763 System_Reflection_ParameterInfo);
3764 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
3765 param->DefaultValueImpl = NULL; /* FIXME */
3766 param->MemberImpl = (MonoObject*)member;
3767 param->NameImpl = mono_string_new (domain, names [i]);
3768 param->PositionImpl = i;
3769 param->AttrsImpl = method->signature->params [i]->attrs;
3770 mono_array_set (res, gpointer, i, param);
3773 CACHE_OBJECT (&(method->signature), res, NULL);
3778 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
3782 memset (assembly, 0, sizeof (MonoAssemblyName));
3784 assembly->culture = "";
3786 while (*p && (isalnum (*p) || *p == '.' || *p == '-'))
3789 while (*p == ' ' || *p == ',') {
3798 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
3800 assembly->major = strtoul (p, &s, 10);
3801 if (s == p || *s != '.')
3804 assembly->minor = strtoul (p, &s, 10);
3805 if (s == p || *s != '.')
3808 assembly->build = strtoul (p, &s, 10);
3809 if (s == p || *s != '.')
3812 assembly->revision = strtoul (p, &s, 10);
3815 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
3817 if (strncmp (p, "neutral", 7) == 0) {
3818 assembly->culture = "";
3821 assembly->culture = p;
3822 while (*p && *p != ',') {
3826 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
3829 while (*s && isxdigit (*s)) {
3833 assembly->hash_len = s - p;
3834 if (!(s-p) || ((s-p) & 1))
3836 assembly->hash_value = s = p;
3837 while (*s && isxdigit (*s)) {
3839 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3842 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3847 while (*p && *p != ',')
3851 while (*p == ' ' || *p == ',') {
3865 * mono_reflection_parse_type:
3868 * Parse a type name as accepted by the GetType () method and output the info
3869 * extracted in the info structure.
3870 * the name param will be mangled, so, make a copy before passing it to this function.
3871 * The fields in info will be valid until the memory pointed to by name is valid.
3872 * Returns 0 on parse error.
3873 * See also mono_type_get_name () below.
3876 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
3878 char *start, *p, *w, *last_point, *startn;
3879 int in_modifiers = 0;
3880 int isbyref = 0, rank;
3882 start = p = w = name;
3884 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
3885 info->name = info->name_space = NULL;
3886 info->nested = NULL;
3887 info->modifiers = NULL;
3889 /* last_point separates the namespace from the name */
3895 *p = 0; /* NULL terminate the name */
3897 info->nested = g_list_append (info->nested, startn);
3898 /* we have parsed the nesting namespace + name */
3902 info->name_space = start;
3904 info->name = last_point + 1;
3906 info->name_space = (char *)"";
3932 info->name_space = start;
3934 info->name = last_point + 1;
3936 info->name_space = (char *)"";
3943 if (isbyref) /* only one level allowed by the spec */
3946 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
3950 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
3961 else if (*p != '*') /* '*' means unknown lower bound */
3967 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
3979 return 0; /* missing assembly name */
3980 if (!assembly_name_to_aname (&info->assembly, p))
3986 if (info->assembly.name)
3989 *w = 0; /* terminate class name */
3990 if (!info->name || !*info->name)
3992 /* add other consistency checks */
3997 mono_type_get_name_recurse (MonoType *type, GString *str)
4001 switch (type->type) {
4002 case MONO_TYPE_ARRAY: {
4003 int i, rank = type->data.array->rank;
4005 mono_type_get_name_recurse (&type->data.array->eklass->byval_arg, str);
4006 g_string_append_c (str, '[');
4007 for (i = 1; i < rank; i++)
4008 g_string_append_c (str, ',');
4009 g_string_append_c (str, ']');
4012 case MONO_TYPE_SZARRAY:
4013 mono_type_get_name_recurse (&type->data.klass->byval_arg, str);
4014 g_string_append (str, "[]");
4017 mono_type_get_name_recurse (type->data.type, str);
4018 g_string_append_c (str, '*');
4021 klass = mono_class_from_mono_type (type);
4022 if (klass->nested_in) {
4023 mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
4024 g_string_append_c (str, '+');
4026 if (*klass->name_space) {
4027 g_string_append (str, klass->name_space);
4028 g_string_append_c (str, '.');
4030 g_string_append (str, klass->name);
4036 * mono_type_get_name:
4039 * Returns the string representation for type as required by System.Reflection.
4040 * The inverse of mono_reflection_parse_type ().
4043 mono_type_get_name (MonoType *type)
4045 GString* result = g_string_new ("");
4046 mono_type_get_name_recurse (type, result);
4049 g_string_append_c (result, '&');
4051 return g_string_free (result, FALSE);
4055 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
4062 image = mono_defaults.corlib;
4065 klass = mono_class_from_name_case (image, info->name_space, info->name);
4067 klass = mono_class_from_name (image, info->name_space, info->name);
4070 for (mod = info->nested; mod; mod = mod->next) {
4073 mono_class_init (klass);
4074 nested = klass->nested_classes;
4077 klass = nested->data;
4079 if (g_strcasecmp (klass->name, mod->data) == 0)
4082 if (strcmp (klass->name, mod->data) == 0)
4086 nested = nested->next;
4093 mono_class_init (klass);
4094 for (mod = info->modifiers; mod; mod = mod->next) {
4095 modval = GPOINTER_TO_UINT (mod->data);
4096 if (!modval) { /* byref: must be last modifier */
4097 return &klass->this_arg;
4098 } else if (modval == -1) {
4099 klass = mono_ptr_class_get (&klass->byval_arg);
4100 } else { /* array rank */
4101 klass = mono_array_class_get (klass, modval);
4103 mono_class_init (klass);
4106 return &klass->byval_arg;
4110 * mono_reflection_get_type:
4111 * @image: a metadata context
4112 * @info: type description structure
4113 * @ignorecase: flag for case-insensitive string compares
4115 * Build a MonoType from the type description in @info.
4120 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
4123 MonoReflectionAssembly *assembly;
4127 type = mono_reflection_get_type_internal (image, info, ignorecase);
4130 if (!mono_domain_has_type_resolve (mono_domain_get ()))
4133 // Reconstruct the type name
4134 fullName = g_string_new ("");
4135 if (info->name_space && (info->name_space [0] != '\0'))
4136 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
4138 g_string_printf (fullName, info->name);
4139 for (mod = info->nested; mod; mod = mod->next)
4140 g_string_append_printf (fullName, "+%s", (char*)mod->data);
4143 mono_domain_try_type_resolve (
4144 mono_domain_get (), fullName->str, NULL);
4145 if (assembly && (!image || (assembly->assembly->image == image)))
4146 type = mono_reflection_get_type_internal (assembly->assembly->image,
4148 g_string_free (fullName, TRUE);
4153 * mono_reflection_type_from_name:
4155 * @image: a metadata context (can be NULL).
4157 * Retrieves a MonoType from its @name. If the name is not fully qualified,
4158 * it defaults to get the type from @image or, if @image is NULL or loading
4159 * from it fails, uses corlib.
4163 mono_reflection_type_from_name (char *name, MonoImage *image)
4166 MonoTypeNameParse info;
4168 /*g_print ("requested type %s\n", str);*/
4169 if (!mono_reflection_parse_type (name, &info)) {
4170 g_list_free (info.modifiers);
4171 g_list_free (info.nested);
4175 if (info.assembly.name) {
4176 image = mono_image_loaded (info.assembly.name);
4177 /* do we need to load if it's not already loaded? */
4179 g_list_free (info.modifiers);
4180 g_list_free (info.nested);
4183 } else if (image == NULL) {
4184 image = mono_defaults.corlib;
4187 type = mono_reflection_get_type (image, &info, FALSE);
4188 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
4189 image = mono_defaults.corlib;
4190 type = mono_reflection_get_type (image, &info, FALSE);
4193 g_list_free (info.modifiers);
4194 g_list_free (info.nested);
4199 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
4201 int slen, type = t->type;
4206 case MONO_TYPE_BOOLEAN: {
4207 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
4212 case MONO_TYPE_CHAR:
4214 case MONO_TYPE_I2: {
4215 guint16 *val = g_malloc (sizeof (guint16));
4220 #if SIZEOF_VOID_P == 4
4226 case MONO_TYPE_I4: {
4227 guint32 *val = g_malloc (sizeof (guint32));
4232 #if SIZEOF_VOID_P == 8
4233 case MONO_TYPE_U: /* error out instead? this should probably not happen */
4238 case MONO_TYPE_I8: {
4239 guint64 *val = g_malloc (sizeof (guint64));
4244 case MONO_TYPE_VALUETYPE:
4245 if (t->data.klass->enumtype) {
4246 type = t->data.klass->enum_basetype->type;
4249 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
4252 case MONO_TYPE_STRING:
4253 if (*p == (char)0xFF) {
4257 slen = mono_metadata_decode_value (p, &p);
4259 return mono_string_new_len (mono_domain_get (), p, slen);
4260 case MONO_TYPE_CLASS: {
4263 if (*p == (char)0xFF) {
4268 slen = mono_metadata_decode_value (p, &p);
4269 n = g_memdup (p, slen + 1);
4271 t = mono_reflection_type_from_name (n, image);
4273 g_warning ("Cannot load type '%s'", n);
4276 return mono_type_get_object (mono_domain_get (), t);
4278 case MONO_TYPE_OBJECT: {
4286 } else if (subt == 0x0E) {
4287 type = MONO_TYPE_STRING;
4289 } else if (subt == 0x55) {
4292 slen = mono_metadata_decode_value (p, &p);
4293 n = g_memdup (p, slen + 1);
4295 t = mono_reflection_type_from_name (n, image);
4297 g_warning ("Cannot load type '%s'", n);
4300 subc = mono_class_from_mono_type (t);
4301 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
4302 MonoType simple_type = {{0}};
4303 simple_type.type = subt;
4304 subc = mono_class_from_mono_type (&simple_type);
4306 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
4308 val = load_cattr_value (image, &subc->byval_arg, p, end);
4309 obj = mono_object_new (mono_domain_get (), subc);
4310 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
4314 case MONO_TYPE_SZARRAY:
4317 guint32 i, alen, basetype;
4320 if (alen == 0xffffffff) {
4324 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
4325 basetype = t->data.klass->byval_arg.type;
4330 case MONO_TYPE_BOOLEAN:
4331 for (i=0;i<alen;i++)
4333 MonoBoolean val=*p++;
4334 mono_array_set(arr,MonoBoolean,i,val);
4337 case MONO_TYPE_CHAR:
4340 for (i=0;i<alen;i++)
4342 guint16 val=read16(p);
4343 mono_array_set(arr,guint16,i,val);
4350 for (i=0;i<alen;i++)
4352 guint32 val=read32(p);
4353 mono_array_set(arr,guint32,i,val);
4360 for (i=0;i<alen;i++)
4362 guint64 val=read64(p);
4363 mono_array_set(arr,guint64,i,val);
4367 case MONO_TYPE_CLASS:
4368 case MONO_TYPE_STRING:
4369 for (i = 0; i < alen; i++) {
4370 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
4371 mono_array_set (arr, gpointer, i, item);
4375 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
4381 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
4387 type_is_reference (MonoType *type)
4389 switch (type->type) {
4390 case MONO_TYPE_BOOLEAN:
4391 case MONO_TYPE_CHAR:
4404 case MONO_TYPE_VALUETYPE:
4412 free_param_data (MonoMethodSignature *sig, void **params) {
4414 for (i = 0; i < sig->param_count; ++i) {
4415 if (!type_is_reference (sig->params [i]))
4416 g_free (params [i]);
4421 * Find the method index in the metadata methodDef table.
4422 * Later put these three helper methods in metadata and export them.
4425 find_method_index (MonoMethod *method) {
4426 MonoClass *klass = method->klass;
4429 for (i = 0; i < klass->method.count; ++i) {
4430 if (method == klass->methods [i])
4431 return klass->method.first + 1 + i;
4437 * Find the field index in the metadata FieldDef table.
4440 find_field_index (MonoClass *klass, MonoClassField *field) {
4443 for (i = 0; i < klass->field.count; ++i) {
4444 if (field == &klass->fields [i])
4445 return klass->field.first + 1 + i;
4451 * Find the property index in the metadata Property table.
4454 find_property_index (MonoClass *klass, MonoProperty *property) {
4457 for (i = 0; i < klass->property.count; ++i) {
4458 if (property == &klass->properties [i])
4459 return klass->property.first + 1 + i;
4465 * Find the event index in the metadata Event table.
4468 find_event_index (MonoClass *klass, MonoEvent *event) {
4471 for (i = 0; i < klass->event.count; ++i) {
4472 if (event == &klass->events [i])
4473 return klass->event.first + 1 + i;
4479 create_custom_attr (MonoImage *image, MonoMethod *method,
4480 const char *data, guint32 len)
4482 const char *p = data;
4484 guint32 i, j, num_named;
4488 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
4491 mono_class_init (method->klass);
4492 /*g_print ("got attr %s\n", method->klass->name);*/
4494 params = g_new (void*, method->signature->param_count);
4498 for (i = 0; i < method->signature->param_count; ++i) {
4499 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
4503 attr = mono_object_new (mono_domain_get (), method->klass);
4504 mono_runtime_invoke (method, attr, params, NULL);
4505 free_param_data (method->signature, params);
4507 num_named = read16 (named);
4509 for (j = 0; j < num_named; j++) {
4511 char *name, named_type, data_type;
4512 named_type = *named++;
4513 data_type = *named++; /* type of data */
4514 if (data_type == 0x55) {
4517 type_len = mono_metadata_decode_blob_size (named, &named);
4518 type_name = g_malloc (type_len + 1);
4519 memcpy (type_name, named, type_len);
4520 type_name [type_len] = 0;
4522 /* FIXME: lookup the type and check type consistency */
4524 name_len = mono_metadata_decode_blob_size (named, &named);
4525 name = g_malloc (name_len + 1);
4526 memcpy (name, named, name_len);
4527 name [name_len] = 0;
4529 if (named_type == 0x53) {
4530 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
4531 void *val = load_cattr_value (image, field->type, named, &named);
4532 mono_field_set_value (attr, field, val);
4533 if (!type_is_reference (field->type))
4535 } else if (named_type == 0x54) {
4538 MonoType *prop_type;
4540 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
4541 /* can we have more that 1 arg in a custom attr named property? */
4542 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
4543 pparams [0] = load_cattr_value (image, prop_type, named, &named);
4544 mono_property_set_value (prop, attr, pparams, NULL);
4545 if (!type_is_reference (prop_type))
4546 g_free (pparams [0]);
4555 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
4562 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
4563 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
4564 for (i = 0; i < cinfo->num_attrs; ++i) {
4565 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
4566 mono_array_set (result, gpointer, i, attr);
4572 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
4574 guint32 mtoken, i, len;
4575 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
4577 MonoCustomAttrInfo *ainfo;
4578 GList *tmp, *list = NULL;
4581 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4582 /* the table is not sorted */
4583 for (i = 0; i < ca->rows; ++i) {
4584 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
4586 list = g_list_prepend (list, GUINT_TO_POINTER (i));
4588 len = g_list_length (list);
4591 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
4592 ainfo->num_attrs = len;
4593 ainfo->image = image;
4594 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
4595 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
4596 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
4597 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
4598 case CUSTOM_ATTR_TYPE_METHODDEF:
4599 mtoken |= MONO_TOKEN_METHOD_DEF;
4601 case CUSTOM_ATTR_TYPE_MEMBERREF:
4602 mtoken |= MONO_TOKEN_MEMBER_REF;
4605 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
4608 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
4609 if (!ainfo->attrs [i].ctor)
4610 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
4611 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
4612 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
4613 ainfo->attrs [i].data = data;
4621 mono_custom_attrs_from_method (MonoMethod *method)
4623 MonoCustomAttrInfo *cinfo;
4626 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
4628 idx = find_method_index (method);
4629 idx <<= CUSTOM_ATTR_BITS;
4630 idx |= CUSTOM_ATTR_METHODDEF;
4631 return mono_custom_attrs_from_index (method->klass->image, idx);
4635 mono_custom_attrs_from_class (MonoClass *klass)
4637 MonoCustomAttrInfo *cinfo;
4640 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
4642 idx = mono_metadata_token_index (klass->type_token);
4643 idx <<= CUSTOM_ATTR_BITS;
4644 idx |= CUSTOM_ATTR_TYPEDEF;
4645 return mono_custom_attrs_from_index (klass->image, idx);
4649 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
4651 MonoCustomAttrInfo *cinfo;
4654 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
4656 idx = 1; /* there is only one assembly */
4657 idx <<= CUSTOM_ATTR_BITS;
4658 idx |= CUSTOM_ATTR_ASSEMBLY;
4659 return mono_custom_attrs_from_index (assembly->image, idx);
4663 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
4665 MonoCustomAttrInfo *cinfo;
4668 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
4670 idx = find_property_index (klass, property);
4671 idx <<= CUSTOM_ATTR_BITS;
4672 idx |= CUSTOM_ATTR_PROPERTY;
4673 return mono_custom_attrs_from_index (klass->image, idx);
4677 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
4679 MonoCustomAttrInfo *cinfo;
4682 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
4684 idx = find_event_index (klass, event);
4685 idx <<= CUSTOM_ATTR_BITS;
4686 idx |= CUSTOM_ATTR_EVENT;
4687 return mono_custom_attrs_from_index (klass->image, idx);
4691 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
4693 MonoCustomAttrInfo *cinfo;
4696 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
4698 idx = find_field_index (klass, field);
4699 idx <<= CUSTOM_ATTR_BITS;
4700 idx |= CUSTOM_ATTR_FIELDDEF;
4701 return mono_custom_attrs_from_index (klass->image, idx);
4705 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
4708 guint32 i, idx, method_index;
4709 guint32 param_list, param_last, param_pos, found;
4712 /* FIXME: handle dynamic custom attrs for parameters */
4713 /*if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
4715 image = method->klass->image;
4716 method_index = find_method_index (method);
4717 ca = &image->tables [MONO_TABLE_METHOD];
4719 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
4720 if (method_index == ca->rows) {
4721 ca = &image->tables [MONO_TABLE_PARAM];
4722 param_last = ca->rows + 1;
4724 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
4725 ca = &image->tables [MONO_TABLE_PARAM];
4728 for (i = param_list; i < param_last; ++i) {
4729 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
4730 if (param_pos == param) {
4738 idx <<= CUSTOM_ATTR_BITS;
4739 idx |= CUSTOM_ATTR_PARAMDEF;
4740 return mono_custom_attrs_from_index (image, idx);
4744 * mono_reflection_get_custom_attrs:
4745 * @obj: a reflection object handle
4747 * Return an array with all the custom attributes defined of the
4748 * reflection handle @obj. The objects are fully build.
4751 mono_reflection_get_custom_attrs (MonoObject *obj)
4755 MonoCustomAttrInfo *cinfo;
4757 MONO_ARCH_SAVE_REGS;
4759 klass = obj->vtable->klass;
4760 /* FIXME: need to handle: Module */
4761 if (klass == mono_defaults.monotype_class) {
4762 MonoReflectionType *rtype = (MonoReflectionType*)obj;
4763 klass = mono_class_from_mono_type (rtype->type);
4764 cinfo = mono_custom_attrs_from_class (klass);
4765 } else if (strcmp ("Assembly", klass->name) == 0) {
4766 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
4767 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
4768 } else if (strcmp ("MonoProperty", klass->name) == 0) {
4769 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
4770 cinfo = mono_custom_attrs_from_property (rprop->klass, rprop->property);
4771 } else if (strcmp ("MonoEvent", klass->name) == 0) {
4772 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
4773 cinfo = mono_custom_attrs_from_event (revent->klass, revent->event);
4774 } else if (strcmp ("MonoField", klass->name) == 0) {
4775 MonoReflectionField *rfield = (MonoReflectionField*)obj;
4776 cinfo = mono_custom_attrs_from_field (rfield->klass, rfield->field);
4777 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
4778 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
4779 cinfo = mono_custom_attrs_from_method (rmethod->method);
4780 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
4781 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
4782 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
4783 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
4784 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
4785 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
4786 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
4787 } else { /* handle other types here... */
4788 g_error ("get custom attrs not yet supported for %s", klass->name);
4792 result = mono_custom_attrs_construct (cinfo);
4794 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
4795 result = mono_array_new (mono_domain_get (), klass, 0);
4801 static MonoMethodSignature*
4802 parameters_to_signature (MonoArray *parameters) {
4803 MonoMethodSignature *sig;
4806 count = parameters? mono_array_length (parameters): 0;
4808 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
4809 sig->param_count = count;
4810 sig->sentinelpos = -1; /* FIXME */
4811 for (i = 0; i < count; ++i) {
4812 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
4813 sig->params [i] = pt->type;
4818 static MonoMethodSignature*
4819 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
4820 MonoMethodSignature *sig;
4822 sig = parameters_to_signature (ctor->parameters);
4823 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4824 sig->ret = &mono_defaults.void_class->byval_arg;
4828 static MonoMethodSignature*
4829 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
4830 MonoMethodSignature *sig;
4832 sig = parameters_to_signature (method->parameters);
4833 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4834 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
4839 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
4841 MonoClass *klass = mono_object_class (prop);
4842 if (strcmp (klass->name, "PropertyBuilder") == 0) {
4843 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
4844 *name = mono_string_to_utf8 (pb->name);
4845 *type = pb->type->type;
4847 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
4848 *name = g_strdup (p->property->name);
4849 if (p->property->get)
4850 *type = p->property->get->signature->ret;
4852 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
4857 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
4859 MonoClass *klass = mono_object_class (field);
4860 if (strcmp (klass->name, "FieldBuilder") == 0) {
4861 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
4862 *name = mono_string_to_utf8 (fb->name);
4863 *type = fb->type->type;
4865 MonoReflectionField *f = (MonoReflectionField *)field;
4866 *name = g_strdup (f->field->name);
4867 *type = f->field->type;
4872 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
4873 char *name, *result;
4877 name = mono_type_get_name (type);
4878 klass = my_mono_class_from_mono_type (type);
4879 ta = klass->image->assembly;
4880 if (ta == ass || klass->image == mono_defaults.corlib)
4883 /* missing public key */
4884 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
4885 name, ta->aname.name,
4886 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
4887 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
4893 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
4896 MonoTypeEnum simple_type;
4898 if ((p-buffer) + 10 >= *buflen) {
4901 newbuf = g_realloc (buffer, *buflen);
4902 p = newbuf + (p-buffer);
4905 argval = ((char*)arg + sizeof (MonoObject));
4906 simple_type = type->type;
4908 switch (simple_type) {
4909 case MONO_TYPE_BOOLEAN:
4914 case MONO_TYPE_CHAR:
4917 swap_with_size (p, argval, 2, 1);
4923 swap_with_size (p, argval, 4, 1);
4929 swap_with_size (p, argval, 8, 1);
4932 case MONO_TYPE_VALUETYPE:
4933 if (type->data.klass->enumtype) {
4934 simple_type = type->data.klass->enum_basetype->type;
4937 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
4940 case MONO_TYPE_STRING: {
4947 str = mono_string_to_utf8 ((MonoString*)arg);
4948 slen = strlen (str);
4949 if ((p-buffer) + 10 + slen >= *buflen) {
4953 newbuf = g_realloc (buffer, *buflen);
4954 p = newbuf + (p-buffer);
4957 mono_metadata_encode_value (slen, p, &p);
4958 memcpy (p, str, slen);
4963 case MONO_TYPE_CLASS: {
4971 k = mono_object_class (arg);
4972 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
4973 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
4974 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
4976 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
4977 slen = strlen (str);
4978 if ((p-buffer) + 10 + slen >= *buflen) {
4982 newbuf = g_realloc (buffer, *buflen);
4983 p = newbuf + (p-buffer);
4986 mono_metadata_encode_value (slen, p, &p);
4987 memcpy (p, str, slen);
4992 case MONO_TYPE_SZARRAY: {
4997 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
5000 len = mono_array_length ((MonoArray*)arg);
5002 *p++ = (len >> 8) & 0xff;
5003 *p++ = (len >> 16) & 0xff;
5004 *p++ = (len >> 24) & 0xff;
5006 *retbuffer = buffer;
5007 eclass = type->data.klass;
5008 for (i = 0; i < len; ++i) {
5009 encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
5013 /* it may be a boxed value or a Type */
5014 case MONO_TYPE_OBJECT: {
5015 MonoClass *klass = mono_object_class (arg);
5019 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
5022 } else if (klass->enumtype) {
5024 } else if (klass == mono_defaults.string_class) {
5025 simple_type = MONO_TYPE_STRING;
5028 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
5029 *p++ = simple_type = klass->byval_arg.type;
5032 g_error ("unhandled type in custom attr");
5034 str = type_get_qualified_name (klass->enum_basetype, NULL);
5035 slen = strlen (str);
5036 if ((p-buffer) + 10 + slen >= *buflen) {
5040 newbuf = g_realloc (buffer, *buflen);
5041 p = newbuf + (p-buffer);
5044 mono_metadata_encode_value (slen, p, &p);
5045 memcpy (p, str, slen);
5048 simple_type = klass->enum_basetype->type;
5052 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
5055 *retbuffer = buffer;
5059 * mono_reflection_get_custom_attrs_blob:
5060 * @ctor: custom attribute constructor
5061 * @ctorArgs: arguments o the constructor
5067 * Creates the blob of data that needs to be saved in the metadata and that represents
5068 * the custom attributed described by @ctor, @ctorArgs etc.
5069 * Returns: a Byte array representing the blob of data.
5072 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
5075 MonoMethodSignature *sig;
5080 MONO_ARCH_SAVE_REGS;
5082 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
5083 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
5085 sig = ((MonoReflectionMethod*)ctor)->method->signature;
5087 g_assert (mono_array_length (ctorArgs) == sig->param_count);
5089 p = buffer = g_malloc (buflen);
5090 /* write the prolog */
5093 for (i = 0; i < sig->param_count; ++i) {
5094 arg = mono_array_get (ctorArgs, MonoObject*, i);
5095 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
5099 i += mono_array_length (properties);
5101 i += mono_array_length (fields);
5103 *p++ = (i >> 8) & 0xff;
5106 for (i = 0; i < mono_array_length (properties); ++i) {
5111 prop = mono_array_get (properties, gpointer, i);
5112 get_prop_name_and_type (prop, &pname, &ptype);
5113 *p++ = 0x54; /* PROPERTY signature */
5114 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
5115 char *str = type_get_qualified_name (ptype, NULL);
5116 int slen = strlen (str);
5117 if ((p-buffer) + 10 + slen >= buflen) {
5121 newbuf = g_realloc (buffer, buflen);
5122 p = newbuf + (p-buffer);
5127 * This seems to be optional...
5130 mono_metadata_encode_value (slen, p, &p);
5131 memcpy (p, str, slen);
5135 mono_metadata_encode_value (ptype->type, p, &p);
5137 len = strlen (pname);
5138 mono_metadata_encode_value (len, p, &p);
5139 memcpy (p, pname, len);
5141 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
5148 for (i = 0; i < mono_array_length (fields); ++i) {
5153 field = mono_array_get (fields, gpointer, i);
5154 get_field_name_and_type (field, &fname, &ftype);
5155 *p++ = 0x53; /* FIELD signature */
5156 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
5157 char *str = type_get_qualified_name (ftype, NULL);
5158 int slen = strlen (str);
5159 if ((p-buffer) + 10 + slen >= buflen) {
5163 newbuf = g_realloc (buffer, buflen);
5164 p = newbuf + (p-buffer);
5169 * This seems to be optional...
5172 mono_metadata_encode_value (slen, p, &p);
5173 memcpy (p, str, slen);
5177 mono_metadata_encode_value (ftype->type, p, &p);
5179 len = strlen (fname);
5180 mono_metadata_encode_value (len, p, &p);
5181 memcpy (p, fname, len);
5183 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
5188 g_assert (p - buffer <= buflen);
5189 buflen = p - buffer;
5190 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5191 p = mono_array_addr (result, char, 0);
5192 memcpy (p, buffer, buflen);
5194 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
5200 * mono_reflection_setup_internal_class:
5201 * @tb: a TypeBuilder object
5203 * Creates a MonoClass that represents the TypeBuilder.
5204 * This is a trick that lets us simplify a lot of reflection code
5205 * (and will allow us to support Build and Run assemblies easier).
5208 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
5210 MonoClass *klass, *parent;
5212 MONO_ARCH_SAVE_REGS;
5214 klass = g_new0 (MonoClass, 1);
5216 klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
5219 /* check so we can compile corlib correctly */
5220 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
5221 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
5222 parent = tb->parent->type->data.klass;
5224 parent = my_mono_class_from_mono_type (tb->parent->type);
5228 klass->inited = 1; /* we lie to the runtime */
5229 klass->name = mono_string_to_utf8 (tb->name);
5230 klass->name_space = mono_string_to_utf8 (tb->nspace);
5231 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
5232 klass->flags = tb->attrs;
5234 klass->element_class = klass;
5235 klass->reflection_info = tb; /* need to pin. */
5237 /* Put into cache so mono_class_get () will find it */
5238 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
5241 mono_g_hash_table_insert (tb->module->assemblyb->dynamic_assembly->tokens,
5242 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
5246 mono_class_setup_parent (klass, parent);
5247 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
5248 const char *old_n = klass->name;
5249 /* trick to get relative numbering right when compiling corlib */
5250 klass->name = "BuildingObject";
5251 mono_class_setup_parent (klass, mono_defaults.object_class);
5252 klass->name = old_n;
5254 mono_class_setup_mono_type (klass);
5256 mono_class_setup_supertypes (klass);
5259 * FIXME: handle interfaces.
5262 tb->type.type = &klass->byval_arg;
5264 if (tb->nesting_type) {
5265 g_assert (tb->nesting_type->type);
5266 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
5269 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
5273 * mono_reflection_create_internal_class:
5274 * @tb: a TypeBuilder object
5276 * Actually create the MonoClass that is associated with the TypeBuilder.
5279 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
5283 MONO_ARCH_SAVE_REGS;
5285 klass = my_mono_class_from_mono_type (tb->type.type);
5287 if (klass->enumtype && klass->enum_basetype == NULL) {
5288 MonoReflectionFieldBuilder *fb;
5290 g_assert (tb->fields != NULL);
5291 g_assert (mono_array_length (tb->fields) >= 1);
5293 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
5295 klass->enum_basetype = fb->type->type;
5296 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
5297 if (!klass->element_class)
5298 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
5299 klass->instance_size = klass->element_class->instance_size;
5300 klass->size_inited = 1;
5302 * this is almost safe to do with enums and it's needed to be able
5303 * to create objects of the enum type (for use in SetConstant).
5305 /* FIXME: Does this mean enums can't have method overrides ? */
5306 mono_class_setup_vtable (klass, NULL, 0);
5310 static MonoMarshalSpec*
5311 mono_marshal_spec_from_builder (MonoAssembly *assembly,
5312 MonoReflectionMarshal *minfo)
5314 MonoMarshalSpec *res;
5316 res = g_new0 (MonoMarshalSpec, 1);
5317 res->native = minfo->type;
5319 switch (minfo->type) {
5320 case MONO_NATIVE_LPARRAY:
5321 res->data.array_data.elem_type = minfo->eltype;
5322 res->data.array_data.param_num = 0; /* Not yet */
5323 res->data.array_data.num_elem = minfo->count;
5326 case MONO_NATIVE_BYVALTSTR:
5327 case MONO_NATIVE_BYVALARRAY:
5328 res->data.array_data.num_elem = minfo->count;
5331 case MONO_NATIVE_CUSTOM:
5332 if (minfo->marshaltyperef)
5333 res->data.custom_data.custom_name =
5334 type_get_qualified_name (minfo->marshaltyperef->type,
5337 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
5348 reflection_methodbuilder_to_mono_method (MonoClass *klass,
5349 ReflectionMethodBuilder *rmb,
5350 MonoMethodSignature *sig)
5353 MonoMethodNormal *pm;
5354 MonoMarshalSpec **specs;
5357 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5358 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5359 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
5361 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
5363 pm = (MonoMethodNormal*)m;
5366 m->flags = rmb->attrs;
5367 m->iflags = rmb->iattrs;
5368 m->name = mono_string_to_utf8 (rmb->name);
5371 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
5373 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
5374 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
5377 m->addr = mono_lookup_internal_call (m);
5378 m->signature->pinvoke = 1;
5379 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
5381 m->signature->pinvoke = 1;
5383 } else if (!m->klass->dummy &&
5384 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
5385 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
5386 MonoMethodHeader *header;
5388 gint32 max_stack, i;
5389 gint32 num_locals = 0;
5390 gint32 num_clauses = 0;
5394 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
5395 code_size = rmb->ilgen->code_len;
5396 max_stack = rmb->ilgen->max_stack;
5397 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
5398 if (rmb->ilgen->ex_handlers)
5399 num_clauses = method_count_clauses (rmb->ilgen);
5402 code = mono_array_addr (rmb->code, guint8, 0);
5403 code_size = mono_array_length (rmb->code);
5404 /* we probably need to run a verifier on the code... */
5414 header = g_malloc0 (sizeof (MonoMethodHeader) +
5415 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
5416 header->code_size = code_size;
5417 header->code = g_malloc (code_size);
5418 memcpy ((char*)header->code, code, code_size);
5419 header->max_stack = max_stack;
5420 header->init_locals = rmb->init_locals;
5421 header->num_locals = num_locals;
5423 for (i = 0; i < num_locals; ++i) {
5424 MonoReflectionLocalBuilder *lb =
5425 mono_array_get (rmb->ilgen->locals,
5426 MonoReflectionLocalBuilder*, i);
5428 header->locals [i] = g_new0 (MonoType, 1);
5429 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
5432 header->num_clauses = num_clauses;
5434 header->clauses = method_encode_clauses (klass->image->assembly->dynamic,
5439 pm->header = header;
5442 /* Parameter marshalling */
5445 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
5446 MonoReflectionParamBuilder *pb;
5447 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
5448 if (pb->marshal_info) {
5450 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
5451 specs [pb->position] =
5452 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
5457 mono_g_hash_table_insert (
5458 ((MonoDynamicAssembly*)klass->image->assembly->dynamic)->param_marshalling,
5465 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
5467 ReflectionMethodBuilder rmb;
5469 MonoMethodSignature *sig;
5471 name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
5473 sig = ctor_builder_to_signature (mb);
5475 rmb.ilgen = mb->ilgen;
5476 rmb.parameters = mb->parameters;
5477 rmb.pinfo = mb->pinfo;
5478 rmb.attrs = mb->attrs | METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
5479 rmb.iattrs = mb->iattrs;
5480 rmb.call_conv = mb->call_conv;
5481 rmb.type = mb->type;
5482 rmb.name = mono_string_new (mono_domain_get (), name);
5483 rmb.table_idx = &mb->table_idx;
5484 rmb.init_locals = mb->init_locals;
5487 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
5488 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
5490 if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
5491 /* ilgen is no longer needed */
5499 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
5501 ReflectionMethodBuilder rmb;
5502 MonoMethodSignature *sig;
5504 sig = method_builder_to_signature (mb);
5506 rmb.ilgen = mb->ilgen;
5507 rmb.parameters = mb->parameters;
5508 rmb.pinfo = mb->pinfo;
5509 rmb.attrs = mb->attrs;
5510 rmb.iattrs = mb->iattrs;
5511 rmb.call_conv = mb->call_conv;
5512 rmb.type = mb->type;
5513 rmb.name = mb->name;
5514 rmb.table_idx = &mb->table_idx;
5515 rmb.init_locals = mb->init_locals;
5516 rmb.code = mb->code;
5518 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
5519 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
5521 if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
5522 /* ilgen is no longer needed */
5529 ensure_runtime_vtable (MonoClass *klass)
5531 MonoReflectionTypeBuilder *tb = klass->reflection_info;
5532 int i, num, j, onum;
5533 MonoMethod **overrides;
5535 if (!tb || klass->wastypebuilder)
5538 ensure_runtime_vtable (klass->parent);
5540 num = tb->ctors? mono_array_length (tb->ctors): 0;
5541 num += tb->methods? mono_array_length (tb->methods): 0;
5542 klass->method.count = num;
5543 klass->methods = g_new (MonoMethod*, num);
5544 num = tb->ctors? mono_array_length (tb->ctors): 0;
5545 for (i = 0; i < num; ++i)
5546 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
5547 num = tb->methods? mono_array_length (tb->methods): 0;
5549 for (i = 0; i < num; ++i)
5550 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
5552 klass->wastypebuilder = TRUE;
5553 if (tb->interfaces) {
5554 klass->interface_count = mono_array_length (tb->interfaces);
5555 klass->interfaces = g_new (MonoClass*, klass->interface_count);
5556 for (i = 0; i < klass->interface_count; ++i) {
5557 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
5558 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
5562 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
5563 for (i = 0; i < klass->method.count; ++i)
5564 klass->methods [i]->slot = i;
5569 for (i = 0; i < mono_array_length (tb->methods); ++i) {
5570 MonoReflectionMethodBuilder *mb =
5571 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
5572 if (mb->override_method)
5577 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
5581 for (i = 0; i < mono_array_length (tb->methods); ++i) {
5582 MonoReflectionMethodBuilder *mb =
5583 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
5584 if (mb->override_method) {
5585 /* FIXME: What if 'override_method' is a MethodBuilder ? */
5586 overrides [onum * 2] =
5587 mb->override_method->method;
5588 overrides [onum * 2 + 1] =
5591 g_assert (mb->mhandle);
5598 mono_class_setup_vtable (klass, overrides, onum);
5602 typebuilder_setup_fields (MonoClass *klass)
5604 MonoReflectionTypeBuilder *tb = klass->reflection_info;
5605 MonoReflectionFieldBuilder *fb;
5606 MonoClassField *field;
5611 klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
5612 klass->field.first = 0;
5613 klass->field.last = klass->field.count;
5615 if (!klass->field.count)
5618 klass->fields = g_new0 (MonoClassField, klass->field.count);
5620 for (i = 0; i < klass->field.count; ++i) {
5621 fb = mono_array_get (tb->fields, gpointer, i);
5622 field = &klass->fields [i];
5623 field->name = mono_string_to_utf8 (fb->name);
5625 /* FIXME: handle type modifiers */
5626 field->type = g_memdup (fb->type->type, sizeof (MonoType));
5627 field->type->attrs = fb->attrs;
5629 field->type = fb->type->type;
5631 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
5632 field->data = mono_array_addr (fb->rva_data, char, 0);
5633 if (fb->offset != -1)
5634 field->offset = fb->offset;
5635 field->parent = klass;
5637 mono_save_custom_attrs (klass->image, field, fb->cattrs);
5639 if (fb->def_value) {
5640 MonoDynamicAssembly *assembly = klass->image->assembly->dynamic;
5641 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
5642 field->def_value = g_new0 (MonoConstant, 1);
5643 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
5644 /* Copy the data from the blob since it might get realloc-ed */
5645 p = assembly->blob.data + idx;
5646 len = mono_metadata_decode_blob_size (p, &p2);
5648 field->def_value->value = g_malloc (len);
5649 memcpy (field->def_value->value, p, len);
5652 mono_class_layout_fields (klass);
5656 typebuilder_setup_properties (MonoClass *klass)
5658 MonoReflectionTypeBuilder *tb = klass->reflection_info;
5659 MonoReflectionPropertyBuilder *pb;
5662 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
5663 klass->property.first = 0;
5664 klass->property.last = klass->property.count;
5666 klass->properties = g_new0 (MonoProperty, klass->property.count);
5667 for (i = 0; i < klass->property.count; ++i) {
5668 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
5669 klass->properties [i].attrs = pb->attrs;
5670 klass->properties [i].name = mono_string_to_utf8 (pb->name);
5672 klass->properties [i].get = pb->get_method->mhandle;
5674 klass->properties [i].set = pb->set_method->mhandle;
5679 typebuilder_setup_events (MonoClass *klass)
5681 MonoReflectionTypeBuilder *tb = klass->reflection_info;
5682 MonoReflectionEventBuilder *eb;
5685 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
5686 klass->event.first = 0;
5687 klass->event.last = klass->event.count;
5689 klass->events = g_new0 (MonoEvent, klass->event.count);
5690 for (i = 0; i < klass->event.count; ++i) {
5691 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
5692 klass->events [i].attrs = eb->attrs;
5693 klass->events [i].name = mono_string_to_utf8 (eb->name);
5695 klass->events [i].add = eb->add_method->mhandle;
5696 if (eb->remove_method)
5697 klass->events [i].remove = eb->remove_method->mhandle;
5698 if (eb->raise_method)
5699 klass->events [i].raise = eb->raise_method->mhandle;
5701 if (eb->other_methods) {
5702 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
5703 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
5704 MonoReflectionMethodBuilder *mb =
5705 mono_array_get (eb->other_methods,
5706 MonoReflectionMethodBuilder*, j);
5707 klass->events [i].other [j] = mb->mhandle;
5714 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
5717 MonoReflectionType* res;
5719 MONO_ARCH_SAVE_REGS;
5721 klass = my_mono_class_from_mono_type (tb->type.type);
5723 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
5726 * Fields to set in klass:
5727 * the various flags: delegate/unicode/contextbound etc.
5730 klass->flags = tb->attrs;
5731 klass->element_class = klass;
5733 if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->run)
5734 /* No need to fully construct the type */
5735 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5737 /* enums are done right away */
5738 if (!klass->enumtype)
5739 ensure_runtime_vtable (klass);
5741 /* fields and object layout */
5742 if (klass->parent) {
5743 if (!klass->parent->size_inited)
5744 mono_class_init (klass->parent);
5745 klass->instance_size += klass->parent->instance_size;
5746 klass->class_size += klass->parent->class_size;
5747 klass->min_align = klass->parent->min_align;
5749 klass->instance_size = sizeof (MonoObject);
5750 klass->min_align = 1;
5753 /* FIXME: handle packing_size and instance_size */
5754 typebuilder_setup_fields (klass);
5756 typebuilder_setup_properties (klass);
5758 typebuilder_setup_events (klass);
5760 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5761 /* with enums res == tb: need to fix that. */
5762 if (!klass->enumtype)
5763 g_assert (res != (MonoReflectionType*)tb);
5768 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
5770 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5771 guint32 na = mono_array_length (sig->arguments);
5776 MONO_ARCH_SAVE_REGS;
5778 p = buf = g_malloc (10 + na * 10);
5780 mono_metadata_encode_value (0x07, p, &p);
5781 mono_metadata_encode_value (na, p, &p);
5782 for (i = 0; i < na; ++i) {
5783 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5784 encode_reflection_type (assembly, type, p, &p);
5788 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5789 p = mono_array_addr (result, char, 0);
5790 memcpy (p, buf, buflen);
5797 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
5799 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5800 guint32 na = mono_array_length (sig->arguments);
5805 MONO_ARCH_SAVE_REGS;
5807 p = buf = g_malloc (10 + na * 10);
5809 mono_metadata_encode_value (0x06, p, &p);
5810 for (i = 0; i < na; ++i) {
5811 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5812 encode_reflection_type (assembly, type, p, &p);
5816 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5817 p = mono_array_addr (result, char, 0);
5818 memcpy (p, buf, buflen);
5825 * mono_reflection_lookup_dynamic_token:
5827 * Finish the Builder object pointed to by TOKEN and return the corresponding
5828 * runtime structure.
5831 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
5833 MonoDynamicAssembly *assembly = image->assembly->dynamic;
5837 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5840 if (strcmp (obj->vtable->klass->name, "String") == 0) {
5841 result = mono_string_intern ((MonoString*)obj);
5844 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
5845 MonoReflectionType *tb = (MonoReflectionType*)obj;
5846 result = mono_class_from_mono_type (tb->type);
5849 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
5850 result = ((MonoReflectionMethod*)obj)->method;
5853 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
5854 result = ((MonoReflectionMethod*)obj)->method;
5857 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
5858 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
5859 result = mb->mhandle;
5861 /* Type is not yet created */
5862 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5864 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5867 * Hopefully this has been filled in by calling CreateType() on the
5871 * TODO: This won't work if the application finishes another
5872 * TypeBuilder instance instead of this one.
5874 result = mb->mhandle;
5877 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
5878 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
5880 result = cb->mhandle;
5882 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
5884 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5885 result = cb->mhandle;
5888 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
5889 result = ((MonoReflectionField*)obj)->field;
5892 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
5893 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
5894 result = fb->handle;
5897 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
5899 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5900 result = fb->handle;
5903 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
5904 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
5907 klass = tb->type.type->data.klass;
5908 if (klass->wastypebuilder) {
5909 /* Already created */
5913 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5914 result = tb->type.type->data.klass;
5918 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
5919 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
5920 MonoMethodSignature *sig;
5923 if (helper->arguments)
5924 nargs = mono_array_length (helper->arguments);
5928 sig = mono_metadata_signature_alloc (image, nargs);
5929 sig->explicit_this = helper->call_conv & 64;
5930 sig->hasthis = helper->call_conv & 32;
5932 if (helper->call_conv == 0) /* unmanaged */
5933 sig->call_convention = helper->unmanaged_call_conv - 1;
5935 if (helper->call_conv & 0x02)
5936 sig->call_convention = MONO_CALL_VARARG;
5938 sig->call_convention = MONO_CALL_DEFAULT;
5940 sig->param_count = nargs;
5941 /* TODO: Copy type ? */
5942 sig->ret = helper->return_type->type;
5943 for (i = 0; i < nargs; ++i) {
5944 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
5945 sig->params [i] = rt->type;
5951 g_print (obj->vtable->klass->name);
5952 g_assert_not_reached ();