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.
106 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
107 #define FREE_ATOMIC(ptr)
108 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
110 #define ALLOC_ATOMIC(size) g_malloc (size)
111 #define FREE_ATOMIC(ptr) g_free (ptr)
112 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
115 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
116 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
117 static guint32 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper);
118 static guint32 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo);
121 alloc_table (MonoDynamicTable *table, guint nrows)
124 g_assert (table->columns);
125 if (nrows + 1 >= table->alloc_rows) {
126 while (nrows + 1 >= table->alloc_rows)
127 if (table->alloc_rows == 0)
128 table->alloc_rows = 16;
130 table->alloc_rows *= 2;
132 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
137 make_room_in_stream (MonoDynamicStream *stream, int size)
139 while (stream->alloc_size <= size) {
140 if (stream->alloc_size < 4096)
141 stream->alloc_size = 4096;
143 stream->alloc_size *= 2;
145 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
149 string_heap_insert (MonoDynamicStream *sh, const char *str)
153 gpointer oldkey, oldval;
155 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
156 return GPOINTER_TO_UINT (oldval);
158 len = strlen (str) + 1;
160 if (idx + len > sh->alloc_size)
161 make_room_in_stream (sh, idx + len);
164 * We strdup the string even if we already copy them in sh->data
165 * so that the string pointers in the hash remain valid even if
166 * we need to realloc sh->data. We may want to avoid that later.
168 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
169 memcpy (sh->data + idx, str, len);
175 string_heap_init (MonoDynamicStream *sh)
178 sh->alloc_size = 4096;
179 sh->data = ALLOC_ATOMIC (4096);
180 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
181 string_heap_insert (sh, "");
184 #if 0 /* never used */
186 string_heap_free (MonoDynamicStream *sh)
188 FREE_ATOMIC (sh->data);
189 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
190 g_hash_table_destroy (sh->hash);
195 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
198 if (stream->alloc_size < stream->index + len)
199 make_room_in_stream (stream, stream->index + len);
200 memcpy (stream->data + stream->index, data, len);
202 stream->index += len;
204 * align index? Not without adding an additional param that controls it since
205 * we may store a blob value in pieces.
211 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
214 if (stream->alloc_size < stream->index + len)
215 make_room_in_stream (stream, stream->index + len);
216 memset (stream->data + stream->index, 0, len);
218 stream->index += len;
223 stream_data_align (MonoDynamicStream *stream)
226 guint32 count = stream->index % 4;
228 /* we assume the stream data will be aligned */
230 mono_image_add_stream_data (stream, buf, 4 - count);
234 mono_blob_entry_hash (const char* str)
238 len = mono_metadata_decode_blob_size (str, &str);
242 for (str += 1; str < end; str++)
243 h = (h << 5) - h + *str;
251 mono_blob_entry_equal (const char *str1, const char *str2) {
255 len = mono_metadata_decode_blob_size (str1, &end1);
256 len2 = mono_metadata_decode_blob_size (str2, &end2);
259 return memcmp (end1, end2, len) == 0;
263 add_to_blob_cached (MonoDynamicAssembly *assembly, char *b1, int s1, char *b2, int s2)
267 gpointer oldkey, oldval;
269 copy = ALLOC_ATOMIC (s1+s2);
270 memcpy (copy, b1, s1);
271 memcpy (copy + s1, b2, s2);
272 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
274 idx = GPOINTER_TO_UINT (oldval);
276 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
277 mono_image_add_stream_data (&assembly->blob, b2, s2);
278 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
283 /* modified version needed to handle building corlib */
285 my_mono_class_from_mono_type (MonoType *type) {
286 switch (type->type) {
287 case MONO_TYPE_ARRAY:
289 case MONO_TYPE_SZARRAY:
290 return mono_class_from_mono_type (type);
292 /* should be always valid when we reach this case... */
293 return type->data.klass;
298 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
301 g_assert_not_reached ();
306 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
310 case MONO_TYPE_BOOLEAN:
324 case MONO_TYPE_STRING:
325 case MONO_TYPE_OBJECT:
326 case MONO_TYPE_TYPEDBYREF:
327 mono_metadata_encode_value (type->type, p, &p);
330 case MONO_TYPE_SZARRAY:
331 mono_metadata_encode_value (type->type, p, &p);
332 encode_type (assembly, type->data.type, p, &p);
334 case MONO_TYPE_VALUETYPE:
335 case MONO_TYPE_CLASS:
336 mono_metadata_encode_value (type->type, p, &p);
337 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
340 case MONO_TYPE_VALUETYPE:
341 case MONO_TYPE_CLASS: {
342 MonoClass *k = mono_class_from_mono_type (type);
343 mono_metadata_encode_value (type->type, p, &p);
344 /* ensure only non-byref gets passed to mono_image_typedef_or_ref() */
345 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
349 case MONO_TYPE_ARRAY:
350 mono_metadata_encode_value (type->type, p, &p);
351 encode_type (assembly, type->data.array->type, p, &p);
352 mono_metadata_encode_value (type->data.array->rank, p, &p);
353 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
354 mono_metadata_encode_value (0, p, &p);
357 g_error ("need to encode type %x", type->type);
363 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
366 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
370 encode_type (assembly, type->type, p, endbuf);
374 g_assert_not_reached ();
379 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
384 guint32 nparams = sig->param_count;
385 guint32 size = 10 + nparams * 10;
393 p = buf = g_malloc (size);
395 * FIXME: vararg, explicit_this, differenc call_conv values...
397 *p = sig->call_convention;
399 *p |= 0x20; /* hasthis */
401 mono_metadata_encode_value (nparams, p, &p);
402 encode_type (assembly, sig->ret, p, &p);
403 for (i = 0; i < nparams; ++i)
404 encode_type (assembly, sig->params [i], p, &p);
406 g_assert (p - buf < size);
407 mono_metadata_encode_value (p-buf, b, &b);
408 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
414 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
417 * FIXME: reuse code from method_encode_signature().
422 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
423 guint32 size = 10 + nparams * 10;
428 p = buf = g_malloc (size);
429 /* LAMESPEC: all the call conv spec is foobared */
430 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
431 if (mb->call_conv & 2)
432 *p |= 0x5; /* vararg */
433 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
434 *p |= 0x20; /* hasthis */
436 mono_metadata_encode_value (nparams, p, &p);
437 encode_reflection_type (assembly, mb->rtype, p, &p);
438 for (i = 0; i < nparams; ++i) {
439 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
440 encode_reflection_type (assembly, pt, p, &p);
443 g_assert (p - buf < size);
444 mono_metadata_encode_value (p-buf, b, &b);
445 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
451 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
453 MonoDynamicTable *table;
456 guint32 idx, sig_idx, size;
457 guint nl = mono_array_length (ilgen->locals);
464 p = buf = g_malloc (size);
465 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
466 idx = table->next_idx ++;
468 alloc_table (table, table->rows);
469 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
471 mono_metadata_encode_value (0x07, p, &p);
472 mono_metadata_encode_value (nl, p, &p);
473 for (i = 0; i < nl; ++i) {
474 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
475 encode_reflection_type (assembly, lb->type, p, &p);
477 g_assert (p - buf < size);
478 mono_metadata_encode_value (p-buf, b, &b);
479 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
482 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
488 method_count_clauses (MonoReflectionILGen *ilgen)
490 guint32 num_clauses = 0;
493 MonoILExceptionInfo *ex_info;
494 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
495 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
496 if (ex_info->handlers)
497 num_clauses += mono_array_length (ex_info->handlers);
505 static MonoExceptionClause*
506 method_encode_clauses (MonoDynamicAssembly *assembly,
507 MonoReflectionILGen *ilgen, guint32 num_clauses)
509 MonoExceptionClause *clauses;
510 MonoExceptionClause *clause;
511 MonoILExceptionInfo *ex_info;
512 MonoILExceptionBlock *ex_block;
513 guint32 finally_start;
514 int i, j, clause_index;;
516 clauses = g_new0 (MonoExceptionClause, num_clauses);
519 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
520 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
521 finally_start = ex_info->start + ex_info->len;
522 g_assert (ex_info->handlers);
523 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
524 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
525 clause = &(clauses [clause_index]);
527 clause->flags = ex_block->type;
528 clause->try_offset = ex_info->start;
530 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
531 clause->try_len = finally_start - ex_info->start;
533 clause->try_len = ex_info->len;
534 clause->handler_offset = ex_block->start;
535 clause->handler_len = ex_block->len;
536 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
537 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
538 if (ex_block->extype) {
539 mono_g_hash_table_insert (assembly->tokens,
540 GUINT_TO_POINTER (clause->token_or_filter),
543 finally_start = ex_block->start + ex_block->len;
553 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
559 gint32 num_locals = 0;
560 gint32 num_exception = 0;
563 char fat_header [12];
566 guint32 local_sig = 0;
567 guint32 header_size = 12;
570 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
571 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
572 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
573 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
577 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
579 code = mb->ilgen->code;
580 code_size = mb->ilgen->code_len;
581 max_stack = mb->ilgen->max_stack;
582 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
583 if (mb->ilgen->ex_handlers)
584 num_exception = method_count_clauses (mb->ilgen);
588 mono_raise_exception (mono_get_exception_argument (NULL, "a method does not have any IL associated"));
590 code_size = mono_array_length (code);
591 max_stack = 8; /* we probably need to run a verifier on the code... */
594 /* check for exceptions, maxstack, locals */
595 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
597 if (code_size < 64 && !(code_size & 1)) {
598 flags = (code_size << 2) | 0x2;
599 } else if (code_size < 32 && (code_size & 1)) {
600 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
604 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
605 /* add to the fixup todo list */
606 if (mb->ilgen && mb->ilgen->num_token_fixups)
607 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
608 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
609 return assembly->text_rva + idx;
613 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
615 * FIXME: need to set also the header size in fat_flags.
616 * (and more sects and init locals flags)
620 fat_flags |= METHOD_HEADER_MORE_SECTS;
622 fat_flags |= METHOD_HEADER_INIT_LOCALS;
623 fat_header [0] = fat_flags;
624 fat_header [1] = (header_size / 4 ) << 4;
625 shortp = (guint16*)(fat_header + 2);
626 *shortp = GUINT16_TO_LE (max_stack);
627 intp = (guint32*)(fat_header + 4);
628 *intp = GUINT32_TO_LE (code_size);
629 intp = (guint32*)(fat_header + 8);
630 *intp = GUINT32_TO_LE (local_sig);
631 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
632 /* add to the fixup todo list */
633 if (mb->ilgen && mb->ilgen->num_token_fixups)
634 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
636 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
638 unsigned char sheader [4];
639 MonoExceptionClause clause;
640 MonoILExceptionInfo * ex_info;
641 MonoILExceptionBlock * ex_block;
644 stream_data_align (&assembly->code);
645 /* always use fat format for now */
646 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
647 num_exception *= sizeof (MonoExceptionClause);
648 num_exception += 4; /* include the size of the header */
649 sheader [1] = num_exception & 0xff;
650 sheader [2] = (num_exception >> 8) & 0xff;
651 sheader [3] = (num_exception >> 16) & 0xff;
652 mono_image_add_stream_data (&assembly->code, sheader, 4);
653 /* fat header, so we are already aligned */
655 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
656 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
657 if (ex_info->handlers) {
658 int finally_start = ex_info->start + ex_info->len;
659 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
660 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
661 clause.flags = GUINT32_TO_LE (ex_block->type);
662 clause.try_offset = GUINT32_TO_LE (ex_info->start);
663 /* need fault, too, probably */
664 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
665 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
667 clause.try_len = GUINT32_TO_LE (ex_info->len);
668 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
669 clause.handler_len = GUINT32_TO_LE (ex_block->len);
670 finally_start = ex_block->start + ex_block->len;
671 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
672 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
673 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
674 /*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",
675 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);*/
676 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
679 g_error ("No clauses for ex info block %d", i);
683 return assembly->text_rva + idx;
687 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 token)
690 MonoDynamicTable *table;
693 table = &assembly->tables [table_idx];
695 g_assert (col < table->columns);
697 values = table->values + table->columns;
698 for (i = 1; i <= table->rows; ++i) {
699 if (values [col] == token)
701 values += table->columns;
706 static GHashTable *dynamic_custom_attrs = NULL;
708 static MonoCustomAttrInfo*
709 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
712 MonoCustomAttrInfo *ainfo;
713 MonoReflectionCustomAttr *cattr;
717 /* FIXME: check in assembly the Run flag is set */
719 count = mono_array_length (cattrs);
721 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
723 ainfo->image = image;
724 ainfo->num_attrs = count;
725 for (i = 0; i < count; ++i) {
726 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
727 ainfo->attrs [i].ctor = cattr->ctor->method;
728 /* FIXME: might want to memdup the data here */
729 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
730 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
737 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
739 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
744 if (!dynamic_custom_attrs)
745 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
747 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
751 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
753 /* they are cached, so we don't free them */
754 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
760 * idx is the table index of the object
761 * type is one of CUSTOM_ATTR_*
764 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
766 MonoDynamicTable *table;
767 MonoReflectionCustomAttr *cattr;
769 guint32 count, i, token;
773 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
776 count = mono_array_length (cattrs);
777 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
778 table->rows += count;
779 alloc_table (table, table->rows);
780 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
781 idx <<= CUSTOM_ATTR_BITS;
783 for (i = 0; i < count; ++i) {
784 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
785 values [MONO_CUSTOM_ATTR_PARENT] = idx;
786 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
787 type = mono_metadata_token_index (token);
788 type <<= CUSTOM_ATTR_TYPE_BITS;
789 switch (mono_metadata_token_table (token)) {
790 case MONO_TABLE_METHOD:
791 type |= CUSTOM_ATTR_TYPE_METHODDEF;
793 case MONO_TABLE_MEMBERREF:
794 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
797 g_warning ("got wrong token in custom attr");
800 values [MONO_CUSTOM_ATTR_TYPE] = type;
802 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
803 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
804 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
805 values += MONO_CUSTOM_ATTR_SIZE;
811 * Fill in the MethodDef and ParamDef tables for a method.
812 * This is used for both normal methods and constructors.
815 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
817 MonoDynamicTable *table;
822 /* room in this table is already allocated */
823 table = &assembly->tables [MONO_TABLE_METHOD];
824 *mb->table_idx = table->next_idx ++;
825 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
826 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
828 name = mono_string_to_utf8 (mb->name);
829 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
831 } else { /* a constructor */
832 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
833 // MS.NET adds this automatically
834 mb->attrs |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
836 values [MONO_METHOD_FLAGS] = mb->attrs;
837 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
838 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
839 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
841 table = &assembly->tables [MONO_TABLE_PARAM];
842 values [MONO_METHOD_PARAMLIST] = table->next_idx;
845 MonoDynamicTable *mtable;
848 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
849 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
852 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
853 if (mono_array_get (mb->pinfo, gpointer, i))
856 table->rows += count;
857 alloc_table (table, table->rows);
858 values = table->values + table->next_idx * MONO_PARAM_SIZE;
859 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
860 MonoReflectionParamBuilder *pb;
861 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
862 values [MONO_PARAM_FLAGS] = pb->attrs;
863 values [MONO_PARAM_SEQUENCE] = i;
864 if (pb->name != NULL) {
865 name = mono_string_to_utf8 (pb->name);
866 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
870 values [MONO_PARAM_NAME] = 0;
871 values += MONO_PARAM_SIZE;
872 if (pb->marshal_info) {
874 alloc_table (mtable, mtable->rows);
875 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
876 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
877 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
879 pb->table_idx = table->next_idx++;
886 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
888 MonoDynamicTable *table;
891 ReflectionMethodBuilder rmb;
893 rmb.ilgen = mb->ilgen;
894 rmb.rtype = mb->rtype;
895 rmb.parameters = mb->parameters;
896 rmb.pinfo = mb->pinfo;
897 rmb.attrs = mb->attrs;
898 rmb.iattrs = mb->iattrs;
899 rmb.call_conv = mb->call_conv;
903 rmb.table_idx = &mb->table_idx;
904 rmb.init_locals = mb->init_locals;
905 rmb.mhandle = mb->mhandle;
907 mono_image_basic_method (&rmb, assembly);
909 if (mb->dll) { /* It's a P/Invoke method */
911 table = &assembly->tables [MONO_TABLE_IMPLMAP];
913 alloc_table (table, table->rows);
914 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
915 /* map CharSet values to on-disk values */
916 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (mb->charset ? (mb->charset - 1) * 2: 1);
917 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
918 name = mono_string_to_utf8 (mb->dllentry);
919 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
921 name = mono_string_to_utf8 (mb->dll);
922 moduleref = string_heap_insert (&assembly->sheap, name);
924 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
925 table = &assembly->tables [MONO_TABLE_MODULEREF];
927 alloc_table (table, table->rows);
928 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
929 values [MONO_IMPLMAP_SCOPE] = table->rows;
933 if (mb->override_method) {
934 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
936 table = &assembly->tables [MONO_TABLE_METHODIMPL];
938 alloc_table (table, table->rows);
939 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
940 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
941 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
942 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
943 switch (mono_metadata_token_table (tok)) {
944 case MONO_TABLE_MEMBERREF:
945 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
947 case MONO_TABLE_METHOD:
948 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
951 g_assert_not_reached ();
953 values [MONO_METHODIMPL_DECLARATION] = tok;
958 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
960 ReflectionMethodBuilder rmb;
962 rmb.ilgen = mb->ilgen;
963 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
964 rmb.parameters = mb->parameters;
965 rmb.pinfo = mb->pinfo;
966 rmb.attrs = mb->attrs;
967 rmb.iattrs = mb->iattrs;
968 rmb.call_conv = mb->call_conv;
972 rmb.table_idx = &mb->table_idx;
973 rmb.init_locals = mb->init_locals;
974 rmb.mhandle = mb->mhandle;
976 mono_image_basic_method (&rmb, assembly);
981 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
992 p = buf = g_malloc (64);
994 mono_metadata_encode_value (0x06, p, &p);
995 /* encode custom attributes before the type */
996 encode_type (assembly, field->type, p, &p);
997 g_assert (p-buf < 64);
998 mono_metadata_encode_value (p-buf, b, &b);
999 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1005 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
1007 char blob_size [64];
1008 char *b = blob_size;
1013 p = buf = g_malloc (64);
1015 mono_metadata_encode_value (0x06, p, &p);
1016 /* encode custom attributes before the type */
1017 encode_reflection_type (assembly, fb->type, p, &p);
1018 g_assert (p-buf < 64);
1019 mono_metadata_encode_value (p-buf, b, &b);
1020 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1026 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
1027 * dest may be misaligned.
1030 swap_with_size (char *dest, const char* val, int len, int nelem) {
1031 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1034 for (elem = 0; elem < nelem; ++elem) {
1060 g_assert_not_reached ();
1066 memcpy (dest, val, len * nelem);
1071 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
1072 char blob_size [64];
1073 char *b = blob_size;
1076 guint32 idx, len, dummy = 0;
1078 p = buf = g_malloc (64);
1080 *ret_type = MONO_TYPE_CLASS;
1082 box_val = (char*)&dummy;
1084 box_val = ((char*)val) + sizeof (MonoObject);
1085 *ret_type = val->vtable->klass->byval_arg.type;
1088 switch (*ret_type) {
1089 case MONO_TYPE_BOOLEAN:
1094 case MONO_TYPE_CHAR:
1109 case MONO_TYPE_VALUETYPE:
1110 if (val->vtable->klass->enumtype) {
1111 *ret_type = val->vtable->klass->enum_basetype->type;
1114 g_error ("we can't encode valuetypes");
1115 case MONO_TYPE_CLASS:
1117 case MONO_TYPE_STRING: {
1118 MonoString *str = (MonoString*)val;
1119 /* there is no signature */
1120 len = str->length * 2;
1121 mono_metadata_encode_value (len, b, &b);
1122 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1124 char *swapped = g_malloc (2 * mono_string_length (str));
1125 const char *p = (const char*)mono_string_chars (str);
1127 swap_with_size (swapped, p, 2, mono_string_length (str));
1128 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1132 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1139 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1142 /* there is no signature */
1143 mono_metadata_encode_value (len, b, &b);
1144 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1145 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1146 swap_with_size (blob_size, box_val, len, 1);
1147 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1149 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1157 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo) {
1158 char blob_size [64];
1159 char *b = blob_size;
1163 p = buf = g_malloc (256);
1165 switch (minfo->type) {
1166 case MONO_NATIVE_BYVALTSTR:
1167 case MONO_NATIVE_BYVALARRAY:
1168 mono_metadata_encode_value (minfo->type, p, &p);
1169 mono_metadata_encode_value (minfo->count, p, &p);
1171 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
1173 mono_metadata_encode_value (minfo->type, p, &p);
1177 mono_metadata_encode_value (len, b, &b);
1178 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1184 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
1186 MonoDynamicTable *table;
1190 /* maybe this fixup should be done in the C# code */
1191 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1192 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1193 table = &assembly->tables [MONO_TABLE_FIELD];
1194 fb->table_idx = table->next_idx ++;
1195 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1196 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1197 name = mono_string_to_utf8 (fb->name);
1198 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1200 values [MONO_FIELD_FLAGS] = fb->attrs;
1201 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1203 if (fb->offset != -1) {
1204 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1206 alloc_table (table, table->rows);
1207 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1208 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1209 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1211 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1212 guint32 field_type = 0;
1213 table = &assembly->tables [MONO_TABLE_CONSTANT];
1215 alloc_table (table, table->rows);
1216 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1217 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1218 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1219 values [MONO_CONSTANT_TYPE] = field_type;
1220 values [MONO_CONSTANT_PADDING] = 0;
1224 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1226 alloc_table (table, table->rows);
1227 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1228 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1230 * We store it in the code section because it's simpler for now.
1232 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1233 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1235 if (fb->marshal_info) {
1236 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1238 alloc_table (table, table->rows);
1239 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1240 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1241 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1246 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
1250 char *b = blob_size;
1251 guint32 nparams = 0;
1252 MonoReflectionMethodBuilder *mb = fb->get_method;
1253 MonoReflectionMethodBuilder *smb = fb->set_method;
1254 guint32 idx, i, size;
1256 if (mb && mb->parameters)
1257 nparams = mono_array_length (mb->parameters);
1258 if (!mb && smb && smb->parameters)
1259 nparams = mono_array_length (smb->parameters) - 1;
1260 size = 24 + nparams * 10;
1261 buf = p = g_malloc (size);
1264 mono_metadata_encode_value (nparams, p, &p);
1266 encode_reflection_type (assembly, mb->rtype, p, &p);
1267 for (i = 0; i < nparams; ++i) {
1268 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1269 encode_reflection_type (assembly, pt, p, &p);
1272 /* the property type is the last param */
1273 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1274 for (i = 0; i < nparams; ++i) {
1275 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1276 encode_reflection_type (assembly, pt, p, &p);
1280 g_assert (p - buf < size);
1281 mono_metadata_encode_value (p-buf, b, &b);
1282 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1288 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
1290 MonoDynamicTable *table;
1293 guint num_methods = 0;
1297 * we need to set things in the following tables:
1298 * PROPERTYMAP (info already filled in _get_type_info ())
1299 * PROPERTY (rows already preallocated in _get_type_info ())
1300 * METHOD (method info already done with the generic method code)
1303 table = &assembly->tables [MONO_TABLE_PROPERTY];
1304 pb->table_idx = table->next_idx ++;
1305 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1306 name = mono_string_to_utf8 (pb->name);
1307 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1309 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1310 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1312 /* FIXME: we still don't handle 'other' methods */
1313 if (pb->get_method) num_methods ++;
1314 if (pb->set_method) num_methods ++;
1316 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1317 table->rows += num_methods;
1318 alloc_table (table, table->rows);
1320 if (pb->get_method) {
1321 semaidx = table->next_idx ++;
1322 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1323 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1324 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1325 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1327 if (pb->set_method) {
1328 semaidx = table->next_idx ++;
1329 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1330 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1331 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1332 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1337 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
1339 MonoDynamicTable *table;
1342 guint num_methods = 0;
1346 * we need to set things in the following tables:
1347 * EVENTMAP (info already filled in _get_type_info ())
1348 * EVENT (rows already preallocated in _get_type_info ())
1349 * METHOD (method info already done with the generic method code)
1352 table = &assembly->tables [MONO_TABLE_EVENT];
1353 eb->table_idx = table->next_idx ++;
1354 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1355 name = mono_string_to_utf8 (eb->name);
1356 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1358 values [MONO_EVENT_FLAGS] = eb->attrs;
1359 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1362 * FIXME: we still don't handle 'other' methods
1364 if (eb->add_method) num_methods ++;
1365 if (eb->remove_method) num_methods ++;
1366 if (eb->raise_method) num_methods ++;
1368 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1369 table->rows += num_methods;
1370 alloc_table (table, table->rows);
1372 if (eb->add_method) {
1373 semaidx = table->next_idx ++;
1374 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1375 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1376 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1377 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1379 if (eb->remove_method) {
1380 semaidx = table->next_idx ++;
1381 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1382 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1383 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1384 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1386 if (eb->raise_method) {
1387 semaidx = table->next_idx ++;
1388 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1389 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1390 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1391 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1396 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
1398 MonoDynamicTable *table;
1401 guint32 cols [MONO_ASSEMBLY_SIZE];
1405 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1408 if (image->assembly->dynamic)
1410 memset (cols, 0, sizeof (cols));
1412 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1414 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1415 token = table->next_idx ++;
1417 alloc_table (table, table->rows);
1418 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1419 if (strcmp ("corlib", image->assembly_name) == 0)
1420 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1422 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1423 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1424 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1425 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1426 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1427 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1428 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1429 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1431 if ((pubkey = mono_image_get_public_key (image, &publen))) {
1432 guchar pubtoken [9];
1434 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
1435 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
1438 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
1439 * This is currently only a problem with references to System.Xml (see bug#27706),
1440 * but there may be other cases that makes this necessary. Note, we need to set
1441 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
1442 * recognized by ms, yuck!
1443 * FIXME: need to add more assembly names, as needed.
1445 if (strcmp (image->assembly_name, "corlib") == 0 ||
1446 strcmp (image->assembly_name, "mscorlib") == 0 ||
1447 strcmp (image->assembly_name, "System") == 0 ||
1448 strcmp (image->assembly_name, "System.Xml") == 0 ||
1449 strcmp (image->assembly_name, "System.Data") == 0 ||
1450 strcmp (image->assembly_name, "System.Drawing") == 0 ||
1451 strcmp (image->assembly_name, "System.Web") == 0) {
1452 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
1453 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1454 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1455 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1457 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1460 token <<= RESOLTION_SCOPE_BITS;
1461 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1462 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1463 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), image);
1468 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1470 MonoDynamicTable *table;
1476 char *b = blob_size;
1478 switch (type->type) {
1479 case MONO_TYPE_FNPTR:
1481 case MONO_TYPE_SZARRAY:
1482 case MONO_TYPE_ARRAY:
1483 encode_type (assembly, type, p, &p);
1489 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1490 if (assembly->save) {
1491 g_assert (p-sig < 128);
1492 mono_metadata_encode_value (p-sig, b, &b);
1493 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
1494 alloc_table (table, table->rows + 1);
1495 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1496 values [MONO_TYPESPEC_SIGNATURE] = token;
1499 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1500 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1506 * Despite the name, we handle also TypeSpec (with the above helper).
1509 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1511 MonoDynamicTable *table;
1513 guint32 token, scope, enclosing;
1516 #define COMPILE_CORLIB 0
1518 /* nasty hack, need to find the proper solution */
1519 if (type->type == MONO_TYPE_OBJECT)
1520 return TYPEDEFORREF_TYPEDEF | (2 << TYPEDEFORREF_BITS);
1522 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1525 token = create_typespec (assembly, type);
1528 klass = my_mono_class_from_mono_type (type);
1530 klass = mono_class_from_mono_type (type);
1533 * If it's in the same module:
1535 if (klass->image == assembly->assembly.image) {
1536 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1537 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1538 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
1542 if (klass->nested_in) {
1543 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1544 /* get the typeref idx of the enclosing type */
1545 enclosing >>= TYPEDEFORREF_BITS;
1546 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1548 scope = resolution_scope_from_image (assembly, klass->image);
1550 table = &assembly->tables [MONO_TABLE_TYPEREF];
1551 if (assembly->save) {
1552 alloc_table (table, table->rows + 1);
1553 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1554 values [MONO_TYPEREF_SCOPE] = scope;
1555 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1556 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1558 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1559 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1561 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
1566 * Insert a memberef row into the metadata: the token that point to the memberref
1567 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1568 * mono_image_get_fieldref_token()).
1569 * The sig param is an index to an already built signature.
1572 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1574 MonoDynamicTable *table;
1576 guint32 token, pclass;
1579 parent = mono_image_typedef_or_ref (assembly, type);
1580 switch (parent & TYPEDEFORREF_MASK) {
1581 case TYPEDEFORREF_TYPEREF:
1582 pclass = MEMBERREF_PARENT_TYPEREF;
1584 case TYPEDEFORREF_TYPESPEC:
1585 pclass = MEMBERREF_PARENT_TYPESPEC;
1587 case TYPEDEFORREF_TYPEDEF:
1588 /* should never get here */
1590 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
1593 /* extract the index */
1594 parent >>= TYPEDEFORREF_BITS;
1596 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1598 if (assembly->save) {
1599 alloc_table (table, table->rows + 1);
1600 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1601 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1602 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1603 values [MONO_MEMBERREF_SIGNATURE] = sig;
1606 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1613 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1617 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1620 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1621 method->name, method_encode_signature (assembly, method->signature));
1622 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1627 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1631 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1634 field->parent = klass;
1635 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
1636 field->name, fieldref_encode_signature (assembly, field));
1637 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1642 mono_reflection_encode_sighelper (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1650 char *b = blob_size;
1652 if (!assembly->save)
1656 g_assert (helper->type == 2);
1658 if (helper->arguments)
1659 nargs = mono_array_length (helper->arguments);
1663 size = 10 + (nargs * 10);
1665 p = buf = g_malloc (size);
1667 /* Encode calling convention */
1668 /* Change Any to Standard */
1669 if ((helper->call_conv & 0x03) == 0x03)
1670 helper->call_conv = 0x01;
1671 /* explicit_this implies has_this */
1672 if (helper->call_conv & 0x40)
1673 helper->call_conv &= 0x20;
1675 if (helper->call_conv == 0) /* Unmanaged */
1676 *p = helper->unmanaged_call_conv - 1;
1679 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
1680 if (helper->call_conv & 0x02) /* varargs */
1685 mono_metadata_encode_value (nargs, p, &p);
1686 encode_reflection_type (assembly, helper->return_type, p, &p);
1687 for (i = 0; i < nargs; ++i) {
1688 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
1689 encode_reflection_type (assembly, pt, p, &p);
1692 g_assert (p - buf < size);
1693 mono_metadata_encode_value (p-buf, b, &b);
1694 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1701 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1704 MonoDynamicTable *table;
1707 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1708 idx = table->next_idx ++;
1710 alloc_table (table, table->rows);
1711 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1713 values [MONO_STAND_ALONE_SIGNATURE] =
1714 mono_reflection_encode_sighelper (assembly, helper);
1720 reflection_cc_to_file (int call_conv) {
1721 switch (call_conv & 0x3) {
1723 case 1: return MONO_CALL_DEFAULT;
1724 case 2: return MONO_CALL_VARARG;
1726 g_assert_not_reached ();
1733 MonoMethodSignature *sig;
1739 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1744 MonoMethodSignature *sig;
1747 name = mono_string_to_utf8 (m->name);
1748 nparams = mono_array_length (m->parameters);
1749 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1751 sig->call_convention = reflection_cc_to_file (m->call_conv);
1752 sig->param_count = nparams;
1753 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1754 for (i = 0; i < nparams; ++i) {
1755 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1756 sig->params [i] = t->type;
1759 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1761 if (strcmp (name, am->name) == 0 &&
1762 mono_metadata_type_equal (am->parent, m->parent->type) &&
1763 mono_metadata_signature_equal (am->sig, sig)) {
1766 m->table_idx = am->token & 0xffffff;
1770 am = g_new0 (ArrayMethod, 1);
1773 am->parent = m->parent->type;
1774 am->token = mono_image_get_memberref_token (assembly, am->parent,
1775 name, method_encode_signature (assembly, sig));
1776 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1777 m->table_idx = am->token & 0xffffff;
1782 * Insert into the metadata tables all the info about the TypeBuilder tb.
1783 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1786 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1788 MonoDynamicTable *table;
1790 int i, is_object = 0, is_system = 0;
1793 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1794 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1795 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1796 n = mono_string_to_utf8 (tb->name);
1797 if (strcmp (n, "Object") == 0)
1799 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1801 n = mono_string_to_utf8 (tb->nspace);
1802 if (strcmp (n, "System") == 0)
1804 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1806 if (tb->parent && !(is_system && is_object) &&
1807 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
1808 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1810 values [MONO_TYPEDEF_EXTENDS] = 0;
1811 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1812 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1815 * if we have explicitlayout or sequentiallayouts, output data in the
1816 * ClassLayout table.
1818 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1819 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1821 alloc_table (table, table->rows);
1822 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1823 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1824 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1825 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1828 /* handle interfaces */
1829 if (tb->interfaces) {
1830 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1832 table->rows += mono_array_length (tb->interfaces);
1833 alloc_table (table, table->rows);
1834 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1835 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1836 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1837 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1838 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1839 values += MONO_INTERFACEIMPL_SIZE;
1845 table = &assembly->tables [MONO_TABLE_FIELD];
1846 table->rows += mono_array_length (tb->fields);
1847 alloc_table (table, table->rows);
1848 for (i = 0; i < mono_array_length (tb->fields); ++i)
1849 mono_image_get_field_info (
1850 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1853 /* handle constructors */
1855 table = &assembly->tables [MONO_TABLE_METHOD];
1856 table->rows += mono_array_length (tb->ctors);
1857 alloc_table (table, table->rows);
1858 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1859 mono_image_get_ctor_info (domain,
1860 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1863 /* handle methods */
1865 table = &assembly->tables [MONO_TABLE_METHOD];
1866 table->rows += mono_array_length (tb->methods);
1867 alloc_table (table, table->rows);
1868 for (i = 0; i < mono_array_length (tb->methods); ++i)
1869 mono_image_get_method_info (
1870 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1873 /* Do the same with properties etc.. */
1874 if (tb->events && mono_array_length (tb->events)) {
1875 table = &assembly->tables [MONO_TABLE_EVENT];
1876 table->rows += mono_array_length (tb->events);
1877 alloc_table (table, table->rows);
1878 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1880 alloc_table (table, table->rows);
1881 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1882 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1883 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1884 for (i = 0; i < mono_array_length (tb->events); ++i)
1885 mono_image_get_event_info (
1886 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1888 if (tb->properties && mono_array_length (tb->properties)) {
1889 table = &assembly->tables [MONO_TABLE_PROPERTY];
1890 table->rows += mono_array_length (tb->properties);
1891 alloc_table (table, table->rows);
1892 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1894 alloc_table (table, table->rows);
1895 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1896 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1897 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1898 for (i = 0; i < mono_array_length (tb->properties); ++i)
1899 mono_image_get_property_info (
1900 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1903 MonoDynamicTable *ntable;
1905 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1906 ntable->rows += mono_array_length (tb->subtypes);
1907 alloc_table (ntable, ntable->rows);
1908 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1910 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1911 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1913 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1914 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1915 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1916 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1917 mono_string_to_utf8 (tb->name), tb->table_idx,
1918 ntable->next_idx, ntable->rows);*/
1919 values += MONO_NESTED_CLASS_SIZE;
1926 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
1930 g_ptr_array_add (types, type);
1932 if (!type->subtypes)
1935 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
1936 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
1937 collect_types (types, subtype);
1942 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
1943 MonoReflectionTypeBuilder **type2)
1945 if ((*type1)->table_idx < (*type2)->table_idx)
1948 if ((*type1)->table_idx > (*type2)->table_idx)
1955 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
1960 for (i = 0; i < mono_array_length (pinfo); ++i) {
1961 MonoReflectionParamBuilder *pb;
1962 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
1965 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
1970 type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
1973 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1975 for (i = 0; i < mono_array_length (tb->fields); ++i) {
1976 MonoReflectionFieldBuilder* fb;
1977 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
1978 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
1982 for (i = 0; i < mono_array_length (tb->events); ++i) {
1983 MonoReflectionEventBuilder* eb;
1984 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
1985 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1988 if (tb->properties) {
1989 for (i = 0; i < mono_array_length (tb->properties); ++i) {
1990 MonoReflectionPropertyBuilder* pb;
1991 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
1992 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
1996 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
1997 MonoReflectionCtorBuilder* cb;
1998 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
1999 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2000 params_add_cattrs (assembly, cb->pinfo);
2005 for (i = 0; i < mono_array_length (tb->methods); ++i) {
2006 MonoReflectionMethodBuilder* mb;
2007 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2008 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2009 params_add_cattrs (assembly, mb->pinfo);
2014 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2015 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2020 module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
2023 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2025 /* no types in the module */
2029 for (i = 0; i < mono_array_length (mb->types); ++i)
2030 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2034 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
2036 MonoDynamicTable *table;
2040 table = &assembly->tables [MONO_TABLE_MODULE];
2041 mb->table_idx = table->next_idx ++;
2042 name = mono_string_to_utf8 (mb->module.name);
2043 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2045 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2048 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2049 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2050 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2053 #define align_pointer(base,p)\
2055 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
2057 (p) += 4 - (__diff & 3);\
2061 compare_semantics (const void *a, const void *b)
2063 const guint32 *a_values = a;
2064 const guint32 *b_values = b;
2065 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
2068 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
2072 compare_custom_attrs (const void *a, const void *b)
2074 const guint32 *a_values = a;
2075 const guint32 *b_values = b;
2077 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
2081 compare_field_marshal (const void *a, const void *b)
2083 const guint32 *a_values = a;
2084 const guint32 *b_values = b;
2086 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
2090 compare_nested (const void *a, const void *b)
2092 const guint32 *a_values = a;
2093 const guint32 *b_values = b;
2095 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
2099 * build_compressed_metadata() fills in the blob of data that represents the
2100 * raw metadata as it will be saved in the PE file. The five streams are output
2101 * and the metadata tables are comnpressed from the guint32 array representation,
2102 * to the compressed on-disk format.
2105 build_compressed_metadata (MonoDynamicAssembly *assembly)
2107 MonoDynamicTable *table;
2109 guint64 valid_mask = 0;
2110 guint64 sorted_mask;
2111 guint32 heapt_size = 0;
2112 guint32 meta_size = 256; /* allow for header and other stuff */
2113 guint32 table_offset;
2114 guint32 ntables = 0;
2121 * We need to use the current ms version or the ms runtime it won't find
2122 * the support dlls. D'oh!
2123 * const char *version = "mono-" VERSION;
2125 const char *version = "v1.0.3705";
2128 MonoDynamicStream *stream;
2129 } stream_desc [] = {
2130 {"#~", &assembly->tstream},
2131 {"#Strings", &assembly->sheap},
2132 {"#US", &assembly->us},
2133 {"#Blob", &assembly->blob},
2134 {"#GUID", &assembly->guid}
2137 /* tables that are sorted */
2138 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
2139 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
2140 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
2141 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
2142 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
2143 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
2145 /* Compute table sizes */
2146 /* the MonoImage has already been created in mono_image_basic_init() */
2147 meta = assembly->assembly.image;
2149 /* Setup the info used by compute_sizes () */
2150 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
2151 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
2152 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
2154 meta_size += assembly->blob.index;
2155 meta_size += assembly->guid.index;
2156 meta_size += assembly->sheap.index;
2157 meta_size += assembly->us.index;
2159 for (i=0; i < 64; ++i)
2160 meta->tables [i].rows = assembly->tables [i].rows;
2162 for (i = 0; i < 64; i++){
2163 if (meta->tables [i].rows == 0)
2165 valid_mask |= (guint64)1 << i;
2167 meta->tables [i].row_size = mono_metadata_compute_size (
2168 meta, i, &meta->tables [i].size_bitfield);
2169 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
2171 heapt_size += 24; /* #~ header size */
2172 heapt_size += ntables * 4;
2173 meta_size += heapt_size;
2174 meta->raw_metadata = g_malloc0 (meta_size);
2175 p = meta->raw_metadata;
2176 /* the metadata signature */
2177 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
2178 /* version numbers and 4 bytes reserved */
2179 int16val = (guint16*)p;
2180 *int16val++ = GUINT16_TO_LE (1);
2181 *int16val = GUINT16_TO_LE (1);
2183 /* version string */
2184 int32val = (guint32*)p;
2185 *int32val = GUINT32_TO_LE ((strlen (version) + 3) & (~3)); /* needs to be multiple of 4 */
2187 memcpy (p, version, GUINT32_FROM_LE (*int32val));
2188 p += GUINT32_FROM_LE (*int32val);
2189 align_pointer (meta->raw_metadata, p);
2190 int16val = (guint16*)p;
2191 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
2192 *int16val = GUINT16_TO_LE (5); /* number of streams */
2196 * write the stream info.
2198 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
2199 table_offset += 3; table_offset &= ~3;
2201 assembly->tstream.index = heapt_size;
2202 for (i = 0; i < 5; ++i) {
2203 int32val = (guint32*)p;
2204 stream_desc [i].stream->offset = table_offset;
2205 *int32val++ = GUINT32_TO_LE (table_offset);
2206 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
2207 table_offset += GUINT32_FROM_LE (*int32val);
2208 table_offset += 3; table_offset &= ~3;
2210 strcpy (p, stream_desc [i].name);
2211 p += strlen (stream_desc [i].name) + 1;
2212 align_pointer (meta->raw_metadata, p);
2215 * now copy the data, the table stream header and contents goes first.
2217 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
2218 p = meta->raw_metadata + assembly->tstream.offset;
2219 int32val = (guint32*)p;
2220 *int32val = GUINT32_TO_LE (0); /* reserved */
2222 *p++ = 1; /* version */
2224 if (meta->idx_string_wide)
2226 if (meta->idx_guid_wide)
2228 if (meta->idx_blob_wide)
2231 *p++ = 0; /* reserved */
2232 int64val = (guint64*)p;
2233 *int64val++ = GUINT64_TO_LE (valid_mask);
2234 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
2236 int32val = (guint32*)p;
2237 for (i = 0; i < 64; i++){
2238 if (meta->tables [i].rows == 0)
2240 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
2242 p = (unsigned char*)int32val;
2244 /* sort the tables that still need sorting */
2245 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2247 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
2248 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2250 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
2251 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2253 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
2254 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2256 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
2258 /* compress the tables */
2259 for (i = 0; i < 64; i++){
2262 guint32 bitfield = meta->tables [i].size_bitfield;
2263 if (!meta->tables [i].rows)
2265 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
2266 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
2267 meta->tables [i].base = p;
2268 for (row = 1; row <= meta->tables [i].rows; ++row) {
2269 values = assembly->tables [i].values + row * assembly->tables [i].columns;
2270 for (col = 0; col < assembly->tables [i].columns; ++col) {
2271 switch (mono_metadata_table_size (bitfield, col)) {
2273 *p++ = values [col];
2276 *p++ = values [col] & 0xff;
2277 *p++ = (values [col] >> 8) & 0xff;
2280 *p++ = values [col] & 0xff;
2281 *p++ = (values [col] >> 8) & 0xff;
2282 *p++ = (values [col] >> 16) & 0xff;
2283 *p++ = (values [col] >> 24) & 0xff;
2286 g_assert_not_reached ();
2290 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
2293 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
2294 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
2295 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
2296 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
2297 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
2299 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
2303 * Some tables in metadata need to be sorted according to some criteria, but
2304 * when methods and fields are first created with reflection, they may be assigned a token
2305 * that doesn't correspond to the final token they will get assigned after the sorting.
2306 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
2307 * with the reflection objects that represent them. Once all the tables are set up, the
2308 * reflection objects will contains the correct table index. fixup_method() will fixup the
2309 * tokens for the method with ILGenerator @ilgen.
2312 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
2313 guint32 code_idx = GPOINTER_TO_UINT (value);
2314 MonoReflectionILTokenInfo *iltoken;
2315 MonoReflectionFieldBuilder *field;
2316 MonoReflectionCtorBuilder *ctor;
2317 MonoReflectionMethodBuilder *method;
2318 MonoReflectionTypeBuilder *tb;
2319 MonoReflectionArrayMethod *am;
2321 unsigned char *target;
2323 for (i = 0; i < ilgen->num_token_fixups; ++i) {
2324 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
2325 target = assembly->code.data + code_idx + iltoken->code_pos;
2326 switch (target [3]) {
2327 case MONO_TABLE_FIELD:
2328 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
2329 field = (MonoReflectionFieldBuilder *)iltoken->member;
2330 idx = field->table_idx;
2331 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
2332 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
2333 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
2335 g_assert_not_reached ();
2338 case MONO_TABLE_METHOD:
2339 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
2340 method = (MonoReflectionMethodBuilder *)iltoken->member;
2341 idx = method->table_idx;
2342 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
2343 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
2344 idx = ctor->table_idx;
2345 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
2346 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
2347 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
2349 g_assert_not_reached ();
2352 case MONO_TABLE_TYPEDEF:
2353 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
2354 g_assert_not_reached ();
2355 tb = (MonoReflectionTypeBuilder *)iltoken->member;
2356 idx = tb->table_idx;
2358 case MONO_TABLE_MEMBERREF:
2359 if (strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod"))
2360 g_assert_not_reached ();
2361 am = (MonoReflectionArrayMethod*)iltoken->member;
2362 idx = am->table_idx;
2365 g_error ("got unexpected table 0x%02x in fixup", target [3]);
2367 target [0] = idx & 0xff;
2368 target [1] = (idx >> 8) & 0xff;
2369 target [2] = (idx >> 16) & 0xff;
2374 assembly_add_resource (MonoDynamicAssembly *assembly, MonoReflectionResource *rsrc)
2376 MonoDynamicTable *table;
2380 char *b = blob_size;
2382 guint32 idx, offset;
2384 if (rsrc->filename) {
2385 name = mono_string_to_utf8 (rsrc->filename);
2386 sname = g_path_get_basename (name);
2388 table = &assembly->tables [MONO_TABLE_FILE];
2390 alloc_table (table, table->rows);
2391 values = table->values + table->next_idx * MONO_FILE_SIZE;
2392 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
2393 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
2396 mono_sha1_get_digest_from_file (name, hash);
2397 mono_metadata_encode_value (20, b, &b);
2398 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2399 mono_image_add_stream_data (&assembly->blob, hash, 20);
2401 idx = table->next_idx++;
2402 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
2406 offset = mono_array_length (rsrc->data);
2407 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
2408 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
2409 offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
2410 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
2414 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
2416 alloc_table (table, table->rows);
2417 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
2418 values [MONO_MANIFEST_OFFSET] = offset;
2419 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
2420 name = mono_string_to_utf8 (rsrc->name);
2421 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
2423 values [MONO_MANIFEST_IMPLEMENTATION] = idx;
2428 set_version_from_string (MonoString *version, guint32 *values)
2430 gchar *ver, *p, *str;
2433 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
2434 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
2435 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
2436 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
2439 ver = str = mono_string_to_utf8 (version);
2440 for (i = 0; i < 4; ++i) {
2441 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
2447 /* handle Revision and Build */
2457 load_public_key (MonoString *fname, MonoDynamicAssembly *assembly) {
2458 char *name, *content;
2464 name = mono_string_to_utf8 (fname);
2465 if (g_file_get_contents (name, &content, &len, NULL)) {
2467 char *b = blob_size;
2468 /* check it's a public key or keypair */
2469 mono_metadata_encode_value (len, b, &b);
2470 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
2471 mono_image_add_stream_data (&assembly->blob, content, len);
2473 /* need to get the actual value from the key type... */
2474 assembly->strong_name_size = 128;
2475 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
2477 /* FIXME: how do we tell mcs if loading fails? */
2483 * mono_image_build_metadata() will fill the info in all the needed metadata tables
2484 * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
2485 * and recursively outputs the info for a module. Each module will output all the info
2486 * about it's types etc.
2487 * At the end of the process, method and field tokens are fixed up and the on-disk
2488 * compressed metadata representation is created.
2491 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
2493 MonoDynamicTable *table;
2494 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
2495 MonoDomain *domain = mono_object_domain (assemblyb);
2501 if (assembly->text_rva)
2504 assembly->text_rva = START_TEXT_RVA;
2506 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2507 alloc_table (table, 1);
2508 values = table->values + MONO_ASSEMBLY_SIZE;
2509 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2510 name = mono_string_to_utf8 (assemblyb->name);
2511 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
2513 if (assemblyb->culture) {
2514 name = mono_string_to_utf8 (assemblyb->culture);
2515 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
2518 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2520 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->keyfile, assembly);
2521 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2522 set_version_from_string (assemblyb->version, values);
2524 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2525 table->rows = 1; /* .<Module> */
2527 alloc_table (table, table->rows);
2529 * Set the first entry.
2531 values = table->values + table->columns;
2532 values [MONO_TYPEDEF_FLAGS] = 0;
2533 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2534 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2535 values [MONO_TYPEDEF_EXTENDS] = 0;
2536 values [MONO_TYPEDEF_FIELD_LIST] = 1;
2537 values [MONO_TYPEDEF_METHOD_LIST] = 1;
2540 * handle global methods
2541 * FIXME: test what to do when global methods are defined in multiple modules.
2543 if (assemblyb->modules) {
2544 MonoReflectionModuleBuilder *mod = mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, 0);
2545 if (mod->global_methods) {
2546 table = &assembly->tables [MONO_TABLE_METHOD];
2547 table->rows += mono_array_length (mod->global_methods);
2548 alloc_table (table, table->rows);
2549 for (i = 0; i < mono_array_length (mod->global_methods); ++i)
2550 mono_image_get_method_info (
2551 mono_array_get (mod->global_methods, MonoReflectionMethodBuilder*, i), assembly);
2555 if (assemblyb->modules) {
2556 len = mono_array_length (assemblyb->modules);
2557 table = &assembly->tables [MONO_TABLE_MODULE];
2558 alloc_table (table, len);
2559 for (i = 0; i < len; ++i)
2560 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
2562 table = &assembly->tables [MONO_TABLE_MODULE];
2564 alloc_table (table, table->rows);
2565 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
2570 if (assemblyb->modules) {
2571 /* Collect all types into a list sorted by their table_idx */
2572 GPtrArray *types = g_ptr_array_new ();
2574 len = mono_array_length (assemblyb->modules);
2575 for (i = 0; i < len; ++i) {
2576 MonoReflectionModuleBuilder *mb =
2577 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2579 for (i = 0; i < mono_array_length (mb->types); ++i) {
2580 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
2581 collect_types (types, type);
2585 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
2586 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2587 table->rows += types->len;
2588 alloc_table (table, table->rows);
2590 for (i = 0; i < types->len; ++i) {
2591 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
2592 mono_image_get_type_info (domain, type, assembly);
2594 g_ptr_array_free (types, TRUE);
2598 * table->rows is already set above and in mono_image_fill_module_table.
2600 /* add all the custom attributes at the end, once all the indexes are stable */
2601 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
2603 if (assemblyb->modules) {
2604 len = mono_array_length (assemblyb->modules);
2605 for (i = 0; i < len; ++i)
2606 module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
2610 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2614 * mono_image_insert_string:
2615 * @assembly: assembly builder object
2618 * Insert @str into the user string stream of @assembly.
2621 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
2627 MONO_ARCH_SAVE_REGS;
2629 if (!assembly->dynamic_assembly)
2630 mono_image_basic_init (assembly);
2632 if (assembly->dynamic_assembly->save) {
2633 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
2634 idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
2635 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2637 char *swapped = g_malloc (2 * mono_string_length (str));
2638 const char *p = (const char*)mono_string_chars (str);
2640 swap_with_size (swapped, p, 2, mono_string_length (str));
2641 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2645 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2647 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2650 idx = assembly->dynamic_assembly->us.index ++;
2652 mono_g_hash_table_insert (assembly->dynamic_assembly->tokens,
2653 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
2655 return MONO_TOKEN_STRING | idx;
2659 * mono_image_create_token:
2660 * @assembly: a dynamic assembly
2663 * Get a token to insert in the IL code stream for the given MemberInfo.
2664 * @obj can be one of:
2665 * ConstructorBuilder
2675 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2680 klass = obj->vtable->klass;
2681 if (strcmp (klass->name, "MethodBuilder") == 0) {
2682 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2683 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2684 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2686 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2687 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2688 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2689 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2691 else if (strcmp (klass->name, "FieldBuilder") == 0) {
2692 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2693 token = mb->table_idx | MONO_TOKEN_FIELD_DEF;
2695 else if (strcmp (klass->name, "TypeBuilder") == 0) {
2696 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2697 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
2699 else if (strcmp (klass->name, "MonoType") == 0) {
2700 MonoReflectionType *tb = (MonoReflectionType *)obj;
2701 token = mono_metadata_token_from_dor (
2702 mono_image_typedef_or_ref (assembly, tb->type));
2704 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
2705 strcmp (klass->name, "MonoMethod") == 0) {
2706 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2707 if (m->method->klass->image == assembly->assembly.image) {
2708 static guint32 method_table_idx = 0xffffff;
2710 * Each token should have a unique index, but the indexes are
2711 * assigned by managed code, so we don't know about them. An
2712 * easy solution is to count backwards...
2714 method_table_idx --;
2715 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
2717 token = mono_image_get_methodref_token (assembly, m->method);
2718 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2720 else if (strcmp (klass->name, "MonoField") == 0) {
2721 MonoReflectionField *f = (MonoReflectionField *)obj;
2722 if (f->klass->image == assembly->assembly.image) {
2723 static guint32 field_table_idx = 0xffffff;
2725 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
2727 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2728 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2730 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2731 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2732 token = mono_image_get_array_token (assembly, m);
2734 else if (strcmp (klass->name, "SignatureHelper") == 0) {
2735 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
2736 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
2739 g_error ("requested token for %s\n", klass->name);
2741 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
2748 guint32 import_lookup_table;
2752 guint32 import_address_table_rva;
2760 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
2763 create_dynamic_mono_image (char *assembly_name, char *module_name)
2767 image = g_new0 (MonoImage, 1);
2769 /* keep in sync with image.c */
2770 image->name = assembly_name;
2771 image->assembly_name = image->name; /* they may be different */
2772 image->module_name = module_name;
2773 image->references = g_new0 (MonoAssembly*, 1);
2774 image->references [0] = NULL;
2776 image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2777 image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2778 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2779 image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2781 image->delegate_begin_invoke_cache =
2782 g_hash_table_new ((GHashFunc)mono_signature_hash,
2783 (GCompareFunc)mono_metadata_signature_equal);
2784 image->delegate_end_invoke_cache =
2785 g_hash_table_new ((GHashFunc)mono_signature_hash,
2786 (GCompareFunc)mono_metadata_signature_equal);
2787 image->delegate_invoke_cache =
2788 g_hash_table_new ((GHashFunc)mono_signature_hash,
2789 (GCompareFunc)mono_metadata_signature_equal);
2791 image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2792 image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2793 image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2794 image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2795 image->synchronized_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2801 * mono_image_basic_init:
2802 * @assembly: an assembly builder object
2804 * Create the MonoImage that represents the assembly builder and setup some
2805 * of the helper hash table and the basic metadata streams.
2808 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2810 static const guchar entrycode [16] = {0xff, 0x25, 0};
2811 MonoDynamicAssembly *assembly;
2815 MONO_ARCH_SAVE_REGS;
2817 if (assemblyb->dynamic_assembly)
2821 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
2823 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2826 assembly->assembly.dynamic = assembly;
2827 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
2828 assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2829 assembly->method_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2830 assembly->field_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2831 assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2832 assembly->tokens = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2833 assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2834 assembly->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
2836 string_heap_init (&assembly->sheap);
2837 mono_image_add_stream_data (&assembly->us, "", 1);
2838 add_to_blob_cached (assembly, (char*) "", 1, NULL, 0);
2839 /* import tables... */
2840 mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2841 assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2842 assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2843 mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2844 assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2845 mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2846 assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2847 stream_data_align (&assembly->code);
2849 assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2851 for (i=0; i < 64; ++i) {
2852 assembly->tables [i].next_idx = 1;
2853 assembly->tables [i].columns = table_sizes [i];
2856 assembly->run = assemblyb->access != 2;
2857 assembly->save = assemblyb->access != 1;
2859 image = create_dynamic_mono_image (mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
2860 assembly->assembly.aname.name = image->name;
2861 image->assembly = (MonoAssembly*)assembly;
2862 assembly->assembly.image = image;
2864 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
2865 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
2869 calc_section_size (MonoDynamicAssembly *assembly)
2873 /* alignment constraints */
2874 assembly->code.index += 3;
2875 assembly->code.index &= ~3;
2876 assembly->meta_size += 3;
2877 assembly->meta_size &= ~3;
2878 assembly->resources.index += 3;
2879 assembly->resources.index &= ~3;
2881 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2882 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2885 assembly->sections [MONO_SECTION_RELOC].size = 12;
2886 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2893 * mono_image_create_pefile:
2894 * @assemblyb: an assembly builder object
2896 * When we need to save an assembly, we first call this function that ensures the metadata
2897 * tables are built for all the modules in the assembly. This function creates the PE-COFF
2898 * header, the image sections, the CLI header etc. all the data is written in
2899 * assembly->pefile where it can be easily retrieved later in chunks.
2902 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
2903 MonoMSDOSHeader *msdos;
2904 MonoDotNetHeader *header;
2905 MonoSectionTable *section;
2906 MonoCLIHeader *cli_header;
2907 guint32 size, image_size, virtual_base, text_offset;
2908 guint32 header_start, section_start, file_offset, virtual_offset;
2909 MonoDynamicAssembly *assembly;
2910 MonoDynamicStream *pefile;
2912 guint32 *rva, value;
2915 static const unsigned char msheader[] = {
2916 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2917 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2918 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2920 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2921 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2922 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2923 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2926 mono_image_basic_init (assemblyb);
2927 assembly = assemblyb->dynamic_assembly;
2929 /* already created */
2930 if (assembly->pefile.index)
2933 mono_image_build_metadata (assemblyb);
2935 if (assemblyb->resources) {
2936 int len = mono_array_length (assemblyb->resources);
2937 for (i = 0; i < len; ++i)
2938 assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
2942 build_compressed_metadata (assembly);
2944 nsections = calc_section_size (assembly);
2946 pefile = &assembly->pefile;
2948 /* The DOS header and stub */
2949 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2950 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
2952 /* the dotnet header */
2953 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2955 /* the section tables */
2956 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2958 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2959 virtual_offset = VIRT_ALIGN;
2962 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2963 if (!assembly->sections [i].size)
2966 file_offset += FILE_ALIGN - 1;
2967 file_offset &= ~(FILE_ALIGN - 1);
2968 virtual_offset += VIRT_ALIGN - 1;
2969 virtual_offset &= ~(VIRT_ALIGN - 1);
2971 assembly->sections [i].offset = file_offset;
2972 assembly->sections [i].rva = virtual_offset;
2974 file_offset += assembly->sections [i].size;
2975 virtual_offset += assembly->sections [i].size;
2976 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2979 file_offset += FILE_ALIGN - 1;
2980 file_offset &= ~(FILE_ALIGN - 1);
2981 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
2983 image_size += section_start + sizeof (MonoSectionTable) * nsections;
2985 /* back-patch info */
2986 msdos = (MonoMSDOSHeader*)pefile->data;
2987 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
2988 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
2989 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2991 header = (MonoDotNetHeader*)(pefile->data + header_start);
2992 header->pesig [0] = 'P';
2993 header->pesig [1] = 'E';
2995 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
2996 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2997 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2998 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2999 if (assemblyb->pekind == 1) {
3001 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
3004 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
3007 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
3009 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
3010 header->pe.pe_major = 6;
3011 header->pe.pe_minor = 0;
3012 size = assembly->sections [MONO_SECTION_TEXT].size;
3013 size += FILE_ALIGN - 1;
3014 size &= ~(FILE_ALIGN - 1);
3015 header->pe.pe_code_size = size;
3016 size = assembly->sections [MONO_SECTION_RSRC].size;
3017 size += FILE_ALIGN - 1;
3018 size &= ~(FILE_ALIGN - 1);
3019 header->pe.pe_data_size = size;
3020 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
3021 header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
3022 header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
3023 /* pe_rva_entry_point always at the beginning of the text section */
3024 header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
3026 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
3027 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
3028 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
3029 header->nt.pe_os_major = GUINT16_FROM_LE (4);
3030 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
3031 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
3032 size = section_start;
3033 size += FILE_ALIGN - 1;
3034 size &= ~(FILE_ALIGN - 1);
3035 header->nt.pe_header_size = GUINT32_FROM_LE (size);
3037 size += VIRT_ALIGN - 1;
3038 size &= ~(VIRT_ALIGN - 1);
3039 header->nt.pe_image_size = GUINT32_FROM_LE (size);
3042 // Translate the PEFileKind value to the value expected by the Windows loader
3045 short kind = assemblyb->pekind;
3048 // PEFileKinds.ConsoleApplication == 2
3049 // PEFileKinds.WindowApplication == 3
3052 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
3053 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
3059 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
3061 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
3062 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
3063 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
3064 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
3065 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
3066 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
3068 /* fill data directory entries */
3070 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
3071 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
3073 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
3074 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
3076 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
3077 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
3078 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
3079 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
3080 /* patch imported function RVA name */
3081 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
3082 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
3084 /* the import table */
3085 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
3086 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
3087 /* patch imported dll RVA name and other entries in the dir */
3088 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
3089 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
3090 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
3091 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
3092 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
3093 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
3095 p = (assembly->code.data + assembly->ilt_offset);
3096 value = (assembly->text_rva + assembly->imp_names_offset - 2);
3097 *p++ = (value) & 0xff;
3098 *p++ = (value >> 8) & (0xff);
3099 *p++ = (value >> 16) & (0xff);
3100 *p++ = (value >> 24) & (0xff);
3102 /* the CLI header info */
3103 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
3104 cli_header->ch_size = GUINT32_FROM_LE (72);
3105 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
3106 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
3107 if (assemblyb->entry_point)
3108 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
3110 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
3111 /* The embedded managed resources */
3112 text_offset = assembly->text_rva + assembly->code.index;
3113 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
3114 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
3115 text_offset += assembly->resources.index;
3116 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
3117 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
3118 text_offset += assembly->meta_size;
3119 if (assembly->strong_name_size) {
3120 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
3121 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
3122 text_offset += assembly->strong_name_size;
3125 /* write the section tables and section content */
3126 section = (MonoSectionTable*)(pefile->data + section_start);
3127 for (i = 0; i < MONO_SECTION_MAX; ++i) {
3128 static const char *section_names [] = {
3129 ".text", ".rsrc", ".reloc"
3131 if (!assembly->sections [i].size)
3133 strcpy (section->st_name, section_names [i]);
3134 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
3135 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
3136 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
3137 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
3138 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
3139 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
3140 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
3142 case MONO_SECTION_TEXT:
3143 /* patch entry point */
3144 p = (assembly->code.data + 2);
3145 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
3146 *p++ = (value) & 0xff;
3147 *p++ = (value >> 8) & 0xff;
3148 *p++ = (value >> 16) & 0xff;
3149 *p++ = (value >> 24) & 0xff;
3151 text_offset = assembly->sections [i].offset;
3152 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
3153 text_offset += assembly->code.index;
3154 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
3155 text_offset += assembly->resources.index;
3156 memcpy (pefile->data + text_offset, assembly->assembly.image->raw_metadata, assembly->meta_size);
3157 text_offset += assembly->meta_size;
3158 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
3160 g_free (assembly->assembly.image->raw_metadata);
3162 case MONO_SECTION_RELOC:
3163 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
3164 *rva = GUINT32_FROM_LE (assembly->text_rva);
3166 *rva = GUINT32_FROM_LE (12);
3168 data16 = (guint16*)rva;
3170 * the entrypoint is always at the start of the text section
3171 * 3 is IMAGE_REL_BASED_HIGHLOW
3172 * 2 is patch_size_rva - text_rva
3174 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
3176 *data16 = 0; /* terminate */
3178 case MONO_SECTION_RSRC:
3180 g_assert_not_reached ();
3185 /* check that the file is properly padded */
3188 FILE *f = fopen ("mypetest.exe", "w");
3189 fwrite (pefile->data, pefile->index, 1, f);
3196 * We need to return always the same object for MethodInfo, FieldInfo etc..
3197 * but we need to consider the reflected type.
3198 * type uses a different hash, since it uses custom hash/equal functions.
3203 MonoClass *refclass;
3207 reflected_equal (gconstpointer a, gconstpointer b) {
3208 const ReflectedEntry *ea = a;
3209 const ReflectedEntry *eb = b;
3211 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
3215 reflected_hash (gconstpointer a) {
3216 const ReflectedEntry *ea = a;
3217 return GPOINTER_TO_UINT (ea->item);
3220 #define CHECK_OBJECT(t,p,k) \
3226 mono_domain_lock (domain); \
3227 if (!domain->refobject_hash) \
3228 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
3229 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
3230 mono_domain_unlock (domain); \
3236 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
3238 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
3241 #define CACHE_OBJECT(p,o,k) \
3243 ReflectedEntry *e = ALLOC_REFENTRY; \
3245 e->refclass = (k); \
3246 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
3247 mono_domain_unlock (domain); \
3251 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
3253 /* this is done only once */
3254 mono_domain_lock (domain);
3255 CACHE_OBJECT (assembly, res, NULL);
3259 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoImage *module)
3261 /* this is done only once */
3262 mono_domain_lock (domain);
3263 CACHE_OBJECT (module, res, NULL);
3267 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
3269 MonoImage *image = moduleb->module.image;
3270 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
3273 /* a MonoImage was already created in mono_image_basic_init () */
3274 image = ab->dynamic_assembly->assembly.image;
3276 image = create_dynamic_mono_image (mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.name));
3278 moduleb->module.image = image;
3279 register_module (mono_object_domain (moduleb), moduleb, image);
3284 * mono_assembly_get_object:
3285 * @domain: an app domain
3286 * @assembly: an assembly
3288 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
3290 MonoReflectionAssembly*
3291 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
3293 static MonoClass *System_Reflection_Assembly;
3294 MonoReflectionAssembly *res;
3296 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
3297 if (!System_Reflection_Assembly)
3298 System_Reflection_Assembly = mono_class_from_name (
3299 mono_defaults.corlib, "System.Reflection", "Assembly");
3300 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
3301 res->assembly = assembly;
3302 CACHE_OBJECT (assembly, res, NULL);
3307 MonoReflectionModule*
3308 mono_module_get_object (MonoDomain *domain, MonoImage *image)
3310 static MonoClass *System_Reflection_Module;
3311 MonoReflectionModule *res;
3313 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
3314 if (!System_Reflection_Module)
3315 System_Reflection_Module = mono_class_from_name (
3316 mono_defaults.corlib, "System.Reflection", "Module");
3317 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
3320 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
3322 res->fqname = mono_string_new (domain, image->name);
3323 res->name = mono_string_new (domain, image->name);
3324 res->scopename = mono_string_new (domain, image->module_name);
3326 CACHE_OBJECT (image, res, NULL);
3332 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
3334 if ((t1->type != t2->type) ||
3335 (t1->byref != t2->byref))
3339 case MONO_TYPE_VOID:
3340 case MONO_TYPE_BOOLEAN:
3341 case MONO_TYPE_CHAR:
3352 case MONO_TYPE_STRING:
3355 case MONO_TYPE_OBJECT:
3356 case MONO_TYPE_TYPEDBYREF:
3358 case MONO_TYPE_VALUETYPE:
3359 case MONO_TYPE_CLASS:
3360 return t1->data.klass == t2->data.klass;
3362 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3363 case MONO_TYPE_SZARRAY:
3365 if (t1->data.type->type != t2->data.type->type)
3367 if (t1->data.type->type == MONO_TYPE_CLASS || t1->data.type->type == MONO_TYPE_VALUETYPE)
3368 return t1->data.type->data.klass == t2->data.type->data.klass;
3369 if (t1->data.type->type == MONO_TYPE_SZARRAY) {
3374 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3375 case MONO_TYPE_ARRAY:
3376 if (t1->data.array->rank != t2->data.array->rank)
3378 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
3380 g_error ("implement type compare for %0x!", t1->type);
3388 mymono_metadata_type_hash (MonoType *t1)
3394 hash |= t1->byref << 6; /* do not collide with t1->type values */
3396 case MONO_TYPE_VALUETYPE:
3397 case MONO_TYPE_CLASS:
3398 /* check if the distribution is good enough */
3399 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
3401 case MONO_TYPE_SZARRAY:
3402 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
3408 * mono_type_get_object:
3409 * @domain: an app domain
3412 * Return an System.MonoType object representing the type @type.
3415 mono_type_get_object (MonoDomain *domain, MonoType *type)
3417 MonoReflectionType *res;
3418 MonoClass *klass = mono_class_from_mono_type (type);
3420 mono_domain_lock (domain);
3421 if (!domain->type_hash)
3422 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
3423 (GCompareFunc)mymono_metadata_type_equal);
3424 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
3425 mono_domain_unlock (domain);
3428 if (klass->reflection_info && !klass->wastypebuilder) {
3429 //g_assert_not_reached ();
3430 /* should this be considered an error condition? */
3432 mono_domain_unlock (domain);
3433 return klass->reflection_info;
3436 mono_class_init (klass);
3437 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
3439 mono_g_hash_table_insert (domain->type_hash, type, res);
3440 mono_domain_unlock (domain);
3445 * mono_method_get_object:
3446 * @domain: an app domain
3448 * @refclass: the reflected type (can be NULL)
3450 * Return an System.Reflection.MonoMethod object representing the method @method.
3452 MonoReflectionMethod*
3453 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
3456 * We use the same C representation for methods and constructors, but the type
3457 * name in C# is different.
3461 MonoReflectionMethod *ret;
3464 refclass = method->klass;
3466 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
3467 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3468 cname = "MonoCMethod";
3470 cname = "MonoMethod";
3471 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
3473 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
3474 ret->method = method;
3475 ret->name = mono_string_new (domain, method->name);
3476 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
3477 CACHE_OBJECT (method, ret, refclass);
3482 * mono_field_get_object:
3483 * @domain: an app domain
3487 * Return an System.Reflection.MonoField object representing the field @field
3490 MonoReflectionField*
3491 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
3493 MonoReflectionField *res;
3496 CHECK_OBJECT (MonoReflectionField *, field, klass);
3497 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
3498 res = (MonoReflectionField *)mono_object_new (domain, oklass);
3501 CACHE_OBJECT (field, res, klass);
3506 * mono_property_get_object:
3507 * @domain: an app domain
3509 * @property: a property
3511 * Return an System.Reflection.MonoProperty object representing the property @property
3514 MonoReflectionProperty*
3515 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
3517 MonoReflectionProperty *res;
3520 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
3521 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
3522 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
3524 res->property = property;
3525 CACHE_OBJECT (property, res, klass);
3530 * mono_event_get_object:
3531 * @domain: an app domain
3535 * Return an System.Reflection.MonoEvent object representing the event @event
3538 MonoReflectionEvent*
3539 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
3541 MonoReflectionEvent *res;
3544 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
3545 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
3546 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
3549 CACHE_OBJECT (event, res, klass);
3554 * mono_param_get_objects:
3555 * @domain: an app domain
3558 * Return an System.Reflection.ParameterInfo array object representing the parameters
3559 * in the method @method.
3561 MonoReflectionParameter**
3562 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
3564 MonoReflectionParameter **res;
3565 MonoReflectionMethod *member;
3570 if (!method->signature->param_count)
3573 /* Note: the cache is based on the address of the signature into the method
3574 * since we already cache MethodInfos with the method as keys.
3576 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature), NULL);
3578 member = mono_method_get_object (domain, method, NULL);
3579 names = g_new (char *, method->signature->param_count);
3580 mono_method_get_param_names (method, (const char **) names);
3582 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
3584 res = GC_MALLOC (sizeof (MonoReflectionParameter*) * method->signature->param_count);
3586 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
3588 for (i = 0; i < method->signature->param_count; ++i) {
3589 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
3590 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
3591 res [i]->DefaultValueImpl = NULL; /* FIXME */
3592 res [i]->MemberImpl = (MonoObject*)member;
3593 res [i]->NameImpl = mono_string_new (domain, names [i]);
3594 res [i]->PositionImpl = i + 1;
3595 res [i]->AttrsImpl = method->signature->params [i]->attrs;
3598 CACHE_OBJECT (&(method->signature), res, NULL);
3603 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
3607 memset (assembly, 0, sizeof (MonoAssemblyName));
3609 assembly->culture = "";
3611 while (*p && (isalnum (*p) || *p == '.' || *p == '-'))
3614 while (*p == ' ' || *p == ',') {
3623 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
3625 assembly->major = strtoul (p, &s, 10);
3626 if (s == p || *s != '.')
3629 assembly->minor = strtoul (p, &s, 10);
3630 if (s == p || *s != '.')
3633 assembly->build = strtoul (p, &s, 10);
3634 if (s == p || *s != '.')
3637 assembly->revision = strtoul (p, &s, 10);
3640 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
3642 if (strncmp (p, "neutral", 7) == 0) {
3643 assembly->culture = "";
3646 assembly->culture = p;
3647 while (*p && *p != ',') {
3651 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
3654 while (*s && isxdigit (*s)) {
3658 assembly->hash_len = s - p;
3659 if (!(s-p) || ((s-p) & 1))
3661 assembly->hash_value = s = p;
3662 while (*s && isxdigit (*s)) {
3664 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3667 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3672 while (*p && *p != ',')
3676 while (*p == ' ' || *p == ',') {
3690 * mono_reflection_parse_type:
3693 * Parse a type name as accepted by the GetType () method and output the info
3694 * extracted in the info structure.
3695 * the name param will be mangled, so, make a copy before passing it to this function.
3696 * The fields in info will be valid until the memory pointed to by name is valid.
3697 * Returns 0 on parse error.
3698 * See also mono_type_get_name () below.
3701 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
3703 char *start, *p, *w, *last_point, *startn;
3704 int in_modifiers = 0;
3705 int isbyref = 0, rank;
3707 start = p = w = name;
3709 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
3710 info->name = info->name_space = NULL;
3711 info->nested = NULL;
3712 info->modifiers = NULL;
3714 /* last_point separates the namespace from the name */
3720 *p = 0; /* NULL terminate the name */
3722 info->nested = g_list_append (info->nested, startn);
3723 /* we have parsed the nesting namespace + name */
3727 info->name_space = start;
3729 info->name = last_point + 1;
3731 info->name_space = (char *)"";
3757 info->name_space = start;
3759 info->name = last_point + 1;
3761 info->name_space = (char *)"";
3768 if (isbyref) /* only one level allowed by the spec */
3771 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
3775 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
3786 else if (*p != '*') /* '*' means unknown lower bound */
3792 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
3804 return 0; /* missing assembly name */
3805 if (!assembly_name_to_aname (&info->assembly, p))
3811 if (info->assembly.name)
3814 *w = 0; /* terminate class name */
3815 if (!info->name || !*info->name)
3817 /* add other consistency checks */
3822 mono_type_get_name_recurse (MonoType *type, GString *str)
3826 switch (type->type) {
3827 case MONO_TYPE_ARRAY: {
3828 int i, rank = type->data.array->rank;
3830 mono_type_get_name_recurse (type->data.array->type, str);
3831 g_string_append_c (str, '[');
3832 for (i = 1; i < rank; i++)
3833 g_string_append_c (str, ',');
3834 g_string_append_c (str, ']');
3837 case MONO_TYPE_SZARRAY:
3838 mono_type_get_name_recurse (type->data.type, str);
3839 g_string_append (str, "[]");
3842 mono_type_get_name_recurse (type->data.type, str);
3843 g_string_append_c (str, '*');
3846 klass = mono_class_from_mono_type (type);
3847 if (klass->nested_in) {
3848 mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
3849 g_string_append_c (str, '+');
3851 if (*klass->name_space) {
3852 g_string_append (str, klass->name_space);
3853 g_string_append_c (str, '.');
3855 g_string_append (str, klass->name);
3861 * mono_type_get_name:
3864 * Returns the string representation for type as required by System.Reflection.
3865 * The inverse of mono_reflection_parse_type ().
3868 mono_type_get_name (MonoType *type)
3870 GString* result = g_string_new ("");
3871 mono_type_get_name_recurse (type, result);
3874 g_string_append_c (result, '&');
3876 return g_string_free (result, FALSE);
3880 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3887 image = mono_defaults.corlib;
3890 klass = mono_class_from_name_case (image, info->name_space, info->name);
3892 klass = mono_class_from_name (image, info->name_space, info->name);
3895 for (mod = info->nested; mod; mod = mod->next) {
3898 mono_class_init (klass);
3899 nested = klass->nested_classes;
3902 klass = nested->data;
3904 if (g_strcasecmp (klass->name, mod->data) == 0)
3907 if (strcmp (klass->name, mod->data) == 0)
3911 nested = nested->next;
3918 mono_class_init (klass);
3919 for (mod = info->modifiers; mod; mod = mod->next) {
3920 modval = GPOINTER_TO_UINT (mod->data);
3921 if (!modval) { /* byref: must be last modifier */
3922 return &klass->this_arg;
3923 } else if (modval == -1) {
3924 klass = mono_ptr_class_get (&klass->byval_arg);
3925 } else { /* array rank */
3926 klass = mono_array_class_get (&klass->byval_arg, modval);
3928 mono_class_init (klass);
3931 return &klass->byval_arg;
3935 * mono_reflection_get_type:
3936 * @image: a metadata context
3937 * @info: type description structure
3938 * @ignorecase: flag for case-insensitive string compares
3940 * Build a MonoType from the type description in @info.
3945 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3948 MonoReflectionAssembly *assembly;
3952 type = mono_reflection_get_type_internal (image, info, ignorecase);
3955 if (!mono_domain_has_type_resolve (mono_domain_get ()))
3958 // Reconstruct the type name
3959 fullName = g_string_new ("");
3960 if (info->name_space && (info->name_space [0] != '\0'))
3961 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
3963 g_string_printf (fullName, info->name);
3964 for (mod = info->nested; mod; mod = mod->next)
3965 g_string_append_printf (fullName, "+%s", (char*)mod->data);
3968 mono_domain_try_type_resolve (
3969 mono_domain_get (), fullName->str, NULL);
3970 if (assembly && (!image || (assembly->assembly->image == image)))
3971 type = mono_reflection_get_type_internal (assembly->assembly->image,
3973 g_string_free (fullName, TRUE);
3978 * mono_reflection_type_from_name:
3980 * @image: a metadata context (can be NULL).
3982 * Retrieves a MonoType from its @name. If the name is not fully qualified,
3983 * it defaults to get the type from @image or, if @image is NULL or loading
3984 * from it fails, uses corlib.
3988 mono_reflection_type_from_name (char *name, MonoImage *image)
3991 MonoTypeNameParse info;
3993 /*g_print ("requested type %s\n", str);*/
3994 if (!mono_reflection_parse_type (name, &info)) {
3995 g_list_free (info.modifiers);
3996 g_list_free (info.nested);
4000 if (info.assembly.name) {
4001 image = mono_image_loaded (info.assembly.name);
4002 /* do we need to load if it's not already loaded? */
4004 g_list_free (info.modifiers);
4005 g_list_free (info.nested);
4008 } else if (image == NULL) {
4009 image = mono_defaults.corlib;
4012 type = mono_reflection_get_type (image, &info, FALSE);
4013 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
4014 image = mono_defaults.corlib;
4015 type = mono_reflection_get_type (image, &info, FALSE);
4018 g_list_free (info.modifiers);
4019 g_list_free (info.nested);
4024 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
4026 int slen, type = t->type;
4031 case MONO_TYPE_BOOLEAN: {
4032 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
4037 case MONO_TYPE_CHAR:
4039 case MONO_TYPE_I2: {
4040 guint16 *val = g_malloc (sizeof (guint16));
4045 #if SIZEOF_VOID_P == 4
4051 case MONO_TYPE_I4: {
4052 guint32 *val = g_malloc (sizeof (guint32));
4057 #if SIZEOF_VOID_P == 8
4058 case MONO_TYPE_U: /* error out instead? this should probably not happen */
4063 case MONO_TYPE_I8: {
4064 guint64 *val = g_malloc (sizeof (guint64));
4069 case MONO_TYPE_VALUETYPE:
4070 if (t->data.klass->enumtype) {
4071 type = t->data.klass->enum_basetype->type;
4074 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
4077 case MONO_TYPE_STRING:
4078 if (*p == (char)0xFF) {
4082 slen = mono_metadata_decode_value (p, &p);
4084 return mono_string_new_len (mono_domain_get (), p, slen);
4085 case MONO_TYPE_CLASS: {
4088 if (*p == (char)0xFF) {
4093 slen = mono_metadata_decode_value (p, &p);
4094 n = g_memdup (p, slen + 1);
4096 t = mono_reflection_type_from_name (n, image);
4098 g_warning ("Cannot load type '%s'", n);
4101 return mono_type_get_object (mono_domain_get (), t);
4103 case MONO_TYPE_OBJECT: {
4111 } else if (subt == 0x0E) {
4112 type = MONO_TYPE_STRING;
4114 } else if (subt == 0x55) {
4117 slen = mono_metadata_decode_value (p, &p);
4118 n = g_memdup (p, slen + 1);
4120 t = mono_reflection_type_from_name (n, image);
4122 g_warning ("Cannot load type '%s'", n);
4125 subc = mono_class_from_mono_type (t);
4126 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
4127 MonoType simple_type = {{0}};
4128 simple_type.type = subt;
4129 subc = mono_class_from_mono_type (&simple_type);
4131 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
4133 val = load_cattr_value (image, &subc->byval_arg, p, end);
4134 obj = mono_object_new (mono_domain_get (), subc);
4135 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
4139 case MONO_TYPE_SZARRAY:
4145 if (alen == 0xffffffff) {
4149 arr = mono_array_new (mono_domain_get(), mono_class_from_mono_type (t->data.type), alen);
4150 switch (t->data.type->type)
4154 case MONO_TYPE_BOOLEAN:
4155 for (i=0;i<alen;i++)
4157 MonoBoolean val=*p++;
4158 mono_array_set(arr,MonoBoolean,i,val);
4161 case MONO_TYPE_CHAR:
4164 for (i=0;i<alen;i++)
4166 guint16 val=read16(p);
4167 mono_array_set(arr,guint16,i,val);
4174 for (i=0;i<alen;i++)
4176 guint32 val=read32(p);
4177 mono_array_set(arr,guint32,i,val);
4184 for (i=0;i<alen;i++)
4186 guint64 val=read64(p);
4187 mono_array_set(arr,guint64,i,val);
4191 case MONO_TYPE_CLASS:
4192 case MONO_TYPE_STRING:
4193 for (i = 0; i < alen; i++) {
4194 MonoObject *item = load_cattr_value (image, t->data.type, p, &p);
4195 mono_array_set (arr, gpointer, i, item);
4199 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
4205 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
4211 type_is_reference (MonoType *type)
4213 switch (type->type) {
4214 case MONO_TYPE_BOOLEAN:
4215 case MONO_TYPE_CHAR:
4228 case MONO_TYPE_VALUETYPE:
4236 free_param_data (MonoMethodSignature *sig, void **params) {
4238 for (i = 0; i < sig->param_count; ++i) {
4239 if (!type_is_reference (sig->params [i]))
4240 g_free (params [i]);
4245 * Find the method index in the metadata methodDef table.
4246 * Later put these three helper methods in metadata and export them.
4249 find_method_index (MonoMethod *method) {
4250 MonoClass *klass = method->klass;
4253 for (i = 0; i < klass->method.count; ++i) {
4254 if (method == klass->methods [i])
4255 return klass->method.first + 1 + i;
4261 * Find the field index in the metadata FieldDef table.
4264 find_field_index (MonoClass *klass, MonoClassField *field) {
4267 for (i = 0; i < klass->field.count; ++i) {
4268 if (field == &klass->fields [i])
4269 return klass->field.first + 1 + i;
4275 * Find the property index in the metadata Property table.
4278 find_property_index (MonoClass *klass, MonoProperty *property) {
4281 for (i = 0; i < klass->property.count; ++i) {
4282 if (property == &klass->properties [i])
4283 return klass->property.first + 1 + i;
4289 * Find the event index in the metadata Event table.
4292 find_event_index (MonoClass *klass, MonoEvent *event) {
4295 for (i = 0; i < klass->event.count; ++i) {
4296 if (event == &klass->events [i])
4297 return klass->event.first + 1 + i;
4303 create_custom_attr (MonoImage *image, MonoMethod *method,
4304 const char *data, guint32 len)
4306 const char *p = data;
4308 guint32 i, j, num_named;
4312 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
4315 mono_class_init (method->klass);
4316 /*g_print ("got attr %s\n", method->klass->name);*/
4318 params = g_new (void*, method->signature->param_count);
4322 for (i = 0; i < method->signature->param_count; ++i) {
4323 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
4327 attr = mono_object_new (mono_domain_get (), method->klass);
4328 mono_runtime_invoke (method, attr, params, NULL);
4329 free_param_data (method->signature, params);
4331 num_named = read16 (named);
4333 for (j = 0; j < num_named; j++) {
4335 char *name, named_type, data_type;
4336 named_type = *named++;
4337 data_type = *named++; /* type of data */
4338 if (data_type == 0x55) {
4341 if ((unsigned char) *named == 0x80) /* no idea what this is, but it looks optional */
4343 type_len = mono_metadata_decode_blob_size (named, &named);
4344 type_name = g_malloc (type_len + 1);
4345 memcpy (type_name, named, type_len);
4346 type_name [type_len] = 0;
4348 /* FIXME: lookup the type and check type consistency */
4350 name_len = mono_metadata_decode_blob_size (named, &named);
4351 name = g_malloc (name_len + 1);
4352 memcpy (name, named, name_len);
4353 name [name_len] = 0;
4355 if (named_type == 0x53) {
4356 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
4357 void *val = load_cattr_value (image, field->type, named, &named);
4358 mono_field_set_value (attr, field, val);
4359 if (!type_is_reference (field->type))
4361 } else if (named_type == 0x54) {
4364 MonoType *prop_type;
4366 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
4367 /* can we have more that 1 arg in a custom attr named property? */
4368 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
4369 pparams [0] = load_cattr_value (image, prop_type, named, &named);
4370 mono_property_set_value (prop, attr, pparams, NULL);
4371 if (!type_is_reference (prop_type))
4372 g_free (pparams [0]);
4381 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
4388 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
4389 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
4390 for (i = 0; i < cinfo->num_attrs; ++i) {
4391 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
4392 mono_array_set (result, gpointer, i, attr);
4398 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
4400 guint32 mtoken, i, len;
4401 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
4403 MonoCustomAttrInfo *ainfo;
4404 GList *tmp, *list = NULL;
4407 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4408 /* the table is not sorted */
4409 for (i = 0; i < ca->rows; ++i) {
4410 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
4412 list = g_list_prepend (list, GUINT_TO_POINTER (i));
4414 len = g_list_length (list);
4417 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
4418 ainfo->num_attrs = len;
4419 ainfo->image = image;
4420 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
4421 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
4422 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
4423 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
4424 case CUSTOM_ATTR_TYPE_METHODDEF:
4425 mtoken |= MONO_TOKEN_METHOD_DEF;
4427 case CUSTOM_ATTR_TYPE_MEMBERREF:
4428 mtoken |= MONO_TOKEN_MEMBER_REF;
4431 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
4434 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
4435 if (!ainfo->attrs [i].ctor)
4436 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
4437 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
4438 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
4439 ainfo->attrs [i].data = data;
4447 mono_custom_attrs_from_method (MonoMethod *method)
4449 MonoCustomAttrInfo *cinfo;
4452 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
4454 idx = find_method_index (method);
4455 idx <<= CUSTOM_ATTR_BITS;
4456 idx |= CUSTOM_ATTR_METHODDEF;
4457 return mono_custom_attrs_from_index (method->klass->image, idx);
4461 mono_custom_attrs_from_class (MonoClass *klass)
4463 MonoCustomAttrInfo *cinfo;
4466 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
4468 idx = mono_metadata_token_index (klass->type_token);
4469 idx <<= CUSTOM_ATTR_BITS;
4470 idx |= CUSTOM_ATTR_TYPEDEF;
4471 return mono_custom_attrs_from_index (klass->image, idx);
4475 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
4477 MonoCustomAttrInfo *cinfo;
4480 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
4482 idx = 1; /* there is only one assembly */
4483 idx <<= CUSTOM_ATTR_BITS;
4484 idx |= CUSTOM_ATTR_ASSEMBLY;
4485 return mono_custom_attrs_from_index (assembly->image, idx);
4489 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
4491 MonoCustomAttrInfo *cinfo;
4494 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
4496 idx = find_property_index (klass, property);
4497 idx <<= CUSTOM_ATTR_BITS;
4498 idx |= CUSTOM_ATTR_PROPERTY;
4499 return mono_custom_attrs_from_index (klass->image, idx);
4503 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
4505 MonoCustomAttrInfo *cinfo;
4508 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
4510 idx = find_event_index (klass, event);
4511 idx <<= CUSTOM_ATTR_BITS;
4512 idx |= CUSTOM_ATTR_EVENT;
4513 return mono_custom_attrs_from_index (klass->image, idx);
4517 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
4519 MonoCustomAttrInfo *cinfo;
4522 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
4524 idx = find_field_index (klass, field);
4525 idx <<= CUSTOM_ATTR_BITS;
4526 idx |= CUSTOM_ATTR_FIELDDEF;
4527 return mono_custom_attrs_from_index (klass->image, idx);
4531 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
4534 guint32 i, idx, method_index;
4535 guint32 param_list, param_last, param_pos, found;
4538 /* FIXME: handle dynamic custom attrs for parameters */
4539 /*if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
4541 image = method->klass->image;
4542 method_index = find_method_index (method);
4543 ca = &image->tables [MONO_TABLE_METHOD];
4545 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
4546 if (method_index == ca->rows) {
4547 ca = &image->tables [MONO_TABLE_PARAM];
4548 param_last = ca->rows + 1;
4550 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
4551 ca = &image->tables [MONO_TABLE_PARAM];
4554 for (i = param_list; i < param_last; ++i) {
4555 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
4556 if (param_pos == param) {
4564 idx <<= CUSTOM_ATTR_BITS;
4565 idx |= CUSTOM_ATTR_PARAMDEF;
4566 return mono_custom_attrs_from_index (image, idx);
4570 * mono_reflection_get_custom_attrs:
4571 * @obj: a reflection object handle
4573 * Return an array with all the custom attributes defined of the
4574 * reflection handle @obj. The objects are fully build.
4577 mono_reflection_get_custom_attrs (MonoObject *obj)
4581 MonoCustomAttrInfo *cinfo;
4583 MONO_ARCH_SAVE_REGS;
4585 klass = obj->vtable->klass;
4586 /* FIXME: need to handle: Module */
4587 if (klass == mono_defaults.monotype_class) {
4588 MonoReflectionType *rtype = (MonoReflectionType*)obj;
4589 klass = mono_class_from_mono_type (rtype->type);
4590 cinfo = mono_custom_attrs_from_class (klass);
4591 } else if (strcmp ("Assembly", klass->name) == 0) {
4592 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
4593 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
4594 } else if (strcmp ("MonoProperty", klass->name) == 0) {
4595 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
4596 cinfo = mono_custom_attrs_from_property (rprop->klass, rprop->property);
4597 } else if (strcmp ("MonoEvent", klass->name) == 0) {
4598 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
4599 cinfo = mono_custom_attrs_from_event (revent->klass, revent->event);
4600 } else if (strcmp ("MonoField", klass->name) == 0) {
4601 MonoReflectionField *rfield = (MonoReflectionField*)obj;
4602 cinfo = mono_custom_attrs_from_field (rfield->klass, rfield->field);
4603 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
4604 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
4605 cinfo = mono_custom_attrs_from_method (rmethod->method);
4606 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
4607 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
4608 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
4609 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl);
4610 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
4611 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
4612 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
4613 } else { /* handle other types here... */
4614 g_error ("get custom attrs not yet supported for %s", klass->name);
4618 result = mono_custom_attrs_construct (cinfo);
4620 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
4621 result = mono_array_new (mono_domain_get (), klass, 0);
4627 static MonoMethodSignature*
4628 parameters_to_signature (MonoArray *parameters) {
4629 MonoMethodSignature *sig;
4632 count = parameters? mono_array_length (parameters): 0;
4634 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
4635 sig->param_count = count;
4636 sig->sentinelpos = -1; /* FIXME */
4637 for (i = 0; i < count; ++i) {
4638 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
4639 sig->params [i] = pt->type;
4644 static MonoMethodSignature*
4645 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
4646 MonoMethodSignature *sig;
4648 sig = parameters_to_signature (ctor->parameters);
4649 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4650 sig->ret = &mono_defaults.void_class->byval_arg;
4654 static MonoMethodSignature*
4655 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
4656 MonoMethodSignature *sig;
4658 sig = parameters_to_signature (method->parameters);
4659 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4660 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
4665 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
4667 MonoClass *klass = mono_object_class (prop);
4668 if (strcmp (klass->name, "PropertyBuilder") == 0) {
4669 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
4670 *name = mono_string_to_utf8 (pb->name);
4671 *type = pb->type->type;
4673 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
4674 *name = g_strdup (p->property->name);
4675 if (p->property->get)
4676 *type = p->property->get->signature->ret;
4678 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
4683 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
4685 MonoClass *klass = mono_object_class (field);
4686 if (strcmp (klass->name, "FieldBuilder") == 0) {
4687 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
4688 *name = mono_string_to_utf8 (fb->name);
4689 *type = fb->type->type;
4691 MonoReflectionField *f = (MonoReflectionField *)field;
4692 *name = g_strdup (f->field->name);
4693 *type = f->field->type;
4698 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
4699 char *name, *result;
4703 name = mono_type_get_name (type);
4704 klass = my_mono_class_from_mono_type (type);
4705 ta = klass->image->assembly;
4706 if (ta == ass || klass->image == mono_defaults.corlib)
4709 /* missing public key */
4710 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
4711 name, ta->aname.name,
4712 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
4713 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
4719 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
4722 MonoTypeEnum simple_type;
4724 if ((p-buffer) + 10 >= *buflen) {
4727 newbuf = g_realloc (buffer, *buflen);
4728 p = newbuf + (p-buffer);
4731 argval = ((char*)arg + sizeof (MonoObject));
4732 simple_type = type->type;
4734 switch (simple_type) {
4735 case MONO_TYPE_BOOLEAN:
4740 case MONO_TYPE_CHAR:
4743 swap_with_size (p, argval, 2, 1);
4749 swap_with_size (p, argval, 4, 1);
4755 swap_with_size (p, argval, 8, 1);
4758 case MONO_TYPE_VALUETYPE:
4759 if (type->data.klass->enumtype) {
4760 simple_type = type->data.klass->enum_basetype->type;
4763 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
4766 case MONO_TYPE_STRING: {
4773 str = mono_string_to_utf8 ((MonoString*)arg);
4774 slen = strlen (str);
4775 if ((p-buffer) + 10 + slen >= *buflen) {
4779 newbuf = g_realloc (buffer, *buflen);
4780 p = newbuf + (p-buffer);
4783 mono_metadata_encode_value (slen, p, &p);
4784 memcpy (p, str, slen);
4789 case MONO_TYPE_CLASS: {
4797 k = mono_object_class (arg);
4798 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
4799 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
4800 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
4802 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
4803 slen = strlen (str);
4804 if ((p-buffer) + 10 + slen >= *buflen) {
4808 newbuf = g_realloc (buffer, *buflen);
4809 p = newbuf + (p-buffer);
4812 mono_metadata_encode_value (slen, p, &p);
4813 memcpy (p, str, slen);
4818 case MONO_TYPE_SZARRAY: {
4823 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
4826 len = mono_array_length ((MonoArray*)arg);
4828 *p++ = (len >> 8) & 0xff;
4829 *p++ = (len >> 16) & 0xff;
4830 *p++ = (len >> 24) & 0xff;
4832 *retbuffer = buffer;
4833 eclass = mono_class_from_mono_type (type)->element_class;
4834 for (i = 0; i < len; ++i) {
4835 encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
4839 /* it may be a boxed value or a Type */
4840 case MONO_TYPE_OBJECT: {
4841 MonoClass *klass = mono_object_class (arg);
4845 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
4848 } else if (klass->enumtype) {
4850 } else if (klass == mono_defaults.string_class) {
4851 simple_type = MONO_TYPE_STRING;
4854 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
4855 *p++ = simple_type = klass->byval_arg.type;
4858 g_error ("unhandled type in custom attr");
4860 str = type_get_qualified_name (klass->enum_basetype, NULL);
4861 slen = strlen (str);
4862 if ((p-buffer) + 10 + slen >= *buflen) {
4866 newbuf = g_realloc (buffer, *buflen);
4867 p = newbuf + (p-buffer);
4870 mono_metadata_encode_value (slen, p, &p);
4871 memcpy (p, str, slen);
4874 simple_type = klass->enum_basetype->type;
4878 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
4881 *retbuffer = buffer;
4885 * mono_reflection_get_custom_attrs_blob:
4886 * @ctor: custom attribute constructor
4887 * @ctorArgs: arguments o the constructor
4893 * Creates the blob of data that needs to be saved in the metadata and that represents
4894 * the custom attributed described by @ctor, @ctorArgs etc.
4895 * Returns: a Byte array representing the blob of data.
4898 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
4901 MonoMethodSignature *sig;
4906 MONO_ARCH_SAVE_REGS;
4908 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4909 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
4911 sig = ((MonoReflectionMethod*)ctor)->method->signature;
4913 g_assert (mono_array_length (ctorArgs) == sig->param_count);
4915 p = buffer = g_malloc (buflen);
4916 /* write the prolog */
4919 for (i = 0; i < sig->param_count; ++i) {
4920 arg = mono_array_get (ctorArgs, MonoObject*, i);
4921 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
4925 i += mono_array_length (properties);
4927 i += mono_array_length (fields);
4929 *p++ = (i >> 8) & 0xff;
4932 for (i = 0; i < mono_array_length (properties); ++i) {
4937 prop = mono_array_get (properties, gpointer, i);
4938 get_prop_name_and_type (prop, &pname, &ptype);
4939 *p++ = 0x54; /* PROPERTY signature */
4940 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
4941 char *str = type_get_qualified_name (ptype, NULL);
4942 int slen = strlen (str);
4943 if ((p-buffer) + 10 + slen >= buflen) {
4947 newbuf = g_realloc (buffer, buflen);
4948 p = newbuf + (p-buffer);
4953 * This seems to be optional...
4956 mono_metadata_encode_value (slen, p, &p);
4957 memcpy (p, str, slen);
4961 mono_metadata_encode_value (ptype->type, p, &p);
4963 len = strlen (pname);
4964 mono_metadata_encode_value (len, p, &p);
4965 memcpy (p, pname, len);
4967 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
4974 for (i = 0; i < mono_array_length (fields); ++i) {
4979 field = mono_array_get (fields, gpointer, i);
4980 get_field_name_and_type (field, &fname, &ftype);
4981 *p++ = 0x53; /* FIELD signature */
4982 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
4983 char *str = type_get_qualified_name (ftype, NULL);
4984 int slen = strlen (str);
4985 if ((p-buffer) + 10 + slen >= buflen) {
4989 newbuf = g_realloc (buffer, buflen);
4990 p = newbuf + (p-buffer);
4995 * This seems to be optional...
4998 mono_metadata_encode_value (slen, p, &p);
4999 memcpy (p, str, slen);
5003 mono_metadata_encode_value (ftype->type, p, &p);
5005 len = strlen (fname);
5006 mono_metadata_encode_value (len, p, &p);
5007 memcpy (p, fname, len);
5009 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
5014 g_assert (p - buffer <= buflen);
5015 buflen = p - buffer;
5016 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5017 p = mono_array_addr (result, char, 0);
5018 memcpy (p, buffer, buflen);
5020 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
5026 * mono_reflection_setup_internal_class:
5027 * @tb: a TypeBuilder object
5029 * Creates a MonoClass that represents the TypeBuilder.
5030 * This is a trick that lets us simplify a lot of reflection code
5031 * (and will allow us to support Build and Run assemblies easier).
5034 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
5036 MonoClass *klass, *parent;
5038 MONO_ARCH_SAVE_REGS;
5040 klass = g_new0 (MonoClass, 1);
5042 klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
5045 /* check so we can compile corlib correctly */
5046 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
5047 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
5048 parent = tb->parent->type->data.klass;
5050 parent = my_mono_class_from_mono_type (tb->parent->type);
5054 klass->inited = 1; /* we lie to the runtime */
5055 klass->name = mono_string_to_utf8 (tb->name);
5056 klass->name_space = mono_string_to_utf8 (tb->nspace);
5057 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
5058 klass->flags = tb->attrs;
5060 klass->element_class = klass;
5061 klass->reflection_info = tb; /* need to pin. */
5063 /* Put into cache so mono_class_get () will find it */
5064 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
5067 mono_g_hash_table_insert (tb->module->assemblyb->dynamic_assembly->tokens,
5068 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
5072 mono_class_setup_parent (klass, parent);
5073 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
5074 const char *old_n = klass->name;
5075 /* trick to get relative numbering right when compiling corlib */
5076 klass->name = "BuildingObject";
5077 mono_class_setup_parent (klass, mono_defaults.object_class);
5078 klass->name = old_n;
5080 mono_class_setup_mono_type (klass);
5082 mono_class_setup_supertypes (klass);
5085 * FIXME: handle interfaces.
5088 tb->type.type = &klass->byval_arg;
5090 if (tb->nesting_type) {
5091 g_assert (tb->nesting_type->type);
5092 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
5095 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
5099 * mono_reflection_create_internal_class:
5100 * @tb: a TypeBuilder object
5102 * Actually create the MonoClass that is associated with the TypeBuilder.
5105 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
5109 MONO_ARCH_SAVE_REGS;
5111 klass = my_mono_class_from_mono_type (tb->type.type);
5113 if (klass->enumtype && klass->enum_basetype == NULL) {
5114 MonoReflectionFieldBuilder *fb;
5116 g_assert (tb->fields != NULL);
5117 g_assert (mono_array_length (tb->fields) >= 1);
5119 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
5121 klass->enum_basetype = fb->type->type;
5122 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
5123 if (!klass->element_class)
5124 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
5125 klass->instance_size = klass->element_class->instance_size;
5126 klass->size_inited = 1;
5128 * this is almost safe to do with enums and it's needed to be able
5129 * to create objects of the enum type (for use in SetConstant).
5131 /* FIXME: Does this mean enums can't have method overrides ? */
5132 mono_class_setup_vtable (klass, NULL, 0);
5137 reflection_methodbuilder_to_mono_method (MonoClass *klass,
5138 ReflectionMethodBuilder *rmb,
5139 MonoMethodSignature *sig)
5142 MonoMethodNormal *pm;
5144 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5145 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5146 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
5148 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
5150 pm = (MonoMethodNormal*)m;
5153 m->flags = rmb->attrs;
5154 m->iflags = rmb->iattrs;
5155 m->name = mono_string_to_utf8 (rmb->name);
5158 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
5160 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
5161 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
5164 m->addr = mono_lookup_internal_call (m);
5165 m->signature->pinvoke = 1;
5166 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
5168 m->signature->pinvoke = 1;
5170 } else if (!m->klass->dummy &&
5171 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
5172 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
5173 MonoMethodHeader *header;
5175 gint32 max_stack, i;
5176 gint32 num_locals = 0;
5177 gint32 num_clauses = 0;
5181 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
5182 code_size = rmb->ilgen->code_len;
5183 max_stack = rmb->ilgen->max_stack;
5184 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
5185 if (rmb->ilgen->ex_handlers)
5186 num_clauses = method_count_clauses (rmb->ilgen);
5189 code = mono_array_addr (rmb->code, guint8, 0);
5190 code_size = mono_array_length (rmb->code);
5191 /* we probably need to run a verifier on the code... */
5201 header = g_malloc0 (sizeof (MonoMethodHeader) +
5202 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
5203 header->code_size = code_size;
5204 header->code = g_malloc (code_size);
5205 memcpy ((char*)header->code, code, code_size);
5206 header->max_stack = max_stack;
5207 header->init_locals = rmb->init_locals;
5208 header->num_locals = num_locals;
5210 for (i = 0; i < num_locals; ++i) {
5211 MonoReflectionLocalBuilder *lb =
5212 mono_array_get (rmb->ilgen->locals,
5213 MonoReflectionLocalBuilder*, i);
5215 header->locals [i] = g_new0 (MonoType, 1);
5216 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
5219 header->num_clauses = num_clauses;
5221 header->clauses = method_encode_clauses (klass->image->assembly->dynamic,
5226 pm->header = header;
5233 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
5235 ReflectionMethodBuilder rmb;
5237 MonoMethodSignature *sig;
5239 name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
5241 sig = ctor_builder_to_signature (mb);
5243 rmb.ilgen = mb->ilgen;
5244 rmb.parameters = mb->parameters;
5245 rmb.pinfo = mb->pinfo;
5246 rmb.attrs = mb->attrs | METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
5247 rmb.iattrs = mb->iattrs;
5248 rmb.call_conv = mb->call_conv;
5249 rmb.type = mb->type;
5250 rmb.name = mono_string_new (mono_domain_get (), name);
5251 rmb.table_idx = &mb->table_idx;
5252 rmb.init_locals = mb->init_locals;
5255 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
5256 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
5258 if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
5259 /* ilgen is no longer needed */
5267 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
5269 ReflectionMethodBuilder rmb;
5270 MonoMethodSignature *sig;
5272 sig = method_builder_to_signature (mb);
5274 rmb.ilgen = mb->ilgen;
5275 rmb.parameters = mb->parameters;
5276 rmb.pinfo = mb->pinfo;
5277 rmb.attrs = mb->attrs;
5278 rmb.iattrs = mb->iattrs;
5279 rmb.call_conv = mb->call_conv;
5280 rmb.type = mb->type;
5281 rmb.name = mb->name;
5282 rmb.table_idx = &mb->table_idx;
5283 rmb.init_locals = mb->init_locals;
5284 rmb.code = mb->code;
5286 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
5287 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
5289 if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
5290 /* ilgen is no longer needed */
5297 ensure_runtime_vtable (MonoClass *klass)
5299 MonoReflectionTypeBuilder *tb = klass->reflection_info;
5300 int i, num, j, onum;
5301 MonoMethod **overrides;
5303 if (!tb || klass->wastypebuilder)
5306 ensure_runtime_vtable (klass->parent);
5308 num = tb->ctors? mono_array_length (tb->ctors): 0;
5309 num += tb->methods? mono_array_length (tb->methods): 0;
5310 klass->method.count = num;
5311 klass->methods = g_new (MonoMethod*, num);
5312 num = tb->ctors? mono_array_length (tb->ctors): 0;
5313 for (i = 0; i < num; ++i)
5314 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
5315 num = tb->methods? mono_array_length (tb->methods): 0;
5317 for (i = 0; i < num; ++i)
5318 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
5320 klass->wastypebuilder = TRUE;
5321 if (tb->interfaces) {
5322 klass->interface_count = mono_array_length (tb->interfaces);
5323 klass->interfaces = g_new (MonoClass*, klass->interface_count);
5324 for (i = 0; i < klass->interface_count; ++i) {
5325 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
5326 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
5330 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
5331 for (i = 0; i < klass->method.count; ++i)
5332 klass->methods [i]->slot = i;
5337 for (i = 0; i < mono_array_length (tb->methods); ++i) {
5338 MonoReflectionMethodBuilder *mb =
5339 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
5340 if (mb->override_method)
5345 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
5349 for (i = 0; i < mono_array_length (tb->methods); ++i) {
5350 MonoReflectionMethodBuilder *mb =
5351 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
5352 if (mb->override_method) {
5353 /* FIXME: What if 'override_method' is a MethodBuilder ? */
5354 overrides [onum * 2] =
5355 mb->override_method->method;
5356 overrides [onum * 2 + 1] =
5359 g_assert (mb->mhandle);
5366 mono_class_setup_vtable (klass, overrides, onum);
5370 typebuilder_setup_fields (MonoClass *klass)
5372 MonoReflectionTypeBuilder *tb = klass->reflection_info;
5373 MonoReflectionFieldBuilder *fb;
5374 MonoClassField *field;
5377 klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
5378 klass->field.first = 0;
5379 klass->field.last = klass->field.count;
5381 if (!klass->field.count)
5384 klass->fields = g_new0 (MonoClassField, klass->field.count);
5386 for (i = 0; i < klass->field.count; ++i) {
5387 fb = mono_array_get (tb->fields, gpointer, i);
5388 field = &klass->fields [i];
5389 field->name = mono_string_to_utf8 (fb->name);
5391 /* FIXME: handle type modifiers */
5392 field->type = g_memdup (fb->type->type, sizeof (MonoType));
5393 field->type->attrs = fb->attrs;
5395 field->type = fb->type->type;
5397 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
5398 field->data = mono_array_addr (fb->rva_data, char, 0);
5399 if (fb->offset != -1)
5400 field->offset = fb->offset;
5401 field->parent = klass;
5403 mono_save_custom_attrs (klass->image, field, fb->cattrs);
5405 mono_class_layout_fields (klass);
5409 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
5412 MonoReflectionType* res;
5414 MONO_ARCH_SAVE_REGS;
5416 klass = my_mono_class_from_mono_type (tb->type.type);
5418 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
5421 * Fields to set in klass:
5422 * the various flags: delegate/unicode/contextbound etc.
5427 klass->flags = tb->attrs;
5428 klass->element_class = klass;
5430 if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->run)
5431 /* No need to fully construct the type */
5432 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5434 /* enums are done right away */
5435 if (!klass->enumtype)
5436 ensure_runtime_vtable (klass);
5438 /* fields and object layout */
5439 if (klass->parent) {
5440 if (!klass->parent->size_inited)
5441 mono_class_init (klass->parent);
5442 klass->instance_size += klass->parent->instance_size;
5443 klass->class_size += klass->parent->class_size;
5444 klass->min_align = klass->parent->min_align;
5446 klass->instance_size = sizeof (MonoObject);
5447 klass->min_align = 1;
5450 /* FIXME: handle packing_size and instance_size */
5451 typebuilder_setup_fields (klass);
5453 /* FIXME: properties */
5455 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5456 /* with enums res == tb: need to fix that. */
5457 if (!klass->enumtype)
5458 g_assert (res != (MonoReflectionType*)tb);
5463 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
5465 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5466 guint32 na = mono_array_length (sig->arguments);
5471 MONO_ARCH_SAVE_REGS;
5473 p = buf = g_malloc (10 + na * 10);
5475 mono_metadata_encode_value (0x07, p, &p);
5476 mono_metadata_encode_value (na, p, &p);
5477 for (i = 0; i < na; ++i) {
5478 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5479 encode_reflection_type (assembly, type, p, &p);
5483 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5484 p = mono_array_addr (result, char, 0);
5485 memcpy (p, buf, buflen);
5492 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
5494 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5495 guint32 na = mono_array_length (sig->arguments);
5500 MONO_ARCH_SAVE_REGS;
5502 p = buf = g_malloc (10 + na * 10);
5504 mono_metadata_encode_value (0x06, p, &p);
5505 for (i = 0; i < na; ++i) {
5506 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5507 encode_reflection_type (assembly, type, p, &p);
5511 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5512 p = mono_array_addr (result, char, 0);
5513 memcpy (p, buf, buflen);
5520 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
5522 MonoDynamicAssembly *assembly = image->assembly->dynamic;
5526 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5529 if (strcmp (obj->vtable->klass->name, "String") == 0) {
5533 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
5534 MonoReflectionType *tb = (MonoReflectionType*)obj;
5535 result = mono_class_from_mono_type (tb->type);
5538 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
5539 result = ((MonoReflectionMethod*)obj)->method;
5542 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
5543 result = ((MonoReflectionMethod*)obj)->method;
5546 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
5547 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
5548 result = mb->mhandle;
5550 /* Type is not yet created */
5551 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5553 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5556 * Hopefully this has been filled in by calling CreateType() on the
5560 * TODO: This won't work if the application finishes another
5561 * TypeBuilder instance instead of this one.
5563 result = mb->mhandle;
5566 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
5567 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
5569 result = cb->mhandle;
5571 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
5573 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5574 result = cb->mhandle;
5577 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
5578 result = ((MonoReflectionField*)obj)->field;
5581 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
5582 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
5583 result = fb->handle;
5586 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
5588 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5589 result = fb->handle;
5592 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
5593 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
5596 klass = tb->type.type->data.klass;
5597 if (klass->wastypebuilder) {
5598 /* Already created */
5602 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5603 result = tb->type.type->data.klass;
5607 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
5608 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
5609 MonoMethodSignature *sig;
5612 if (helper->arguments)
5613 nargs = mono_array_length (helper->arguments);
5617 sig = mono_metadata_signature_alloc (image, nargs);
5618 sig->explicit_this = helper->call_conv & 64;
5619 sig->hasthis = helper->call_conv & 32;
5621 if (helper->call_conv == 0) /* unmanaged */
5622 sig->call_convention = helper->unmanaged_call_conv - 1;
5624 if (helper->call_conv & 0x02)
5625 sig->call_convention = MONO_CALL_VARARG;
5627 sig->call_convention = MONO_CALL_DEFAULT;
5629 sig->param_count = nargs;
5630 /* TODO: Copy type ? */
5631 sig->ret = helper->return_type->type;
5632 for (i = 0; i < nargs; ++i) {
5633 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
5634 sig->params [i] = rt->type;
5640 g_print (obj->vtable->klass->name);
5641 g_assert_not_reached ();