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,
101 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
102 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
103 static guint32 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper);
104 static guint32 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo);
107 alloc_table (MonoDynamicTable *table, guint nrows)
110 g_assert (table->columns);
111 table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
115 string_heap_insert (MonoDynamicStream *sh, const char *str)
119 gpointer oldkey, oldval;
121 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
122 return GPOINTER_TO_UINT (oldval);
124 len = strlen (str) + 1;
126 if (idx + len > sh->alloc_size) {
127 sh->alloc_size += len + 4096;
128 sh->data = g_realloc (sh->data, sh->alloc_size);
131 * We strdup the string even if we already copy them in sh->data
132 * so that the string pointers in the hash remain valid even if
133 * we need to realloc sh->data. We may want to avoid that later.
135 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
136 memcpy (sh->data + idx, str, len);
142 string_heap_init (MonoDynamicStream *sh)
145 sh->alloc_size = 4096;
146 sh->data = g_malloc (4096);
147 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
148 string_heap_insert (sh, "");
151 #if 0 /* never used */
153 string_heap_free (MonoDynamicStream *sh)
156 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
157 g_hash_table_destroy (sh->hash);
162 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
165 if (stream->alloc_size < stream->index + len) {
166 stream->alloc_size += len + 4096;
167 stream->data = g_realloc (stream->data, stream->alloc_size);
169 memcpy (stream->data + stream->index, data, len);
171 stream->index += len;
173 * align index? Not without adding an additional param that controls it since
174 * we may store a blob value in pieces.
180 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
183 if (stream->alloc_size < stream->index + len) {
184 stream->alloc_size += len + 4096;
185 stream->data = g_realloc (stream->data, stream->alloc_size);
187 memset (stream->data + stream->index, 0, len);
189 stream->index += len;
194 stream_data_align (MonoDynamicStream *stream)
197 guint32 count = stream->index % 4;
199 /* we assume the stream data will be aligned */
201 mono_image_add_stream_data (stream, buf, 4 - count);
205 mono_blob_entry_hash (const char* str)
209 len = mono_metadata_decode_blob_size (str, &str);
212 for (str += 1; str < end; str++)
213 h = (h << 5) - h + *str;
218 mono_blob_entry_equal (const char *str1, const char *str2) {
222 len = mono_metadata_decode_blob_size (str1, &end1);
223 len2 = mono_metadata_decode_blob_size (str2, &end2);
226 return memcmp (end1, end2, len) == 0;
230 add_to_blob_cached (MonoDynamicAssembly *assembly, char *b1, int s1, char *b2, int s2)
234 gpointer oldkey, oldval;
236 copy = g_malloc (s1+s2);
237 memcpy (copy, b1, s1);
238 memcpy (copy + s1, b2, s2);
239 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
241 idx = GPOINTER_TO_UINT (oldval);
243 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
244 mono_image_add_stream_data (&assembly->blob, b2, s2);
245 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
250 /* modified version needed to handle building corlib */
252 my_mono_class_from_mono_type (MonoType *type) {
253 switch (type->type) {
254 case MONO_TYPE_ARRAY:
256 case MONO_TYPE_SZARRAY:
257 return mono_class_from_mono_type (type);
259 /* should be always valid when we reach this case... */
260 return type->data.klass;
265 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
268 g_assert_not_reached ();
273 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
277 case MONO_TYPE_BOOLEAN:
291 case MONO_TYPE_STRING:
292 case MONO_TYPE_OBJECT:
293 case MONO_TYPE_TYPEDBYREF:
294 mono_metadata_encode_value (type->type, p, &p);
297 case MONO_TYPE_SZARRAY:
298 mono_metadata_encode_value (type->type, p, &p);
299 encode_type (assembly, type->data.type, p, &p);
301 case MONO_TYPE_VALUETYPE:
302 case MONO_TYPE_CLASS:
303 mono_metadata_encode_value (type->type, p, &p);
304 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
307 case MONO_TYPE_VALUETYPE:
308 case MONO_TYPE_CLASS: {
309 MonoClass *k = mono_class_from_mono_type (type);
310 mono_metadata_encode_value (type->type, p, &p);
311 /* ensure only non-byref gets passed to mono_image_typedef_or_ref() */
312 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
316 case MONO_TYPE_ARRAY:
317 mono_metadata_encode_value (type->type, p, &p);
318 encode_type (assembly, type->data.array->type, p, &p);
319 mono_metadata_encode_value (type->data.array->rank, p, &p);
320 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
321 mono_metadata_encode_value (0, p, &p);
324 g_error ("need to encode type %x", type->type);
330 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
333 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
337 encode_type (assembly, type->type, p, endbuf);
341 g_assert_not_reached ();
346 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
351 guint32 nparams = sig->param_count;
352 guint32 size = 10 + nparams * 10;
357 p = buf = g_malloc (size);
359 * FIXME: vararg, explicit_this, differenc call_conv values...
361 *p = sig->call_convention;
363 *p |= 0x20; /* hasthis */
365 mono_metadata_encode_value (nparams, p, &p);
366 encode_type (assembly, sig->ret, p, &p);
367 for (i = 0; i < nparams; ++i)
368 encode_type (assembly, sig->params [i], p, &p);
370 g_assert (p - buf < size);
371 mono_metadata_encode_value (p-buf, b, &b);
372 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
378 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
381 * FIXME: reuse code from method_encode_signature().
386 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
387 guint32 size = 10 + nparams * 10;
392 p = buf = g_malloc (size);
393 /* LAMESPEC: all the call conv spec is foobared */
394 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
395 if (mb->call_conv & 2)
396 *p |= 0x5; /* vararg */
397 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
398 *p |= 0x20; /* hasthis */
400 mono_metadata_encode_value (nparams, p, &p);
401 encode_reflection_type (assembly, mb->rtype, p, &p);
402 for (i = 0; i < nparams; ++i) {
403 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
404 encode_reflection_type (assembly, pt, p, &p);
407 g_assert (p - buf < size);
408 mono_metadata_encode_value (p-buf, b, &b);
409 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
415 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
417 MonoDynamicTable *table;
420 guint32 idx, sig_idx, size;
421 guint nl = mono_array_length (ilgen->locals);
428 p = buf = g_malloc (size);
429 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
430 idx = table->next_idx ++;
432 alloc_table (table, table->rows);
433 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
435 mono_metadata_encode_value (0x07, p, &p);
436 mono_metadata_encode_value (nl, p, &p);
437 for (i = 0; i < nl; ++i) {
438 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
439 encode_reflection_type (assembly, lb->type, p, &p);
441 g_assert (p - buf < size);
442 mono_metadata_encode_value (p-buf, b, &b);
443 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
446 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
452 method_count_clauses (MonoReflectionILGen *ilgen)
454 guint32 num_clauses = 0;
457 MonoILExceptionInfo *ex_info;
458 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
459 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
460 if (ex_info->handlers)
461 num_clauses += mono_array_length (ex_info->handlers);
469 static MonoExceptionClause*
470 method_encode_clauses (MonoDynamicAssembly *assembly,
471 MonoReflectionILGen *ilgen, guint32 num_clauses)
473 MonoExceptionClause *clauses;
474 MonoExceptionClause *clause;
475 MonoILExceptionInfo *ex_info;
476 MonoILExceptionBlock *ex_block;
477 guint32 finally_start;
478 int i, j, clause_index;;
480 clauses = g_new0 (MonoExceptionClause, num_clauses);
483 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
484 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
485 finally_start = ex_info->start + ex_info->len;
486 g_assert (ex_info->handlers);
487 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
488 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
489 clause = &(clauses [clause_index]);
491 clause->flags = ex_block->type;
492 clause->try_offset = ex_info->start;
494 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
495 clause->try_len = finally_start - ex_info->start;
497 clause->try_len = ex_info->len;
498 clause->handler_offset = ex_block->start;
499 clause->handler_len = ex_block->len;
500 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
501 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
502 if (ex_block->extype) {
503 mono_g_hash_table_insert (assembly->tokens,
504 GUINT_TO_POINTER (clause->token_or_filter),
507 finally_start = ex_block->start + ex_block->len;
517 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
523 gint32 num_locals = 0;
524 gint32 num_exception = 0;
527 char fat_header [12];
530 guint32 local_sig = 0;
531 guint32 header_size = 12;
534 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
535 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
536 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
537 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
541 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
543 code = mb->ilgen->code;
544 code_size = mb->ilgen->code_len;
545 max_stack = mb->ilgen->max_stack;
546 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
547 if (mb->ilgen->ex_handlers)
548 num_exception = method_count_clauses (mb->ilgen);
551 code_size = mono_array_length (code);
552 max_stack = 8; /* we probably need to run a verifier on the code... */
555 /* check for exceptions, maxstack, locals */
556 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
558 if (code_size < 64 && !(code_size & 1)) {
559 flags = (code_size << 2) | 0x2;
560 } else if (code_size < 32 && (code_size & 1)) {
561 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
565 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
566 /* add to the fixup todo list */
567 if (mb->ilgen && mb->ilgen->num_token_fixups)
568 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
569 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
570 return assembly->text_rva + idx;
574 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
576 * FIXME: need to set also the header size in fat_flags.
577 * (and more sects and init locals flags)
581 fat_flags |= METHOD_HEADER_MORE_SECTS;
583 fat_flags |= METHOD_HEADER_INIT_LOCALS;
584 fat_header [0] = fat_flags;
585 fat_header [1] = (header_size / 4 ) << 4;
586 shortp = (guint16*)(fat_header + 2);
587 *shortp = GUINT16_TO_LE (max_stack);
588 intp = (guint32*)(fat_header + 4);
589 *intp = GUINT32_TO_LE (code_size);
590 intp = (guint32*)(fat_header + 8);
591 *intp = GUINT32_TO_LE (local_sig);
592 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
593 /* add to the fixup todo list */
594 if (mb->ilgen && mb->ilgen->num_token_fixups)
595 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
597 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
599 unsigned char sheader [4];
600 MonoExceptionClause clause;
601 MonoILExceptionInfo * ex_info;
602 MonoILExceptionBlock * ex_block;
605 stream_data_align (&assembly->code);
606 /* always use fat format for now */
607 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
608 num_exception *= sizeof (MonoExceptionClause);
609 num_exception += 4; /* include the size of the header */
610 sheader [1] = num_exception & 0xff;
611 sheader [2] = (num_exception >> 8) & 0xff;
612 sheader [3] = (num_exception >> 16) & 0xff;
613 mono_image_add_stream_data (&assembly->code, sheader, 4);
614 /* fat header, so we are already aligned */
616 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
617 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
618 if (ex_info->handlers) {
619 int finally_start = ex_info->start + ex_info->len;
620 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
621 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
622 clause.flags = GUINT32_TO_LE (ex_block->type);
623 clause.try_offset = GUINT32_TO_LE (ex_info->start);
624 /* need fault, too, probably */
625 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
626 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
628 clause.try_len = GUINT32_TO_LE (ex_info->len);
629 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
630 clause.handler_len = GUINT32_TO_LE (ex_block->len);
631 finally_start = ex_block->start + ex_block->len;
632 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
633 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
634 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
635 /*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",
636 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);*/
637 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
640 g_error ("No clauses for ex info block %d", i);
644 return assembly->text_rva + idx;
648 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 token)
651 MonoDynamicTable *table;
654 table = &assembly->tables [table_idx];
656 g_assert (col < table->columns);
658 values = table->values + table->columns;
659 for (i = 1; i <= table->rows; ++i) {
660 if (values [col] == token)
662 values += table->columns;
676 CustomAttrEntry attrs [MONO_ZERO_LEN_ARRAY];
679 static GHashTable *dynamic_custom_attrs = NULL;
682 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
685 CustomAttrInfo *ainfo;
686 MonoReflectionCustomAttr *cattr;
690 /* FIXME: check in assembly the Run flag is set */
692 count = mono_array_length (cattrs);
694 ainfo = g_malloc0 (sizeof (CustomAttrInfo) + sizeof (CustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
696 ainfo->image = image;
697 ainfo->num_attrs = count;
698 for (i = 0; i < count; ++i) {
699 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
700 ainfo->attrs [i].ctor = cattr->ctor->method;
701 /* FIXME: might want to memdup the data here */
702 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
703 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
706 if (!dynamic_custom_attrs)
707 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
709 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
713 * idx is the table index of the object
714 * type is one of CUSTOM_ATTR_*
717 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
719 MonoDynamicTable *table;
720 MonoReflectionCustomAttr *cattr;
722 guint32 count, i, token;
726 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
729 count = mono_array_length (cattrs);
730 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
731 table->rows += count;
732 alloc_table (table, table->rows);
733 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
734 idx <<= CUSTOM_ATTR_BITS;
736 for (i = 0; i < count; ++i) {
737 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
738 values [MONO_CUSTOM_ATTR_PARENT] = idx;
739 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
740 type = mono_metadata_token_index (token);
741 type <<= CUSTOM_ATTR_TYPE_BITS;
742 switch (mono_metadata_token_table (token)) {
743 case MONO_TABLE_METHOD:
744 type |= CUSTOM_ATTR_TYPE_METHODDEF;
746 case MONO_TABLE_MEMBERREF:
747 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
750 g_warning ("got wrong token in custom attr");
753 values [MONO_CUSTOM_ATTR_TYPE] = type;
755 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
756 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
757 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
758 values += MONO_CUSTOM_ATTR_SIZE;
764 * Fill in the MethodDef and ParamDef tables for a method.
765 * This is used for both normal methods and constructors.
768 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
770 MonoDynamicTable *table;
775 /* room in this table is already allocated */
776 table = &assembly->tables [MONO_TABLE_METHOD];
777 *mb->table_idx = table->next_idx ++;
778 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
779 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
781 name = mono_string_to_utf8 (mb->name);
782 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
784 } else { /* a constructor */
785 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
786 // MS.NET adds this automatically
787 mb->attrs |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
789 values [MONO_METHOD_FLAGS] = mb->attrs;
790 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
791 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
792 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
794 table = &assembly->tables [MONO_TABLE_PARAM];
795 values [MONO_METHOD_PARAMLIST] = table->next_idx;
798 MonoDynamicTable *mtable;
801 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
802 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
805 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
806 if (mono_array_get (mb->pinfo, gpointer, i))
809 table->rows += count;
810 alloc_table (table, table->rows);
811 values = table->values + table->next_idx * MONO_PARAM_SIZE;
812 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
813 MonoReflectionParamBuilder *pb;
814 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
815 values [MONO_PARAM_FLAGS] = pb->attrs;
816 values [MONO_PARAM_SEQUENCE] = i;
817 if (pb->name != NULL) {
818 name = mono_string_to_utf8 (pb->name);
819 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
823 values [MONO_PARAM_NAME] = 0;
824 values += MONO_PARAM_SIZE;
825 if (pb->marshal_info) {
827 alloc_table (mtable, mtable->rows);
828 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
829 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
830 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
832 pb->table_idx = table->next_idx++;
839 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
841 MonoDynamicTable *table;
844 ReflectionMethodBuilder rmb;
846 rmb.ilgen = mb->ilgen;
847 rmb.rtype = mb->rtype;
848 rmb.parameters = mb->parameters;
849 rmb.pinfo = mb->pinfo;
850 rmb.attrs = mb->attrs;
851 rmb.iattrs = mb->iattrs;
852 rmb.call_conv = mb->call_conv;
856 rmb.table_idx = &mb->table_idx;
857 rmb.init_locals = mb->init_locals;
858 rmb.mhandle = mb->mhandle;
860 mono_image_basic_method (&rmb, assembly);
862 if (mb->dll) { /* It's a P/Invoke method */
864 table = &assembly->tables [MONO_TABLE_IMPLMAP];
866 alloc_table (table, table->rows);
867 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
868 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
869 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
870 name = mono_string_to_utf8 (mb->dllentry);
871 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
873 name = mono_string_to_utf8 (mb->dll);
874 moduleref = string_heap_insert (&assembly->sheap, name);
876 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
877 table = &assembly->tables [MONO_TABLE_MODULEREF];
879 alloc_table (table, table->rows);
880 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
881 values [MONO_IMPLMAP_SCOPE] = table->rows;
885 if (mb->override_method) {
886 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
888 table = &assembly->tables [MONO_TABLE_METHODIMPL];
890 alloc_table (table, table->rows);
891 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
892 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
893 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
894 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
895 switch (mono_metadata_token_table (tok)) {
896 case MONO_TABLE_MEMBERREF:
897 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
899 case MONO_TABLE_METHOD:
900 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
903 g_assert_not_reached ();
905 values [MONO_METHODIMPL_DECLARATION] = tok;
910 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
912 ReflectionMethodBuilder rmb;
914 rmb.ilgen = mb->ilgen;
915 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
916 rmb.parameters = mb->parameters;
917 rmb.pinfo = mb->pinfo;
918 rmb.attrs = mb->attrs;
919 rmb.iattrs = mb->iattrs;
920 rmb.call_conv = mb->call_conv;
924 rmb.table_idx = &mb->table_idx;
925 rmb.init_locals = mb->init_locals;
926 rmb.mhandle = mb->mhandle;
928 mono_image_basic_method (&rmb, assembly);
933 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
941 p = buf = g_malloc (64);
943 mono_metadata_encode_value (0x06, p, &p);
944 /* encode custom attributes before the type */
945 encode_type (assembly, field->type, p, &p);
946 g_assert (p-buf < 64);
947 mono_metadata_encode_value (p-buf, b, &b);
948 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
954 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
962 p = buf = g_malloc (64);
964 mono_metadata_encode_value (0x06, p, &p);
965 /* encode custom attributes before the type */
966 encode_reflection_type (assembly, fb->type, p, &p);
967 g_assert (p-buf < 64);
968 mono_metadata_encode_value (p-buf, b, &b);
969 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
975 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
976 * dest may be misaligned.
979 swap_with_size (char *dest, const char* val, int len, int nelem) {
980 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
983 for (elem = 0; elem < nelem; ++elem) {
1009 g_assert_not_reached ();
1015 memcpy (dest, val, len * nelem);
1020 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
1021 char blob_size [64];
1022 char *b = blob_size;
1025 guint32 idx, len, dummy = 0;
1027 p = buf = g_malloc (64);
1029 *ret_type = MONO_TYPE_CLASS;
1031 box_val = (char*)&dummy;
1033 box_val = ((char*)val) + sizeof (MonoObject);
1034 *ret_type = val->vtable->klass->byval_arg.type;
1037 switch (*ret_type) {
1038 case MONO_TYPE_BOOLEAN:
1043 case MONO_TYPE_CHAR:
1058 case MONO_TYPE_VALUETYPE:
1059 if (val->vtable->klass->enumtype) {
1060 *ret_type = val->vtable->klass->enum_basetype->type;
1063 g_error ("we can't encode valuetypes");
1064 case MONO_TYPE_CLASS:
1066 case MONO_TYPE_STRING: {
1067 MonoString *str = (MonoString*)val;
1068 /* there is no signature */
1069 len = str->length * 2;
1070 mono_metadata_encode_value (len, b, &b);
1071 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1073 char *swapped = g_malloc (2 * mono_string_length (str));
1074 const char *p = (const char*)mono_string_chars (str);
1076 swap_with_size (swapped, p, 2, mono_string_length (str));
1077 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1081 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1088 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1091 /* there is no signature */
1092 mono_metadata_encode_value (len, b, &b);
1093 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1094 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1095 swap_with_size (blob_size, box_val, len, 1);
1096 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1098 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1106 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo) {
1107 char blob_size [64];
1108 char *b = blob_size;
1112 p = buf = g_malloc (256);
1114 switch (minfo->type) {
1115 case MONO_NATIVE_BYVALTSTR:
1116 case MONO_NATIVE_BYVALARRAY:
1117 mono_metadata_encode_value (minfo->type, p, &p);
1118 mono_metadata_encode_value (minfo->count, p, &p);
1120 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
1122 mono_metadata_encode_value (minfo->type, p, &p);
1126 mono_metadata_encode_value (len, b, &b);
1127 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1133 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
1135 MonoDynamicTable *table;
1139 /* maybe this fixup should be done in the C# code */
1140 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1141 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1142 table = &assembly->tables [MONO_TABLE_FIELD];
1143 fb->table_idx = table->next_idx ++;
1144 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1145 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1146 name = mono_string_to_utf8 (fb->name);
1147 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1149 values [MONO_FIELD_FLAGS] = fb->attrs;
1150 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1152 if (fb->offset != -1) {
1153 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1155 alloc_table (table, table->rows);
1156 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1157 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1158 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1160 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1161 guint32 field_type = 0;
1162 table = &assembly->tables [MONO_TABLE_CONSTANT];
1164 alloc_table (table, table->rows);
1165 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1166 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1167 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1168 values [MONO_CONSTANT_TYPE] = field_type;
1169 values [MONO_CONSTANT_PADDING] = 0;
1173 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1175 alloc_table (table, table->rows);
1176 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1177 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1179 * We store it in the code section because it's simpler for now.
1181 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1182 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1184 if (fb->marshal_info) {
1185 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1187 alloc_table (table, table->rows);
1188 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1189 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1190 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1195 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
1199 char *b = blob_size;
1200 guint32 nparams = 0;
1201 MonoReflectionMethodBuilder *mb = fb->get_method;
1202 MonoReflectionMethodBuilder *smb = fb->set_method;
1203 guint32 idx, i, size;
1205 if (mb && mb->parameters)
1206 nparams = mono_array_length (mb->parameters);
1207 if (!mb && smb && smb->parameters)
1208 nparams = mono_array_length (smb->parameters) - 1;
1209 size = 24 + nparams * 10;
1210 buf = p = g_malloc (size);
1213 mono_metadata_encode_value (nparams, p, &p);
1215 encode_reflection_type (assembly, mb->rtype, p, &p);
1216 for (i = 0; i < nparams; ++i) {
1217 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1218 encode_reflection_type (assembly, pt, p, &p);
1221 /* the property type is the last param */
1222 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1223 for (i = 0; i < nparams; ++i) {
1224 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1225 encode_reflection_type (assembly, pt, p, &p);
1229 g_assert (p - buf < size);
1230 mono_metadata_encode_value (p-buf, b, &b);
1231 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1237 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
1239 MonoDynamicTable *table;
1242 guint num_methods = 0;
1246 * we need to set things in the following tables:
1247 * PROPERTYMAP (info already filled in _get_type_info ())
1248 * PROPERTY (rows already preallocated in _get_type_info ())
1249 * METHOD (method info already done with the generic method code)
1252 table = &assembly->tables [MONO_TABLE_PROPERTY];
1253 pb->table_idx = table->next_idx ++;
1254 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1255 name = mono_string_to_utf8 (pb->name);
1256 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1258 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1259 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1261 /* FIXME: we still don't handle 'other' methods */
1262 if (pb->get_method) num_methods ++;
1263 if (pb->set_method) num_methods ++;
1265 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1266 table->rows += num_methods;
1267 alloc_table (table, table->rows);
1269 if (pb->get_method) {
1270 semaidx = table->next_idx ++;
1271 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1272 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1273 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1274 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1276 if (pb->set_method) {
1277 semaidx = table->next_idx ++;
1278 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1279 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1280 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1281 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1286 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
1288 MonoDynamicTable *table;
1291 guint num_methods = 0;
1295 * we need to set things in the following tables:
1296 * EVENTMAP (info already filled in _get_type_info ())
1297 * EVENT (rows already preallocated in _get_type_info ())
1298 * METHOD (method info already done with the generic method code)
1301 table = &assembly->tables [MONO_TABLE_EVENT];
1302 eb->table_idx = table->next_idx ++;
1303 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1304 name = mono_string_to_utf8 (eb->name);
1305 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1307 values [MONO_EVENT_FLAGS] = eb->attrs;
1308 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1311 * FIXME: we still don't handle 'other' methods
1313 if (eb->add_method) num_methods ++;
1314 if (eb->remove_method) num_methods ++;
1315 if (eb->raise_method) num_methods ++;
1317 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1318 table->rows += num_methods;
1319 alloc_table (table, table->rows);
1321 if (eb->add_method) {
1322 semaidx = table->next_idx ++;
1323 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1324 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1325 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1326 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1328 if (eb->remove_method) {
1329 semaidx = table->next_idx ++;
1330 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1331 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1332 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1333 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1335 if (eb->raise_method) {
1336 semaidx = table->next_idx ++;
1337 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1338 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1339 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1340 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1345 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
1347 MonoDynamicTable *table;
1350 guint32 cols [MONO_ASSEMBLY_SIZE];
1354 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1357 if (image->assembly->dynamic)
1359 memset (cols, 0, sizeof (cols));
1361 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1363 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1364 token = table->next_idx ++;
1366 alloc_table (table, table->rows);
1367 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1368 if (strcmp ("corlib", image->assembly_name) == 0)
1369 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1371 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1372 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1373 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1374 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1375 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1376 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1377 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1378 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1380 if ((pubkey = mono_image_get_public_key (image, &publen))) {
1381 guchar pubtoken [9];
1383 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
1384 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
1387 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
1388 * This is currently only a problem with references to System.Xml (see bug#27706),
1389 * but there may be other cases that makes this necessary. Note, we need to set
1390 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
1391 * recognized by ms, yuck!
1392 * FIXME: need to add more assembly names, as needed.
1394 if (strcmp (image->assembly_name, "corlib") == 0 ||
1395 strcmp (image->assembly_name, "mscorlib") == 0 ||
1396 strcmp (image->assembly_name, "System") == 0 ||
1397 strcmp (image->assembly_name, "System.Xml") == 0 ||
1398 strcmp (image->assembly_name, "System.Data") == 0 ||
1399 strcmp (image->assembly_name, "System.Drawing") == 0 ||
1400 strcmp (image->assembly_name, "System.Web") == 0) {
1401 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
1402 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1403 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1404 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1406 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1409 token <<= RESOLTION_SCOPE_BITS;
1410 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1411 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1412 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), image);
1417 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1419 MonoDynamicTable *table;
1425 char *b = blob_size;
1427 switch (type->type) {
1428 case MONO_TYPE_FNPTR:
1430 case MONO_TYPE_SZARRAY:
1431 case MONO_TYPE_ARRAY:
1432 encode_type (assembly, type, p, &p);
1438 g_assert (p-sig < 128);
1439 mono_metadata_encode_value (p-sig, b, &b);
1440 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
1442 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1443 alloc_table (table, table->rows + 1);
1444 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1445 values [MONO_TYPESPEC_SIGNATURE] = token;
1447 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1448 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1454 * Despite the name, we handle also TypeSpec (with the above helper).
1457 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1459 MonoDynamicTable *table;
1461 guint32 token, scope, enclosing;
1464 #define COMPILE_CORLIB 0
1466 /* nasty hack, need to find the proper solution */
1467 if (type->type == MONO_TYPE_OBJECT)
1468 return TYPEDEFORREF_TYPEDEF | (2 << TYPEDEFORREF_BITS);
1470 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1473 token = create_typespec (assembly, type);
1476 klass = my_mono_class_from_mono_type (type);
1478 klass = mono_class_from_mono_type (type);
1481 * If it's in the same module:
1483 if (klass->image == assembly->assembly.image) {
1484 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1485 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1486 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
1490 if (klass->nested_in) {
1491 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1492 /* get the typeref idx of the enclosing type */
1493 enclosing >>= TYPEDEFORREF_BITS;
1494 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1496 scope = resolution_scope_from_image (assembly, klass->image);
1498 table = &assembly->tables [MONO_TABLE_TYPEREF];
1499 alloc_table (table, table->rows + 1);
1500 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1501 values [MONO_TYPEREF_SCOPE] = scope;
1502 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1503 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1504 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1505 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1507 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
1512 * Insert a memberef row into the metadata: the token that point to the memberref
1513 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1514 * mono_image_get_fieldref_token()).
1515 * The sig param is an index to an already built signature.
1518 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1520 MonoDynamicTable *table;
1522 guint32 token, pclass;
1525 parent = mono_image_typedef_or_ref (assembly, type);
1526 switch (parent & TYPEDEFORREF_MASK) {
1527 case TYPEDEFORREF_TYPEREF:
1528 pclass = MEMBERREF_PARENT_TYPEREF;
1530 case TYPEDEFORREF_TYPESPEC:
1531 pclass = MEMBERREF_PARENT_TYPESPEC;
1533 case TYPEDEFORREF_TYPEDEF:
1534 /* should never get here */
1536 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
1539 /* extract the index */
1540 parent >>= TYPEDEFORREF_BITS;
1542 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1543 alloc_table (table, table->rows + 1);
1544 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1545 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1546 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1547 values [MONO_MEMBERREF_SIGNATURE] = sig;
1548 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1555 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1559 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1562 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1563 method->name, method_encode_signature (assembly, method->signature));
1564 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1569 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1573 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1576 field->parent = klass;
1577 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
1578 field->name, fieldref_encode_signature (assembly, field));
1579 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1584 mono_reflection_encode_sighelper (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1592 char *b = blob_size;
1595 g_assert (helper->type == 2);
1597 if (helper->arguments)
1598 nargs = mono_array_length (helper->arguments);
1602 size = 10 + (nargs * 10);
1604 p = buf = g_malloc (size);
1606 /* Encode calling convention */
1607 /* Change Any to Standard */
1608 if ((helper->call_conv & 0x03) == 0x03)
1609 helper->call_conv = 0x01;
1610 /* explicit_this implies has_this */
1611 if (helper->call_conv & 0x40)
1612 helper->call_conv &= 0x20;
1614 if (helper->call_conv == 0) /* Unmanaged */
1615 *p = helper->unmanaged_call_conv - 1;
1618 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
1619 if (helper->call_conv & 0x02) /* varargs */
1624 mono_metadata_encode_value (nargs, p, &p);
1625 encode_reflection_type (assembly, helper->return_type, p, &p);
1626 for (i = 0; i < nargs; ++i) {
1627 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
1628 encode_reflection_type (assembly, pt, p, &p);
1631 g_assert (p - buf < size);
1632 mono_metadata_encode_value (p-buf, b, &b);
1633 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1640 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1643 MonoDynamicTable *table;
1646 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1647 idx = table->next_idx ++;
1649 alloc_table (table, table->rows);
1650 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1652 values [MONO_STAND_ALONE_SIGNATURE] =
1653 mono_reflection_encode_sighelper (assembly, helper);
1659 reflection_cc_to_file (int call_conv) {
1660 switch (call_conv & 0x3) {
1662 case 1: return MONO_CALL_DEFAULT;
1663 case 2: return MONO_CALL_VARARG;
1665 g_assert_not_reached ();
1672 MonoMethodSignature *sig;
1678 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1683 MonoMethodSignature *sig;
1686 name = mono_string_to_utf8 (m->name);
1687 nparams = mono_array_length (m->parameters);
1688 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1690 sig->call_convention = reflection_cc_to_file (m->call_conv);
1691 sig->param_count = nparams;
1692 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1693 for (i = 0; i < nparams; ++i) {
1694 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1695 sig->params [i] = t->type;
1698 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1700 if (strcmp (name, am->name) == 0 &&
1701 mono_metadata_type_equal (am->parent, m->parent->type) &&
1702 mono_metadata_signature_equal (am->sig, sig)) {
1708 am = g_new0 (ArrayMethod, 1);
1711 am->parent = m->parent->type;
1712 am->token = mono_image_get_memberref_token (assembly, am->parent,
1713 name, method_encode_signature (assembly, sig));
1714 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1715 m->table_idx = am->token & 0xffffff;
1720 * Insert into the metadata tables all the info about the TypeBuilder tb.
1721 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1724 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1726 MonoDynamicTable *table;
1728 int i, is_object = 0, is_system = 0;
1731 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1732 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1733 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1734 n = mono_string_to_utf8 (tb->name);
1735 if (strcmp (n, "Object") == 0)
1737 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1739 n = mono_string_to_utf8 (tb->nspace);
1740 if (strcmp (n, "System") == 0)
1742 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1744 if (tb->parent && !(is_system && is_object) &&
1745 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
1746 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1748 values [MONO_TYPEDEF_EXTENDS] = 0;
1749 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1750 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1753 * if we have explicitlayout or sequentiallayouts, output data in the
1754 * ClassLayout table.
1756 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1757 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1759 alloc_table (table, table->rows);
1760 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1761 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1762 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1763 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1766 /* handle interfaces */
1767 if (tb->interfaces) {
1768 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1770 table->rows += mono_array_length (tb->interfaces);
1771 alloc_table (table, table->rows);
1772 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1773 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1774 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1775 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1776 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1777 values += MONO_INTERFACEIMPL_SIZE;
1783 table = &assembly->tables [MONO_TABLE_FIELD];
1784 table->rows += mono_array_length (tb->fields);
1785 alloc_table (table, table->rows);
1786 for (i = 0; i < mono_array_length (tb->fields); ++i)
1787 mono_image_get_field_info (
1788 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1791 /* handle constructors */
1793 table = &assembly->tables [MONO_TABLE_METHOD];
1794 table->rows += mono_array_length (tb->ctors);
1795 alloc_table (table, table->rows);
1796 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1797 mono_image_get_ctor_info (domain,
1798 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1801 /* handle methods */
1803 table = &assembly->tables [MONO_TABLE_METHOD];
1804 table->rows += mono_array_length (tb->methods);
1805 alloc_table (table, table->rows);
1806 for (i = 0; i < mono_array_length (tb->methods); ++i)
1807 mono_image_get_method_info (
1808 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1811 /* Do the same with properties etc.. */
1812 if (tb->events && mono_array_length (tb->events)) {
1813 table = &assembly->tables [MONO_TABLE_EVENT];
1814 table->rows += mono_array_length (tb->events);
1815 alloc_table (table, table->rows);
1816 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1818 alloc_table (table, table->rows);
1819 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1820 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1821 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1822 for (i = 0; i < mono_array_length (tb->events); ++i)
1823 mono_image_get_event_info (
1824 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1826 if (tb->properties && mono_array_length (tb->properties)) {
1827 table = &assembly->tables [MONO_TABLE_PROPERTY];
1828 table->rows += mono_array_length (tb->properties);
1829 alloc_table (table, table->rows);
1830 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1832 alloc_table (table, table->rows);
1833 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1834 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1835 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1836 for (i = 0; i < mono_array_length (tb->properties); ++i)
1837 mono_image_get_property_info (
1838 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1841 MonoDynamicTable *ntable;
1843 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1844 ntable->rows += mono_array_length (tb->subtypes);
1845 alloc_table (ntable, ntable->rows);
1846 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1848 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1849 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1851 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1852 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1853 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1854 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1855 mono_string_to_utf8 (tb->name), tb->table_idx,
1856 ntable->next_idx, ntable->rows);*/
1857 values += MONO_NESTED_CLASS_SIZE;
1864 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
1868 g_ptr_array_add (types, type);
1870 if (!type->subtypes)
1873 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
1874 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
1875 collect_types (types, subtype);
1880 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
1881 MonoReflectionTypeBuilder **type2)
1883 if ((*type1)->table_idx < (*type2)->table_idx)
1886 if ((*type1)->table_idx > (*type2)->table_idx)
1893 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
1898 for (i = 0; i < mono_array_length (pinfo); ++i) {
1899 MonoReflectionParamBuilder *pb;
1900 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
1903 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
1908 type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
1911 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1913 for (i = 0; i < mono_array_length (tb->fields); ++i) {
1914 MonoReflectionFieldBuilder* fb;
1915 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
1916 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
1920 for (i = 0; i < mono_array_length (tb->events); ++i) {
1921 MonoReflectionEventBuilder* eb;
1922 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
1923 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1926 if (tb->properties) {
1927 for (i = 0; i < mono_array_length (tb->properties); ++i) {
1928 MonoReflectionPropertyBuilder* pb;
1929 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
1930 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
1934 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
1935 MonoReflectionCtorBuilder* cb;
1936 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
1937 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
1938 params_add_cattrs (assembly, cb->pinfo);
1943 for (i = 0; i < mono_array_length (tb->methods); ++i) {
1944 MonoReflectionMethodBuilder* mb;
1945 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
1946 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
1947 params_add_cattrs (assembly, mb->pinfo);
1952 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
1953 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
1958 module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
1961 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1963 /* no types in the module */
1967 for (i = 0; i < mono_array_length (mb->types); ++i)
1968 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
1972 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1974 MonoDynamicTable *table;
1978 table = &assembly->tables [MONO_TABLE_MODULE];
1979 mb->table_idx = table->next_idx ++;
1980 name = mono_string_to_utf8 (mb->module.name);
1981 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1983 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1986 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1987 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1988 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1991 #define align_pointer(base,p)\
1993 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1995 (p) += 4 - (__diff & 3);\
1999 compare_semantics (const void *a, const void *b)
2001 const guint32 *a_values = a;
2002 const guint32 *b_values = b;
2003 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
2006 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
2010 compare_custom_attrs (const void *a, const void *b)
2012 const guint32 *a_values = a;
2013 const guint32 *b_values = b;
2015 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
2019 compare_field_marshal (const void *a, const void *b)
2021 const guint32 *a_values = a;
2022 const guint32 *b_values = b;
2024 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
2028 compare_nested (const void *a, const void *b)
2030 const guint32 *a_values = a;
2031 const guint32 *b_values = b;
2033 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
2037 * build_compressed_metadata() fills in the blob of data that represents the
2038 * raw metadata as it will be saved in the PE file. The five streams are output
2039 * and the metadata tables are comnpressed from the guint32 array representation,
2040 * to the compressed on-disk format.
2043 build_compressed_metadata (MonoDynamicAssembly *assembly)
2045 MonoDynamicTable *table;
2047 guint64 valid_mask = 0;
2048 guint64 sorted_mask;
2049 guint32 heapt_size = 0;
2050 guint32 meta_size = 256; /* allow for header and other stuff */
2051 guint32 table_offset;
2052 guint32 ntables = 0;
2059 * We need to use the current ms version or the ms runtime it won't find
2060 * the support dlls. D'oh!
2061 * const char *version = "mono-" VERSION;
2063 const char *version = "v1.0.3705";
2066 MonoDynamicStream *stream;
2067 } stream_desc [] = {
2068 {"#~", &assembly->tstream},
2069 {"#Strings", &assembly->sheap},
2070 {"#US", &assembly->us},
2071 {"#Blob", &assembly->blob},
2072 {"#GUID", &assembly->guid}
2075 /* tables that are sorted */
2076 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
2077 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
2078 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
2079 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
2080 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
2081 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
2083 /* Compute table sizes */
2084 /* the MonoImage has already been created in mono_image_basic_init() */
2085 meta = assembly->assembly.image;
2087 /* Setup the info used by compute_sizes () */
2088 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
2089 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
2090 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
2092 meta_size += assembly->blob.index;
2093 meta_size += assembly->guid.index;
2094 meta_size += assembly->sheap.index;
2095 meta_size += assembly->us.index;
2097 for (i=0; i < 64; ++i)
2098 meta->tables [i].rows = assembly->tables [i].rows;
2100 for (i = 0; i < 64; i++){
2101 if (meta->tables [i].rows == 0)
2103 valid_mask |= (guint64)1 << i;
2105 meta->tables [i].row_size = mono_metadata_compute_size (
2106 meta, i, &meta->tables [i].size_bitfield);
2107 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
2109 heapt_size += 24; /* #~ header size */
2110 heapt_size += ntables * 4;
2111 meta_size += heapt_size;
2112 meta->raw_metadata = g_malloc0 (meta_size);
2113 p = meta->raw_metadata;
2114 /* the metadata signature */
2115 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
2116 /* version numbers and 4 bytes reserved */
2117 int16val = (guint16*)p;
2118 *int16val++ = GUINT16_TO_LE (1);
2119 *int16val = GUINT16_TO_LE (1);
2121 /* version string */
2122 int32val = (guint32*)p;
2123 *int32val = GUINT32_TO_LE ((strlen (version) + 3) & (~3)); /* needs to be multiple of 4 */
2125 memcpy (p, version, GUINT32_FROM_LE (*int32val));
2126 p += GUINT32_FROM_LE (*int32val);
2127 align_pointer (meta->raw_metadata, p);
2128 int16val = (guint16*)p;
2129 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
2130 *int16val = GUINT16_TO_LE (5); /* number of streams */
2134 * write the stream info.
2136 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
2137 table_offset += 3; table_offset &= ~3;
2139 assembly->tstream.index = heapt_size;
2140 for (i = 0; i < 5; ++i) {
2141 int32val = (guint32*)p;
2142 stream_desc [i].stream->offset = table_offset;
2143 *int32val++ = GUINT32_TO_LE (table_offset);
2144 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
2145 table_offset += GUINT32_FROM_LE (*int32val);
2146 table_offset += 3; table_offset &= ~3;
2148 strcpy (p, stream_desc [i].name);
2149 p += strlen (stream_desc [i].name) + 1;
2150 align_pointer (meta->raw_metadata, p);
2153 * now copy the data, the table stream header and contents goes first.
2155 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
2156 p = meta->raw_metadata + assembly->tstream.offset;
2157 int32val = (guint32*)p;
2158 *int32val = GUINT32_TO_LE (0); /* reserved */
2160 *p++ = 1; /* version */
2162 if (meta->idx_string_wide)
2164 if (meta->idx_guid_wide)
2166 if (meta->idx_blob_wide)
2169 *p++ = 0; /* reserved */
2170 int64val = (guint64*)p;
2171 *int64val++ = GUINT64_TO_LE (valid_mask);
2172 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
2174 int32val = (guint32*)p;
2175 for (i = 0; i < 64; i++){
2176 if (meta->tables [i].rows == 0)
2178 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
2180 p = (unsigned char*)int32val;
2182 /* sort the tables that still need sorting */
2183 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2185 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
2186 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2188 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
2189 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2191 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
2192 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2194 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
2196 /* compress the tables */
2197 for (i = 0; i < 64; i++){
2200 guint32 bitfield = meta->tables [i].size_bitfield;
2201 if (!meta->tables [i].rows)
2203 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
2204 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
2205 meta->tables [i].base = p;
2206 for (row = 1; row <= meta->tables [i].rows; ++row) {
2207 values = assembly->tables [i].values + row * assembly->tables [i].columns;
2208 for (col = 0; col < assembly->tables [i].columns; ++col) {
2209 switch (mono_metadata_table_size (bitfield, col)) {
2211 *p++ = values [col];
2214 *p++ = values [col] & 0xff;
2215 *p++ = (values [col] >> 8) & 0xff;
2218 *p++ = values [col] & 0xff;
2219 *p++ = (values [col] >> 8) & 0xff;
2220 *p++ = (values [col] >> 16) & 0xff;
2221 *p++ = (values [col] >> 24) & 0xff;
2224 g_assert_not_reached ();
2228 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
2231 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
2232 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
2233 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
2234 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
2235 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
2237 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
2241 * Some tables in metadata need to be sorted according to some criteria, but
2242 * when methods and fields are first created with reflection, they may be assigned a token
2243 * that doesn't correspond to the final token they will get assigned after the sorting.
2244 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
2245 * with the reflection objects that represent them. Once all the tables are set up, the
2246 * reflection objects will contains the correct table index. fixup_method() will fixup the
2247 * tokens for the method with ILGenerator @ilgen.
2250 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
2251 guint32 code_idx = GPOINTER_TO_UINT (value);
2252 MonoReflectionILTokenInfo *iltoken;
2253 MonoReflectionFieldBuilder *field;
2254 MonoReflectionCtorBuilder *ctor;
2255 MonoReflectionMethodBuilder *method;
2256 MonoReflectionTypeBuilder *tb;
2257 MonoReflectionArrayMethod *am;
2259 unsigned char *target;
2261 for (i = 0; i < ilgen->num_token_fixups; ++i) {
2262 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
2263 target = assembly->code.data + code_idx + iltoken->code_pos;
2264 switch (target [3]) {
2265 case MONO_TABLE_FIELD:
2266 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
2267 field = (MonoReflectionFieldBuilder *)iltoken->member;
2268 idx = field->table_idx;
2269 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
2270 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
2271 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
2273 g_assert_not_reached ();
2276 case MONO_TABLE_METHOD:
2277 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
2278 method = (MonoReflectionMethodBuilder *)iltoken->member;
2279 idx = method->table_idx;
2280 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
2281 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
2282 idx = ctor->table_idx;
2283 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
2284 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
2285 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
2287 g_assert_not_reached ();
2290 case MONO_TABLE_TYPEDEF:
2291 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
2292 g_assert_not_reached ();
2293 tb = (MonoReflectionTypeBuilder *)iltoken->member;
2294 idx = tb->table_idx;
2296 case MONO_TABLE_MEMBERREF:
2297 if (strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod"))
2298 g_assert_not_reached ();
2299 am = (MonoReflectionArrayMethod*)iltoken->member;
2300 idx = am->table_idx;
2303 g_error ("got unexpected table 0x%02x in fixup", target [3]);
2305 target [0] = idx & 0xff;
2306 target [1] = (idx >> 8) & 0xff;
2307 target [2] = (idx >> 16) & 0xff;
2312 assembly_add_resource (MonoDynamicAssembly *assembly, MonoReflectionResource *rsrc)
2314 MonoDynamicTable *table;
2318 char *b = blob_size;
2320 guint32 idx, offset;
2322 if (rsrc->filename) {
2323 name = mono_string_to_utf8 (rsrc->filename);
2324 sname = g_path_get_basename (name);
2326 table = &assembly->tables [MONO_TABLE_FILE];
2328 alloc_table (table, table->rows);
2329 values = table->values + table->next_idx * MONO_FILE_SIZE;
2330 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
2331 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
2334 mono_sha1_get_digest_from_file (name, hash);
2335 mono_metadata_encode_value (20, b, &b);
2336 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2337 mono_image_add_stream_data (&assembly->blob, hash, 20);
2339 idx = table->next_idx++;
2340 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
2344 offset = mono_array_length (rsrc->data);
2345 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
2346 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
2347 offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
2348 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
2352 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
2354 alloc_table (table, table->rows);
2355 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
2356 values [MONO_MANIFEST_OFFSET] = offset;
2357 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
2358 name = mono_string_to_utf8 (rsrc->name);
2359 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
2361 values [MONO_MANIFEST_IMPLEMENTATION] = idx;
2366 set_version_from_string (MonoString *version, guint32 *values)
2368 gchar *ver, *p, *str;
2371 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
2372 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
2373 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
2374 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
2377 ver = str = mono_string_to_utf8 (version);
2378 for (i = 0; i < 4; ++i) {
2379 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
2385 /* handle Revision and Build */
2395 load_public_key (MonoString *fname, MonoDynamicAssembly *assembly) {
2396 char *name, *content;
2402 name = mono_string_to_utf8 (fname);
2403 if (g_file_get_contents (name, &content, &len, NULL)) {
2405 char *b = blob_size;
2406 /* check it's a public key or keypair */
2407 mono_metadata_encode_value (len, b, &b);
2408 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
2409 mono_image_add_stream_data (&assembly->blob, content, len);
2411 /* need to get the actual value from the key type... */
2412 assembly->strong_name_size = 128;
2413 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
2415 /* FIXME: how do we tell mcs if loading fails? */
2421 * mono_image_build_metadata() will fill the info in all the needed metadata tables
2422 * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
2423 * and recursively outputs the info for a module. Each module will output all the info
2424 * about it's types etc.
2425 * At the end of the process, method and field tokens are fixed up and the on-disk
2426 * compressed metadata representation is created.
2429 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
2431 MonoDynamicTable *table;
2432 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
2433 MonoDomain *domain = mono_object_domain (assemblyb);
2439 if (assembly->text_rva)
2442 assembly->text_rva = START_TEXT_RVA;
2444 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2445 alloc_table (table, 1);
2446 values = table->values + MONO_ASSEMBLY_SIZE;
2447 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2448 name = mono_string_to_utf8 (assemblyb->name);
2449 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
2451 if (assemblyb->culture) {
2452 name = mono_string_to_utf8 (assemblyb->culture);
2453 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
2456 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2458 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->keyfile, assembly);
2459 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2460 set_version_from_string (assemblyb->version, values);
2462 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2463 table->rows = 1; /* .<Module> */
2465 alloc_table (table, table->rows);
2467 * Set the first entry.
2469 values = table->values + table->columns;
2470 values [MONO_TYPEDEF_FLAGS] = 0;
2471 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2472 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2473 values [MONO_TYPEDEF_EXTENDS] = 0;
2474 values [MONO_TYPEDEF_FIELD_LIST] = 1;
2475 values [MONO_TYPEDEF_METHOD_LIST] = 1;
2478 * handle global methods
2479 * FIXME: test what to do when global methods are defined in multiple modules.
2481 if (assemblyb->modules) {
2482 MonoReflectionModuleBuilder *mod = mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, 0);
2483 if (mod->global_methods) {
2484 table = &assembly->tables [MONO_TABLE_METHOD];
2485 table->rows += mono_array_length (mod->global_methods);
2486 alloc_table (table, table->rows);
2487 for (i = 0; i < mono_array_length (mod->global_methods); ++i)
2488 mono_image_get_method_info (
2489 mono_array_get (mod->global_methods, MonoReflectionMethodBuilder*, i), assembly);
2493 if (assemblyb->modules) {
2494 len = mono_array_length (assemblyb->modules);
2495 table = &assembly->tables [MONO_TABLE_MODULE];
2496 alloc_table (table, len);
2497 for (i = 0; i < len; ++i)
2498 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
2500 table = &assembly->tables [MONO_TABLE_MODULE];
2502 alloc_table (table, table->rows);
2503 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
2508 if (assemblyb->modules) {
2509 /* Collect all types into a list sorted by their table_idx */
2510 GPtrArray *types = g_ptr_array_new ();
2512 len = mono_array_length (assemblyb->modules);
2513 for (i = 0; i < len; ++i) {
2514 MonoReflectionModuleBuilder *mb =
2515 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2517 for (i = 0; i < mono_array_length (mb->types); ++i) {
2518 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
2519 collect_types (types, type);
2523 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
2524 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2525 table->rows += types->len;
2526 alloc_table (table, table->rows);
2528 for (i = 0; i < types->len; ++i) {
2529 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
2530 mono_image_get_type_info (domain, type, assembly);
2532 g_ptr_array_free (types, FALSE);
2536 * table->rows is already set above and in mono_image_fill_module_table.
2538 /* add all the custom attributes at the end, once all the indexes are stable */
2539 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
2541 if (assemblyb->modules) {
2542 len = mono_array_length (assemblyb->modules);
2543 for (i = 0; i < len; ++i)
2544 module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
2548 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2552 * mono_image_insert_string:
2553 * @assembly: assembly builder object
2556 * Insert @str into the user string stream of @assembly.
2559 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
2565 MONO_ARCH_SAVE_REGS;
2567 if (!assembly->dynamic_assembly)
2568 mono_image_basic_init (assembly);
2569 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
2570 idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
2571 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2573 char *swapped = g_malloc (2 * mono_string_length (str));
2574 const char *p = (const char*)mono_string_chars (str);
2576 swap_with_size (swapped, p, 2, mono_string_length (str));
2577 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2581 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2583 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2585 mono_g_hash_table_insert (assembly->dynamic_assembly->tokens,
2586 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
2588 return MONO_TOKEN_STRING | idx;
2592 * mono_image_create_token:
2593 * @assembly: a dynamic assembly
2596 * Get a token to insert in the IL code stream for the given MemberInfo.
2597 * @obj can be one of:
2598 * ConstructorBuilder
2608 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2614 g_error ("System.Array methods not yet supported");
2616 klass = obj->vtable->klass;
2617 if (strcmp (klass->name, "MethodBuilder") == 0) {
2618 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2619 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2620 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2622 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2623 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2624 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2625 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2627 else if (strcmp (klass->name, "FieldBuilder") == 0) {
2628 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2629 token = mb->table_idx | MONO_TOKEN_FIELD_DEF;
2631 else if (strcmp (klass->name, "TypeBuilder") == 0) {
2632 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2633 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
2635 else if (strcmp (klass->name, "MonoType") == 0) {
2636 MonoReflectionType *tb = (MonoReflectionType *)obj;
2637 token = mono_metadata_token_from_dor (
2638 mono_image_typedef_or_ref (assembly, tb->type));
2640 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
2641 strcmp (klass->name, "MonoMethod") == 0) {
2642 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2643 if (m->method->klass->image == assembly->assembly.image)
2644 /* Will get fixed up */
2645 token = MONO_TOKEN_METHOD_DEF | 0;
2647 token = mono_image_get_methodref_token (assembly, m->method);
2648 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2650 else if (strcmp (klass->name, "MonoField") == 0) {
2651 MonoReflectionField *f = (MonoReflectionField *)obj;
2652 if (f->klass->image == assembly->assembly.image)
2653 /* Will get fixed up */
2654 token = MONO_TOKEN_FIELD_DEF | 0;
2656 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2657 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2659 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2660 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2661 token = mono_image_get_array_token (assembly, m);
2663 else if (strcmp (klass->name, "SignatureHelper") == 0) {
2664 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
2665 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
2668 g_error ("requested token for %s\n", klass->name);
2670 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
2677 guint32 import_lookup_table;
2681 guint32 import_address_table_rva;
2689 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
2692 create_dynamic_mono_image (char *assembly_name, char *module_name)
2696 image = g_new0 (MonoImage, 1);
2698 /* keep in sync with image.c */
2699 image->name = assembly_name;
2700 image->assembly_name = image->name; /* they may be different */
2701 image->module_name = module_name;
2702 image->references = g_new0 (MonoAssembly*, 1);
2703 image->references [0] = NULL;
2705 image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2706 image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2707 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2708 image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2710 image->delegate_begin_invoke_cache =
2711 g_hash_table_new ((GHashFunc)mono_signature_hash,
2712 (GCompareFunc)mono_metadata_signature_equal);
2713 image->delegate_end_invoke_cache =
2714 g_hash_table_new ((GHashFunc)mono_signature_hash,
2715 (GCompareFunc)mono_metadata_signature_equal);
2716 image->delegate_invoke_cache =
2717 g_hash_table_new ((GHashFunc)mono_signature_hash,
2718 (GCompareFunc)mono_metadata_signature_equal);
2720 image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2721 image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2722 image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2723 image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2729 * mono_image_basic_init:
2730 * @assembly: an assembly builder object
2732 * Create the MonoImage that represents the assembly builder and setup some
2733 * of the helper hash table and the basic metadata streams.
2736 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2738 static const guchar entrycode [16] = {0xff, 0x25, 0};
2739 MonoDynamicAssembly *assembly;
2743 MONO_ARCH_SAVE_REGS;
2745 if (assemblyb->dynamic_assembly)
2749 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
2751 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2754 assembly->assembly.dynamic = assembly;
2755 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
2756 assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2757 assembly->method_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2758 assembly->field_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2759 assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2760 assembly->tokens = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2761 assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2762 assembly->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
2764 string_heap_init (&assembly->sheap);
2765 mono_image_add_stream_data (&assembly->us, "", 1);
2766 add_to_blob_cached (assembly, (char*) "", 1, NULL, 0);
2767 /* import tables... */
2768 mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2769 assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2770 assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2771 mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2772 assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2773 mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2774 assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2775 stream_data_align (&assembly->code);
2777 assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2779 for (i=0; i < 64; ++i) {
2780 assembly->tables [i].next_idx = 1;
2781 assembly->tables [i].columns = table_sizes [i];
2784 image = create_dynamic_mono_image (mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
2785 assembly->assembly.aname.name = image->name;
2786 image->assembly = (MonoAssembly*)assembly;
2787 assembly->assembly.image = image;
2789 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
2790 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
2794 calc_section_size (MonoDynamicAssembly *assembly)
2798 /* alignment constraints */
2799 assembly->code.index += 3;
2800 assembly->code.index &= ~3;
2801 assembly->meta_size += 3;
2802 assembly->meta_size &= ~3;
2803 assembly->resources.index += 3;
2804 assembly->resources.index &= ~3;
2806 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2807 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2810 assembly->sections [MONO_SECTION_RELOC].size = 12;
2811 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2818 * mono_image_create_pefile:
2819 * @assemblyb: an assembly builder object
2821 * When we need to save an assembly, we first call this function that ensures the metadata
2822 * tables are built for all the modules in the assembly. This function creates the PE-COFF
2823 * header, the image sections, the CLI header etc. all the data is written in
2824 * assembly->pefile where it can be easily retrieved later in chunks.
2827 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
2828 MonoMSDOSHeader *msdos;
2829 MonoDotNetHeader *header;
2830 MonoSectionTable *section;
2831 MonoCLIHeader *cli_header;
2832 guint32 size, image_size, virtual_base, text_offset;
2833 guint32 header_start, section_start, file_offset, virtual_offset;
2834 MonoDynamicAssembly *assembly;
2835 MonoDynamicStream *pefile;
2837 guint32 *rva, value;
2840 static const unsigned char msheader[] = {
2841 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2842 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2843 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2844 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2845 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2846 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2847 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2848 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2851 mono_image_basic_init (assemblyb);
2852 assembly = assemblyb->dynamic_assembly;
2854 /* already created */
2855 if (assembly->pefile.index)
2858 mono_image_build_metadata (assemblyb);
2860 if (assemblyb->resources) {
2861 int len = mono_array_length (assemblyb->resources);
2862 for (i = 0; i < len; ++i)
2863 assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
2867 build_compressed_metadata (assembly);
2869 nsections = calc_section_size (assembly);
2871 pefile = &assembly->pefile;
2873 /* The DOS header and stub */
2874 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2875 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
2877 /* the dotnet header */
2878 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2880 /* the section tables */
2881 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2883 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2884 virtual_offset = VIRT_ALIGN;
2887 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2888 if (!assembly->sections [i].size)
2891 file_offset += FILE_ALIGN - 1;
2892 file_offset &= ~(FILE_ALIGN - 1);
2893 virtual_offset += VIRT_ALIGN - 1;
2894 virtual_offset &= ~(VIRT_ALIGN - 1);
2896 assembly->sections [i].offset = file_offset;
2897 assembly->sections [i].rva = virtual_offset;
2899 file_offset += assembly->sections [i].size;
2900 virtual_offset += assembly->sections [i].size;
2901 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2904 file_offset += FILE_ALIGN - 1;
2905 file_offset &= ~(FILE_ALIGN - 1);
2906 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
2908 image_size += section_start + sizeof (MonoSectionTable) * nsections;
2910 /* back-patch info */
2911 msdos = (MonoMSDOSHeader*)pefile->data;
2912 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
2913 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
2914 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2916 header = (MonoDotNetHeader*)(pefile->data + header_start);
2917 header->pesig [0] = 'P';
2918 header->pesig [1] = 'E';
2920 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
2921 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2922 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2923 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2924 if (assemblyb->pekind == 1) {
2926 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
2929 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2932 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2934 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2935 header->pe.pe_major = 6;
2936 header->pe.pe_minor = 0;
2937 size = assembly->sections [MONO_SECTION_TEXT].size;
2938 size += FILE_ALIGN - 1;
2939 size &= ~(FILE_ALIGN - 1);
2940 header->pe.pe_code_size = size;
2941 size = assembly->sections [MONO_SECTION_RSRC].size;
2942 size += FILE_ALIGN - 1;
2943 size &= ~(FILE_ALIGN - 1);
2944 header->pe.pe_data_size = size;
2945 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2946 header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
2947 header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
2948 /* pe_rva_entry_point always at the beginning of the text section */
2949 header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
2951 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2952 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2953 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2954 header->nt.pe_os_major = GUINT16_FROM_LE (4);
2955 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2956 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2957 size = section_start;
2958 size += FILE_ALIGN - 1;
2959 size &= ~(FILE_ALIGN - 1);
2960 header->nt.pe_header_size = GUINT32_FROM_LE (size);
2962 size += VIRT_ALIGN - 1;
2963 size &= ~(VIRT_ALIGN - 1);
2964 header->nt.pe_image_size = GUINT32_FROM_LE (size);
2967 // Translate the PEFileKind value to the value expected by the Windows loader
2970 short kind = assemblyb->pekind;
2973 // PEFileKinds.ConsoleApplication == 2
2974 // PEFileKinds.WindowApplication == 3
2977 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
2978 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
2984 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
2986 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2987 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2988 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2989 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2990 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2991 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2993 /* fill data directory entries */
2995 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2996 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2998 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2999 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
3001 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
3002 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
3003 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
3004 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
3005 /* patch imported function RVA name */
3006 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
3007 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
3009 /* the import table */
3010 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
3011 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
3012 /* patch imported dll RVA name and other entries in the dir */
3013 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
3014 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
3015 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
3016 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
3017 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
3018 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
3020 p = (assembly->code.data + assembly->ilt_offset);
3021 value = (assembly->text_rva + assembly->imp_names_offset - 2);
3022 *p++ = (value) & 0xff;
3023 *p++ = (value >> 8) & (0xff);
3024 *p++ = (value >> 16) & (0xff);
3025 *p++ = (value >> 24) & (0xff);
3027 /* the CLI header info */
3028 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
3029 cli_header->ch_size = GUINT32_FROM_LE (72);
3030 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
3031 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
3032 if (assemblyb->entry_point)
3033 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
3035 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
3036 /* The embedded managed resources */
3037 text_offset = assembly->text_rva + assembly->code.index;
3038 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
3039 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
3040 text_offset += assembly->resources.index;
3041 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
3042 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
3043 text_offset += assembly->meta_size;
3044 if (assembly->strong_name_size) {
3045 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
3046 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
3047 text_offset += assembly->strong_name_size;
3050 /* write the section tables and section content */
3051 section = (MonoSectionTable*)(pefile->data + section_start);
3052 for (i = 0; i < MONO_SECTION_MAX; ++i) {
3053 static const char *section_names [] = {
3054 ".text", ".rsrc", ".reloc"
3056 if (!assembly->sections [i].size)
3058 strcpy (section->st_name, section_names [i]);
3059 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
3060 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
3061 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
3062 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
3063 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
3064 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
3065 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
3067 case MONO_SECTION_TEXT:
3068 /* patch entry point */
3069 p = (assembly->code.data + 2);
3070 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
3071 *p++ = (value) & 0xff;
3072 *p++ = (value >> 8) & 0xff;
3073 *p++ = (value >> 16) & 0xff;
3074 *p++ = (value >> 24) & 0xff;
3076 text_offset = assembly->sections [i].offset;
3077 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
3078 text_offset += assembly->code.index;
3079 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
3080 text_offset += assembly->resources.index;
3081 memcpy (pefile->data + text_offset, assembly->assembly.image->raw_metadata, assembly->meta_size);
3082 text_offset += assembly->meta_size;
3083 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
3085 case MONO_SECTION_RELOC:
3086 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
3087 *rva = GUINT32_FROM_LE (assembly->text_rva);
3089 *rva = GUINT32_FROM_LE (12);
3091 data16 = (guint16*)rva;
3093 * the entrypoint is always at the start of the text section
3094 * 3 is IMAGE_REL_BASED_HIGHLOW
3095 * 2 is patch_size_rva - text_rva
3097 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
3099 *data16 = 0; /* terminate */
3101 case MONO_SECTION_RSRC:
3103 g_assert_not_reached ();
3108 /* check that the file is properly padded */
3111 FILE *f = fopen ("mypetest.exe", "w");
3112 fwrite (pefile->data, pefile->index, 1, f);
3119 * We need to return always the same object for MethodInfo, FieldInfo etc..
3120 * but we need to consider the reflected type.
3121 * type uses a different hash, since it uses custom hash/equal functions.
3126 MonoClass *refclass;
3130 reflected_equal (gconstpointer a, gconstpointer b) {
3131 const ReflectedEntry *ea = a;
3132 const ReflectedEntry *eb = b;
3134 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
3138 reflected_hash (gconstpointer a) {
3139 const ReflectedEntry *ea = a;
3140 return GPOINTER_TO_UINT (ea->item);
3143 #define CHECK_OBJECT(t,p,k) \
3149 mono_domain_lock (domain); \
3150 if (!domain->refobject_hash) \
3151 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
3152 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
3153 mono_domain_unlock (domain); \
3159 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
3161 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
3164 #define CACHE_OBJECT(p,o,k) \
3166 ReflectedEntry *e = ALLOC_REFENTRY; \
3168 e->refclass = (k); \
3169 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
3170 mono_domain_unlock (domain); \
3174 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
3176 /* this is done only once */
3177 mono_domain_lock (domain);
3178 CACHE_OBJECT (assembly, res, NULL);
3182 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoImage *module)
3184 /* this is done only once */
3185 mono_domain_lock (domain);
3186 CACHE_OBJECT (module, res, NULL);
3190 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
3192 MonoImage *image = moduleb->module.image;
3193 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
3196 /* a MonoImage was already created in mono_image_basic_init () */
3197 image = ab->dynamic_assembly->assembly.image;
3199 image = create_dynamic_mono_image (mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.name));
3201 moduleb->module.image = image;
3202 register_module (mono_object_domain (moduleb), moduleb, image);
3207 * mono_assembly_get_object:
3208 * @domain: an app domain
3209 * @assembly: an assembly
3211 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
3213 MonoReflectionAssembly*
3214 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
3216 static MonoClass *System_Reflection_Assembly;
3217 MonoReflectionAssembly *res;
3219 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
3220 if (!System_Reflection_Assembly)
3221 System_Reflection_Assembly = mono_class_from_name (
3222 mono_defaults.corlib, "System.Reflection", "Assembly");
3223 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
3224 res->assembly = assembly;
3225 CACHE_OBJECT (assembly, res, NULL);
3230 MonoReflectionModule*
3231 mono_module_get_object (MonoDomain *domain, MonoImage *image)
3233 static MonoClass *System_Reflection_Module;
3234 MonoReflectionModule *res;
3236 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
3237 if (!System_Reflection_Module)
3238 System_Reflection_Module = mono_class_from_name (
3239 mono_defaults.corlib, "System.Reflection", "Module");
3240 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
3243 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
3245 res->fqname = mono_string_new (domain, image->name);
3246 res->name = mono_string_new (domain, image->name);
3247 res->scopename = mono_string_new (domain, image->module_name);
3249 CACHE_OBJECT (image, res, NULL);
3255 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
3257 if ((t1->type != t2->type) ||
3258 (t1->byref != t2->byref))
3262 case MONO_TYPE_VOID:
3263 case MONO_TYPE_BOOLEAN:
3264 case MONO_TYPE_CHAR:
3275 case MONO_TYPE_STRING:
3278 case MONO_TYPE_OBJECT:
3279 case MONO_TYPE_TYPEDBYREF:
3281 case MONO_TYPE_VALUETYPE:
3282 case MONO_TYPE_CLASS:
3283 return t1->data.klass == t2->data.klass;
3285 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3286 case MONO_TYPE_SZARRAY:
3288 if (t1->data.type->type != t2->data.type->type)
3290 if (t1->data.type->type == MONO_TYPE_CLASS || t1->data.type->type == MONO_TYPE_VALUETYPE)
3291 return t1->data.type->data.klass == t2->data.type->data.klass;
3292 if (t1->data.type->type == MONO_TYPE_SZARRAY) {
3297 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3298 case MONO_TYPE_ARRAY:
3299 if (t1->data.array->rank != t2->data.array->rank)
3301 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
3303 g_error ("implement type compare for %0x!", t1->type);
3311 mymono_metadata_type_hash (MonoType *t1)
3317 hash |= t1->byref << 6; /* do not collide with t1->type values */
3319 case MONO_TYPE_VALUETYPE:
3320 case MONO_TYPE_CLASS:
3321 /* check if the distribution is good enough */
3322 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
3324 case MONO_TYPE_SZARRAY:
3325 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
3331 * mono_type_get_object:
3332 * @domain: an app domain
3335 * Return an System.MonoType object representing the type @type.
3338 mono_type_get_object (MonoDomain *domain, MonoType *type)
3340 MonoReflectionType *res;
3341 MonoClass *klass = mono_class_from_mono_type (type);
3343 mono_domain_lock (domain);
3344 if (!domain->type_hash)
3345 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
3346 (GCompareFunc)mymono_metadata_type_equal);
3347 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
3348 mono_domain_unlock (domain);
3351 if (klass->reflection_info && !klass->wastypebuilder) {
3352 //g_assert_not_reached ();
3353 /* should this be considered an error condition? */
3355 mono_domain_unlock (domain);
3356 return klass->reflection_info;
3359 mono_class_init (klass);
3360 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
3362 mono_g_hash_table_insert (domain->type_hash, type, res);
3363 mono_domain_unlock (domain);
3368 * mono_method_get_object:
3369 * @domain: an app domain
3371 * @refclass: the reflected type (can be NULL)
3373 * Return an System.Reflection.MonoMethod object representing the method @method.
3375 MonoReflectionMethod*
3376 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
3379 * We use the same C representation for methods and constructors, but the type
3380 * name in C# is different.
3384 MonoReflectionMethod *ret;
3387 refclass = method->klass;
3389 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
3390 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3391 cname = "MonoCMethod";
3393 cname = "MonoMethod";
3394 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
3396 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
3397 ret->method = method;
3398 ret->name = mono_string_new (domain, method->name);
3399 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
3400 CACHE_OBJECT (method, ret, refclass);
3405 * mono_field_get_object:
3406 * @domain: an app domain
3410 * Return an System.Reflection.MonoField object representing the field @field
3413 MonoReflectionField*
3414 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
3416 MonoReflectionField *res;
3419 CHECK_OBJECT (MonoReflectionField *, field, klass);
3420 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
3421 res = (MonoReflectionField *)mono_object_new (domain, oklass);
3424 CACHE_OBJECT (field, res, klass);
3429 * mono_property_get_object:
3430 * @domain: an app domain
3432 * @property: a property
3434 * Return an System.Reflection.MonoProperty object representing the property @property
3437 MonoReflectionProperty*
3438 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
3440 MonoReflectionProperty *res;
3443 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
3444 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
3445 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
3447 res->property = property;
3448 CACHE_OBJECT (property, res, klass);
3453 * mono_event_get_object:
3454 * @domain: an app domain
3458 * Return an System.Reflection.MonoEvent object representing the event @event
3461 MonoReflectionEvent*
3462 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
3464 MonoReflectionEvent *res;
3467 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
3468 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
3469 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
3472 CACHE_OBJECT (event, res, klass);
3477 * mono_param_get_objects:
3478 * @domain: an app domain
3481 * Return an System.Reflection.ParameterInfo array object representing the parameters
3482 * in the method @method.
3484 MonoReflectionParameter**
3485 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
3487 MonoReflectionParameter **res;
3488 MonoReflectionMethod *member;
3493 if (!method->signature->param_count)
3496 member = mono_method_get_object (domain, method, NULL);
3497 names = g_new (char *, method->signature->param_count);
3498 mono_method_get_param_names (method, (const char **) names);
3500 /* Note: the cache is based on the address of the signature into the method
3501 * since we already cache MethodInfos with the method as keys.
3503 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature), NULL);
3504 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
3506 res = GC_MALLOC (sizeof (MonoReflectionParameter*) * method->signature->param_count);
3508 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
3510 for (i = 0; i < method->signature->param_count; ++i) {
3511 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
3512 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
3513 res [i]->DefaultValueImpl = NULL; /* FIXME */
3514 res [i]->MemberImpl = (MonoObject*)member;
3515 res [i]->NameImpl = mono_string_new (domain, names [i]);
3516 res [i]->PositionImpl = i + 1;
3517 res [i]->AttrsImpl = method->signature->params [i]->attrs;
3520 CACHE_OBJECT (&(method->signature), res, NULL);
3525 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
3529 memset (assembly, 0, sizeof (MonoAssemblyName));
3531 assembly->culture = "";
3533 while (*p && (isalnum (*p) || *p == '.'))
3536 while (*p == ' ' || *p == ',') {
3545 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
3547 assembly->major = strtoul (p, &s, 10);
3548 if (s == p || *s != '.')
3551 assembly->minor = strtoul (p, &s, 10);
3552 if (s == p || *s != '.')
3555 assembly->build = strtoul (p, &s, 10);
3556 if (s == p || *s != '.')
3559 assembly->revision = strtoul (p, &s, 10);
3562 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
3564 if (strncmp (p, "neutral", 7) == 0) {
3565 assembly->culture = "";
3568 assembly->culture = p;
3569 while (*p && *p != ',') {
3573 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
3576 while (*s && isxdigit (*s)) {
3580 assembly->hash_len = s - p;
3581 if (!(s-p) || ((s-p) & 1))
3583 assembly->hash_value = s = p;
3584 while (*s && isxdigit (*s)) {
3586 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3589 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3594 while (*p && *p != ',')
3598 while (*p == ' ' || *p == ',') {
3612 * mono_reflection_parse_type:
3615 * Parse a type name as accepted by the GetType () method and output the info
3616 * extracted in the info structure.
3617 * the name param will be mangled, so, make a copy before passing it to this function.
3618 * The fields in info will be valid until the memory pointed to by name is valid.
3619 * Returns 0 on parse error.
3620 * See also mono_type_get_name () below.
3623 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
3625 char *start, *p, *w, *last_point, *startn;
3626 int in_modifiers = 0;
3627 int isbyref = 0, rank;
3629 start = p = w = name;
3631 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
3632 info->name = info->name_space = NULL;
3633 info->nested = NULL;
3634 info->modifiers = NULL;
3636 /* last_point separates the namespace from the name */
3642 *p = 0; /* NULL terminate the name */
3644 /* we have parsed the nesting namespace + name */
3646 info->nested = g_list_append (info->nested, startn);
3650 info->name_space = start;
3652 info->name = last_point + 1;
3654 info->name_space = (char *)"";
3679 info->nested = g_list_append (info->nested, startn);
3682 info->name_space = start;
3684 info->name = last_point + 1;
3686 info->name_space = (char *)"";
3693 if (isbyref) /* only one level allowed by the spec */
3696 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
3700 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
3711 else if (*p != '*') /* '*' means unknown lower bound */
3717 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
3729 return 0; /* missing assembly name */
3730 if (!assembly_name_to_aname (&info->assembly, p))
3736 if (info->assembly.name)
3739 *w = 0; /* terminate class name */
3740 if (!info->name || !*info->name)
3742 /* add other consistency checks */
3747 mono_type_get_name_recurse (MonoType *type, GString *str)
3751 switch (type->type) {
3752 case MONO_TYPE_ARRAY: {
3753 int i, rank = type->data.array->rank;
3755 mono_type_get_name_recurse (type->data.array->type, str);
3756 g_string_append_c (str, '[');
3757 for (i = 1; i < rank; i++)
3758 g_string_append_c (str, ',');
3759 g_string_append_c (str, ']');
3762 case MONO_TYPE_SZARRAY:
3763 mono_type_get_name_recurse (type->data.type, str);
3764 g_string_append (str, "[]");
3767 mono_type_get_name_recurse (type->data.type, str);
3768 g_string_append_c (str, '*');
3771 klass = mono_class_from_mono_type (type);
3772 if (klass->nested_in) {
3773 mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
3774 g_string_append_c (str, '+');
3776 if (*klass->name_space) {
3777 g_string_append (str, klass->name_space);
3778 g_string_append_c (str, '.');
3780 g_string_append (str, klass->name);
3786 * mono_type_get_name:
3789 * Returns the string representation for type as required by System.Reflection.
3790 * The inverse of mono_reflection_parse_type ().
3793 mono_type_get_name (MonoType *type)
3795 GString* result = g_string_new ("");
3796 mono_type_get_name_recurse (type, result);
3799 g_string_append_c (result, '&');
3801 return g_string_free (result, FALSE);
3805 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3812 image = mono_defaults.corlib;
3815 klass = mono_class_from_name_case (image, info->name_space, info->name);
3817 klass = mono_class_from_name (image, info->name_space, info->name);
3820 for (mod = info->nested; mod; mod = mod->next) {
3823 mono_class_init (klass);
3824 nested = klass->nested_classes;
3827 klass = nested->data;
3829 if (g_strcasecmp (klass->name, mod->data) == 0)
3832 if (strcmp (klass->name, mod->data) == 0)
3836 nested = nested->next;
3843 mono_class_init (klass);
3844 for (mod = info->modifiers; mod; mod = mod->next) {
3845 modval = GPOINTER_TO_UINT (mod->data);
3846 if (!modval) { /* byref: must be last modifier */
3847 return &klass->this_arg;
3848 } else if (modval == -1) {
3849 klass = mono_ptr_class_get (&klass->byval_arg);
3850 } else { /* array rank */
3851 klass = mono_array_class_get (&klass->byval_arg, modval);
3853 mono_class_init (klass);
3856 return &klass->byval_arg;
3860 * mono_reflection_get_type:
3861 * @image: a metadata context
3862 * @info: type description structure
3863 * @ignorecase: flag for case-insensitive string compares
3865 * Build a MonoType from the type description in @info.
3870 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3873 MonoReflectionAssembly *assembly;
3877 type = mono_reflection_get_type_internal (image, info, ignorecase);
3880 if (!image || !mono_domain_has_type_resolve (mono_domain_get ()))
3883 // Reconstruct the type name
3884 fullName = g_string_new ("");
3885 if (info->name_space && (info->name_space [0] != '\0'))
3886 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
3888 g_string_printf (fullName, info->name);
3889 for (mod = info->nested; mod; mod = mod->next)
3890 g_string_append_printf (fullName, "+%s", (char*)mod->data);
3893 mono_domain_try_type_resolve (
3894 mono_domain_get (), fullName->str, NULL);
3896 type = mono_reflection_get_type_internal (assembly->assembly->image,
3898 g_string_free (fullName, TRUE);
3903 * mono_reflection_type_from_name:
3905 * @image: a metadata context (can be NULL).
3907 * Retrieves a MonoType from its @name. If the name is not fully qualified,
3908 * it defaults to get the type from @image or, if @image is NULL or loading
3909 * from it fails, uses corlib.
3913 mono_reflection_type_from_name (char *name, MonoImage *image)
3916 MonoTypeNameParse info;
3918 /*g_print ("requested type %s\n", str);*/
3919 if (!mono_reflection_parse_type (name, &info)) {
3920 g_list_free (info.modifiers);
3921 g_list_free (info.nested);
3925 if (info.assembly.name) {
3926 image = mono_image_loaded (info.assembly.name);
3927 /* do we need to load if it's not already loaded? */
3929 g_list_free (info.modifiers);
3930 g_list_free (info.nested);
3933 } else if (image == NULL) {
3934 image = mono_defaults.corlib;
3937 type = mono_reflection_get_type (image, &info, FALSE);
3938 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
3939 image = mono_defaults.corlib;
3940 type = mono_reflection_get_type (image, &info, FALSE);
3943 g_list_free (info.modifiers);
3944 g_list_free (info.nested);
3949 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
3951 int slen, type = t->type;
3956 case MONO_TYPE_BOOLEAN: {
3957 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
3962 case MONO_TYPE_CHAR:
3964 case MONO_TYPE_I2: {
3965 guint16 *val = g_malloc (sizeof (guint16));
3970 #if SIZEOF_VOID_P == 4
3976 case MONO_TYPE_I4: {
3977 guint32 *val = g_malloc (sizeof (guint32));
3982 #if SIZEOF_VOID_P == 8
3983 case MONO_TYPE_U: /* error out instead? this should probably not happen */
3988 case MONO_TYPE_I8: {
3989 guint64 *val = g_malloc (sizeof (guint64));
3994 case MONO_TYPE_VALUETYPE:
3995 if (t->data.klass->enumtype) {
3996 type = t->data.klass->enum_basetype->type;
3999 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
4002 case MONO_TYPE_STRING:
4003 if (*p == (char)0xFF) {
4007 slen = mono_metadata_decode_value (p, &p);
4009 return mono_string_new_len (mono_domain_get (), p, slen);
4010 case MONO_TYPE_CLASS: {
4014 slen = mono_metadata_decode_value (p, &p);
4015 n = g_memdup (p, slen + 1);
4017 t = mono_reflection_type_from_name (n, image);
4019 g_warning ("Cannot load type '%s'", n);
4022 return mono_type_get_object (mono_domain_get (), t);
4024 case MONO_TYPE_OBJECT: {
4032 } else if (subt == 0x55) {
4035 slen = mono_metadata_decode_value (p, &p);
4036 n = g_memdup (p, slen + 1);
4038 t = mono_reflection_type_from_name (n, image);
4040 g_warning ("Cannot load type '%s'", n);
4043 subc = mono_class_from_mono_type (t);
4044 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
4045 MonoType simple_type = {{0}};
4046 simple_type.type = subt;
4047 subc = mono_class_from_mono_type (&simple_type);
4049 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
4051 val = load_cattr_value (image, &subc->byval_arg, p, end);
4052 obj = mono_object_new (mono_domain_get (), subc);
4053 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
4057 case MONO_TYPE_SZARRAY:
4063 arr=mono_array_new(mono_domain_get(),mono_class_from_mono_type(t->data.type),alen);
4064 switch (t->data.type->type)
4068 case MONO_TYPE_BOOLEAN:
4069 for (i=0;i<alen;i++)
4071 MonoBoolean val=*p++;
4072 mono_array_set(arr,MonoBoolean,i,val);
4075 case MONO_TYPE_CHAR:
4078 for (i=0;i<alen;i++)
4080 guint16 val=read16(p);
4081 mono_array_set(arr,guint16,i,val);
4088 for (i=0;i<alen;i++)
4090 guint32 val=read32(p);
4091 mono_array_set(arr,guint32,i,val);
4098 for (i=0;i<alen;i++)
4100 guint64 val=read64(p);
4101 mono_array_set(arr,guint64,i,val);
4105 case MONO_TYPE_STRING:
4106 for (i=0;i<alen;i++)
4110 mono_array_set(arr,gpointer,i,NULL);
4115 slen=mono_metadata_decode_value(p,&p);
4116 mono_array_set(arr,gpointer,i,mono_string_new_len(mono_domain_get(),p,slen));
4122 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
4128 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
4134 type_is_reference (MonoType *type)
4136 switch (type->type) {
4137 case MONO_TYPE_BOOLEAN:
4138 case MONO_TYPE_CHAR:
4151 case MONO_TYPE_VALUETYPE:
4159 free_param_data (MonoMethodSignature *sig, void **params) {
4161 for (i = 0; i < sig->param_count; ++i) {
4162 if (!type_is_reference (sig->params [i]))
4163 g_free (params [i]);
4168 * Find the method index in the metadata methodDef table.
4169 * Later put these three helper methods in metadata and export them.
4172 find_method_index (MonoMethod *method) {
4173 MonoClass *klass = method->klass;
4176 for (i = 0; i < klass->method.count; ++i) {
4177 if (method == klass->methods [i])
4178 return klass->method.first + 1 + i;
4184 * Find the field index in the metadata FieldDef table.
4187 find_field_index (MonoClass *klass, MonoClassField *field) {
4190 for (i = 0; i < klass->field.count; ++i) {
4191 if (field == &klass->fields [i])
4192 return klass->field.first + 1 + i;
4198 * Find the property index in the metadata Property table.
4201 find_property_index (MonoClass *klass, MonoProperty *property) {
4204 for (i = 0; i < klass->property.count; ++i) {
4205 if (property == &klass->properties [i])
4206 return klass->property.first + 1 + i;
4212 * Find the event index in the metadata Event table.
4215 find_event_index (MonoClass *klass, MonoEvent *event) {
4218 for (i = 0; i < klass->event.count; ++i) {
4219 if (event == &klass->events [i])
4220 return klass->event.first + 1 + i;
4226 create_custom_attr (MonoImage *image, MonoMethod *method,
4227 const char *data, guint32 len)
4229 const char *p = data;
4231 guint32 i, j, num_named;
4235 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
4238 mono_class_init (method->klass);
4239 /*g_print ("got attr %s\n", method->klass->name);*/
4241 params = g_new (void*, method->signature->param_count);
4245 for (i = 0; i < method->signature->param_count; ++i) {
4246 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
4250 attr = mono_object_new (mono_domain_get (), method->klass);
4251 mono_runtime_invoke (method, attr, params, NULL);
4252 free_param_data (method->signature, params);
4254 num_named = read16 (named);
4256 for (j = 0; j < num_named; j++) {
4258 char *name, named_type;
4259 named_type = *named++;
4260 named++; /* type of data */
4261 name_len = mono_metadata_decode_blob_size (named, &named);
4262 name = g_malloc (name_len + 1);
4263 memcpy (name, named, name_len);
4264 name [name_len] = 0;
4266 if (named_type == 0x53) {
4267 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
4268 void *val = load_cattr_value (image, field->type, named, &named);
4269 mono_field_set_value (attr, field, val);
4270 if (!type_is_reference (field->type))
4272 } else if (named_type == 0x54) {
4273 MonoProperty *prop = mono_class_get_property_from_name (mono_object_class (attr), name);
4275 MonoType *prop_type;
4276 /* can we have more that 1 arg in a custom attr named property? */
4277 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
4278 pparams [0] = load_cattr_value (image, prop_type, named, &named);
4279 mono_property_set_value (prop, attr, pparams, NULL);
4280 if (!type_is_reference (prop_type))
4281 g_free (pparams [0]);
4290 attr_array_from_attr_info (CustomAttrInfo *cinfo)
4297 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
4298 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
4299 for (i = 0; i < cinfo->num_attrs; ++i) {
4300 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
4301 mono_array_set (result, gpointer, i, attr);
4307 * mono_reflection_get_custom_attrs:
4308 * @obj: a reflection object handle
4310 * Return an array with all the custom attributes defined of the
4311 * reflection handle @obj. The objects are fully build.
4314 mono_reflection_get_custom_attrs (MonoObject *obj)
4316 guint32 idx, mtoken, i, len;
4317 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
4325 MonoArray *dynamic_attrs = NULL;
4326 CustomAttrInfo *cinfo;
4328 MONO_ARCH_SAVE_REGS;
4330 klass = obj->vtable->klass;
4331 /* FIXME: need to handle: Module */
4332 if (klass == mono_defaults.monotype_class) {
4333 MonoReflectionType *rtype = (MonoReflectionType*)obj;
4334 klass = mono_class_from_mono_type (rtype->type);
4335 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
4336 return attr_array_from_attr_info (cinfo);
4337 idx = mono_metadata_token_index (klass->type_token);
4338 idx <<= CUSTOM_ATTR_BITS;
4339 idx |= CUSTOM_ATTR_TYPEDEF;
4340 image = klass->image;
4341 } else if (strcmp ("Assembly", klass->name) == 0) {
4342 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
4343 idx = 1; /* there is only one assembly */
4344 idx <<= CUSTOM_ATTR_BITS;
4345 idx |= CUSTOM_ATTR_ASSEMBLY;
4346 image = rassembly->assembly->image;
4347 } else if (strcmp ("MonoProperty", klass->name) == 0) {
4348 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
4349 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, rprop->property)))
4350 return attr_array_from_attr_info (cinfo);
4351 idx = find_property_index (rprop->klass, rprop->property);
4352 idx <<= CUSTOM_ATTR_BITS;
4353 idx |= CUSTOM_ATTR_PROPERTY;
4354 image = rprop->klass->image;
4355 } else if (strcmp ("MonoEvent", klass->name) == 0) {
4356 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
4357 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, revent->event)))
4358 return attr_array_from_attr_info (cinfo);
4359 idx = find_event_index (revent->klass, revent->event);
4360 idx <<= CUSTOM_ATTR_BITS;
4361 idx |= CUSTOM_ATTR_EVENT;
4362 image = revent->klass->image;
4363 } else if (strcmp ("MonoField", klass->name) == 0) {
4364 MonoReflectionField *rfield = (MonoReflectionField*)obj;
4365 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, rfield->field)))
4366 return attr_array_from_attr_info (cinfo);
4367 idx = find_field_index (rfield->klass, rfield->field);
4368 idx <<= CUSTOM_ATTR_BITS;
4369 idx |= CUSTOM_ATTR_FIELDDEF;
4370 image = rfield->klass->image;
4371 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
4372 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
4373 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, rmethod->method)))
4374 return attr_array_from_attr_info (cinfo);
4375 idx = find_method_index (rmethod->method);
4376 idx <<= CUSTOM_ATTR_BITS;
4377 idx |= CUSTOM_ATTR_METHODDEF;
4378 image = rmethod->method->klass->image;
4379 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
4380 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
4381 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
4382 guint32 method_index = find_method_index (rmethod->method);
4383 guint32 param_list, param_last, param_pos, found;
4385 /* FIXME: handle dynamic custom attrs for parameters */
4386 image = rmethod->method->klass->image;
4387 ca = &image->tables [MONO_TABLE_METHOD];
4389 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
4390 if (method_index == ca->rows) {
4391 ca = &image->tables [MONO_TABLE_PARAM];
4392 param_last = ca->rows + 1;
4394 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
4395 ca = &image->tables [MONO_TABLE_PARAM];
4398 for (i = param_list; i < param_last; ++i) {
4399 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
4400 if (param_pos == param->PositionImpl) {
4406 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
4408 idx <<= CUSTOM_ATTR_BITS;
4409 idx |= CUSTOM_ATTR_PARAMDEF;
4410 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
4411 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
4412 dynamic_attrs = assemblyb->cattrs;
4414 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
4415 } else { /* handle other types here... */
4416 g_error ("get custom attrs not yet supported for %s", klass->name);
4419 if (dynamic_attrs) {
4420 len = mono_array_length (dynamic_attrs);
4421 for (i = 0; i < len; ++i) {
4422 MonoReflectionCustomAttr *cattr = (MonoReflectionCustomAttr*)mono_array_get (dynamic_attrs, gpointer, i);
4423 attr = create_custom_attr (image, cattr->ctor->method, mono_array_addr (cattr->data, int, 0), mono_array_length (cattr->data));
4424 list = g_list_prepend (list, attr);
4427 /* at this point image and index are set correctly for searching the custom attr */
4428 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4429 /* the table is not sorted */
4430 for (i = 0; i < ca->rows; ++i) {
4431 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
4432 if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
4434 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
4435 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
4436 case CUSTOM_ATTR_TYPE_METHODDEF:
4437 mtoken |= MONO_TOKEN_METHOD_DEF;
4439 case CUSTOM_ATTR_TYPE_MEMBERREF:
4440 mtoken |= MONO_TOKEN_MEMBER_REF;
4443 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
4446 method = mono_get_method (image, mtoken, NULL);
4448 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
4452 const char *data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
4453 data_len = mono_metadata_decode_value (data, &data);
4455 attr = create_custom_attr (image, method, data, data_len);
4457 list = g_list_prepend (list, attr);
4461 len = g_list_length (list);
4463 * The return type is really object[], but System/Attribute.cs does a cast
4464 * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
4465 * probably fix that.
4467 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
4468 result = mono_array_new (mono_domain_get (), klass, len);
4469 for (i = 0; i < len; ++i) {
4470 mono_array_set (result, gpointer, i, list->data);
4473 g_list_free (g_list_first (list));
4478 static MonoMethodSignature*
4479 parameters_to_signature (MonoArray *parameters) {
4480 MonoMethodSignature *sig;
4483 count = parameters? mono_array_length (parameters): 0;
4485 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
4486 sig->param_count = count;
4487 sig->sentinelpos = -1; /* FIXME */
4488 for (i = 0; i < count; ++i) {
4489 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
4490 sig->params [i] = pt->type;
4495 static MonoMethodSignature*
4496 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
4497 MonoMethodSignature *sig;
4499 sig = parameters_to_signature (ctor->parameters);
4500 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4501 sig->ret = &mono_defaults.void_class->byval_arg;
4505 static MonoMethodSignature*
4506 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
4507 MonoMethodSignature *sig;
4509 sig = parameters_to_signature (method->parameters);
4510 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4511 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
4516 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
4518 MonoClass *klass = mono_object_class (prop);
4519 if (strcmp (klass->name, "PropertyBuilder") == 0) {
4520 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
4521 *name = mono_string_to_utf8 (pb->name);
4522 *type = pb->type->type;
4524 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
4525 *name = g_strdup (p->property->name);
4526 if (p->property->get)
4527 *type = p->property->get->signature->ret;
4529 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
4534 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
4536 MonoClass *klass = mono_object_class (field);
4537 if (strcmp (klass->name, "FieldBuilder") == 0) {
4538 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
4539 *name = mono_string_to_utf8 (fb->name);
4540 *type = fb->type->type;
4542 MonoReflectionField *f = (MonoReflectionField *)field;
4543 *name = g_strdup (f->field->name);
4544 *type = f->field->type;
4549 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
4550 char *name, *result;
4554 name = mono_type_get_name (type);
4555 klass = my_mono_class_from_mono_type (type);
4556 ta = klass->image->assembly;
4557 if (ta == ass || klass->image == mono_defaults.corlib)
4560 /* missing public key */
4561 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
4562 name, ta->aname.name,
4563 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
4564 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
4570 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
4573 MonoTypeEnum simple_type;
4575 if ((p-buffer) + 10 >= *buflen) {
4578 newbuf = g_realloc (buffer, *buflen);
4579 p = newbuf + (p-buffer);
4582 argval = ((char*)arg + sizeof (MonoObject));
4583 simple_type = type->type;
4585 switch (simple_type) {
4586 case MONO_TYPE_BOOLEAN:
4591 case MONO_TYPE_CHAR:
4594 swap_with_size (p, argval, 2, 1);
4600 swap_with_size (p, argval, 4, 1);
4606 swap_with_size (p, argval, 8, 1);
4609 case MONO_TYPE_VALUETYPE:
4610 if (type->data.klass->enumtype) {
4611 simple_type = type->data.klass->enum_basetype->type;
4614 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
4617 case MONO_TYPE_STRING: {
4624 str = mono_string_to_utf8 ((MonoString*)arg);
4625 slen = strlen (str);
4626 if ((p-buffer) + 10 + slen >= *buflen) {
4630 newbuf = g_realloc (buffer, *buflen);
4631 p = newbuf + (p-buffer);
4634 mono_metadata_encode_value (slen, p, &p);
4635 memcpy (p, str, slen);
4640 case MONO_TYPE_CLASS: {
4643 MonoClass *k = mono_object_class (arg);
4644 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
4645 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
4646 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
4648 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
4649 slen = strlen (str);
4650 if ((p-buffer) + 10 + slen >= *buflen) {
4654 newbuf = g_realloc (buffer, *buflen);
4655 p = newbuf + (p-buffer);
4658 mono_metadata_encode_value (slen, p, &p);
4659 memcpy (p, str, slen);
4664 /* it may be a boxed value or a Type */
4665 case MONO_TYPE_OBJECT: {
4666 MonoClass *klass = mono_object_class (arg);
4670 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
4673 } else if (klass->enumtype) {
4675 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
4676 *p++ = simple_type = klass->byval_arg.type;
4679 g_error ("unhandled type in custom attr");
4681 str = type_get_qualified_name (klass->enum_basetype, NULL);
4682 slen = strlen (str);
4683 if ((p-buffer) + 10 + slen >= *buflen) {
4687 newbuf = g_realloc (buffer, *buflen);
4688 p = newbuf + (p-buffer);
4691 mono_metadata_encode_value (slen, p, &p);
4692 memcpy (p, str, slen);
4695 simple_type = klass->enum_basetype->type;
4699 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
4702 *retbuffer = buffer;
4706 * mono_reflection_get_custom_attrs_blob:
4707 * @ctor: custom attribute constructor
4708 * @ctorArgs: arguments o the constructor
4714 * Creates the blob of data that needs to be saved in the metadata and that represents
4715 * the custom attributed described by @ctor, @ctorArgs etc.
4716 * Returns: a Byte array representing the blob of data.
4719 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
4722 MonoMethodSignature *sig;
4727 MONO_ARCH_SAVE_REGS;
4729 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4730 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
4732 sig = ((MonoReflectionMethod*)ctor)->method->signature;
4735 p = buffer = g_malloc (buflen);
4736 /* write the prolog */
4739 for (i = 0; i < sig->param_count; ++i) {
4740 if (sig->params[i]->type==MONO_TYPE_SZARRAY)
4742 guint32 alen=mono_array_length(ctorArgs) - i;
4744 if ((p-buffer) + 10 >= buflen) {
4747 newbuf = g_realloc (buffer, buflen);
4748 p = newbuf + (p-buffer);
4752 *p++=(alen>>8)&0xff;
4753 *p++=(alen>>16)&0xff;
4754 *p++=(alen>>24)&0xff;
4755 for (j=0;j<alen;j++)
4757 arg=(MonoObject*)mono_array_get(ctorArgs,gpointer,i+j);
4758 encode_cattr_value(buffer,p,&buffer,&p,&buflen,sig->params[i]->data.type,arg);
4763 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
4764 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
4769 i += mono_array_length (properties);
4771 i += mono_array_length (fields);
4773 *p++ = (i >> 8) & 0xff;
4776 for (i = 0; i < mono_array_length (properties); ++i) {
4781 prop = mono_array_get (properties, gpointer, i);
4782 get_prop_name_and_type (prop, &pname, &ptype);
4783 *p++ = 0x54; /* PROPERTY signature */
4784 mono_metadata_encode_value (ptype->type, p, &p);
4785 len = strlen (pname);
4786 mono_metadata_encode_value (len, p, &p);
4787 memcpy (p, pname, len);
4789 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
4796 for (i = 0; i < mono_array_length (fields); ++i) {
4801 field = mono_array_get (fields, gpointer, i);
4802 get_field_name_and_type (field, &fname, &ftype);
4803 *p++ = 0x53; /* FIELD signature */
4804 mono_metadata_encode_value (ftype->type, p, &p);
4805 len = strlen (fname);
4806 mono_metadata_encode_value (len, p, &p);
4807 memcpy (p, fname, len);
4809 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
4814 g_assert (p - buffer <= buflen);
4815 buflen = p - buffer;
4816 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
4817 p = mono_array_addr (result, char, 0);
4818 memcpy (p, buffer, buflen);
4820 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
4826 * mono_reflection_setup_internal_class:
4827 * @tb: a TypeBuilder object
4829 * Creates a MonoClass that represents the TypeBuilder.
4830 * This is a trick that lets us simplify a lot of reflection code
4831 * (and will allow us to support Build and Run assemblies easier).
4834 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
4836 MonoClass *klass, *parent;
4838 MONO_ARCH_SAVE_REGS;
4840 klass = g_new0 (MonoClass, 1);
4842 klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
4845 /* check so we can compile corlib correctly */
4846 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
4847 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
4848 parent = tb->parent->type->data.klass;
4850 parent = my_mono_class_from_mono_type (tb->parent->type);
4854 klass->inited = 1; /* we lie to the runtime */
4855 klass->name = mono_string_to_utf8 (tb->name);
4856 klass->name_space = mono_string_to_utf8 (tb->nspace);
4857 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
4858 klass->flags = tb->attrs;
4860 klass->element_class = klass;
4861 klass->reflection_info = tb; /* need to pin. */
4863 /* Put into cache so mono_class_get () will find it */
4864 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
4867 mono_g_hash_table_insert (tb->module->assemblyb->dynamic_assembly->tokens,
4868 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
4872 mono_class_setup_parent (klass, parent);
4873 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
4874 const char *old_n = klass->name;
4875 /* trick to get relative numbering right when compiling corlib */
4876 klass->name = "BuildingObject";
4877 mono_class_setup_parent (klass, mono_defaults.object_class);
4878 klass->name = old_n;
4880 mono_class_setup_mono_type (klass);
4883 * FIXME: handle interfaces.
4886 tb->type.type = &klass->byval_arg;
4888 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
4892 * mono_reflection_create_internal_class:
4893 * @tb: a TypeBuilder object
4895 * Actually create the MonoClass that is associated with the TypeBuilder.
4898 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
4902 MONO_ARCH_SAVE_REGS;
4904 klass = my_mono_class_from_mono_type (tb->type.type);
4906 if (klass->enumtype && klass->enum_basetype == NULL) {
4907 MonoReflectionFieldBuilder *fb;
4909 g_assert (tb->fields != NULL);
4910 g_assert (mono_array_length (tb->fields) >= 1);
4912 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
4914 klass->enum_basetype = fb->type->type;
4915 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
4916 if (!klass->element_class)
4917 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
4918 klass->instance_size = klass->element_class->instance_size;
4919 klass->size_inited = 1;
4921 * this is almost safe to do with enums and it's needed to be able
4922 * to create objects of the enum type (for use in SetConstant).
4924 /* FIXME: Does this mean enums can't have method overrides ? */
4925 mono_class_setup_vtable (klass, NULL, 0);
4930 reflection_methodbuilder_to_mono_method (MonoClass *klass,
4931 ReflectionMethodBuilder *rmb,
4932 MonoMethodSignature *sig)
4935 MonoMethodNormal *pm;
4937 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
4938 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
4939 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
4941 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
4943 pm = (MonoMethodNormal*)m;
4946 m->flags = rmb->attrs;
4947 m->iflags = rmb->iattrs;
4948 m->name = mono_string_to_utf8 (rmb->name);
4951 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
4953 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
4954 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
4957 m->addr = mono_lookup_internal_call (m);
4958 m->signature->pinvoke = 1;
4959 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
4961 m->signature->pinvoke = 1;
4963 } else if (!m->klass->dummy &&
4964 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
4965 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
4966 MonoMethodHeader *header;
4968 gint32 max_stack, i;
4969 gint32 num_locals = 0;
4970 gint32 num_clauses = 0;
4974 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
4975 code_size = rmb->ilgen->code_len;
4976 max_stack = rmb->ilgen->max_stack;
4977 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
4978 if (rmb->ilgen->ex_handlers)
4979 num_clauses = method_count_clauses (rmb->ilgen);
4982 code = mono_array_addr (rmb->code, guint8, 0);
4983 code_size = mono_array_length (rmb->code);
4984 /* we probably need to run a verifier on the code... */
4994 header = g_malloc0 (sizeof (MonoMethodHeader) +
4995 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
4996 header->code_size = code_size;
4997 header->code = g_malloc (code_size);
4998 memcpy ((char*)header->code, code, code_size);
4999 header->max_stack = max_stack;
5000 header->init_locals = rmb->init_locals;
5001 header->num_locals = num_locals;
5003 for (i = 0; i < num_locals; ++i) {
5004 MonoReflectionLocalBuilder *lb =
5005 mono_array_get (rmb->ilgen->locals,
5006 MonoReflectionLocalBuilder*, i);
5008 header->locals [i] = g_new0 (MonoType, 1);
5009 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
5012 header->num_clauses = num_clauses;
5014 header->clauses = method_encode_clauses (klass->image->assembly->dynamic,
5019 pm->header = header;
5026 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
5028 ReflectionMethodBuilder rmb;
5030 MonoMethodSignature *sig;
5032 name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
5034 sig = ctor_builder_to_signature (mb);
5036 rmb.ilgen = mb->ilgen;
5037 rmb.parameters = mb->parameters;
5038 rmb.pinfo = mb->pinfo;
5039 rmb.attrs = mb->attrs | METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
5040 rmb.iattrs = mb->iattrs;
5041 rmb.call_conv = mb->call_conv;
5042 rmb.type = mb->type;
5043 rmb.name = mono_string_new (mono_domain_get (), name);
5044 rmb.table_idx = &mb->table_idx;
5045 rmb.init_locals = mb->init_locals;
5048 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
5049 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
5054 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
5056 ReflectionMethodBuilder rmb;
5057 MonoMethodSignature *sig;
5059 sig = method_builder_to_signature (mb);
5061 rmb.ilgen = mb->ilgen;
5062 rmb.parameters = mb->parameters;
5063 rmb.pinfo = mb->pinfo;
5064 rmb.attrs = mb->attrs;
5065 rmb.iattrs = mb->iattrs;
5066 rmb.call_conv = mb->call_conv;
5067 rmb.type = mb->type;
5068 rmb.name = mb->name;
5069 rmb.table_idx = &mb->table_idx;
5070 rmb.init_locals = mb->init_locals;
5071 rmb.code = mb->code;
5073 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
5074 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
5079 ensure_runtime_vtable (MonoClass *klass)
5081 MonoReflectionTypeBuilder *tb = klass->reflection_info;
5082 int i, num, j, onum;
5083 MonoMethod **overrides;
5085 if (!tb || klass->wastypebuilder)
5088 ensure_runtime_vtable (klass->parent);
5090 num = tb->ctors? mono_array_length (tb->ctors): 0;
5091 num += tb->methods? mono_array_length (tb->methods): 0;
5092 klass->method.count = num;
5093 klass->methods = g_new (MonoMethod*, num);
5094 num = tb->ctors? mono_array_length (tb->ctors): 0;
5095 for (i = 0; i < num; ++i)
5096 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
5097 num = tb->methods? mono_array_length (tb->methods): 0;
5099 for (i = 0; i < num; ++i)
5100 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
5102 klass->wastypebuilder = TRUE;
5103 if (tb->interfaces) {
5104 klass->interface_count = mono_array_length (tb->interfaces);
5105 klass->interfaces = g_new (MonoClass*, klass->interface_count);
5106 for (i = 0; i < klass->interface_count; ++i) {
5107 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
5108 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
5115 for (i = 0; i < mono_array_length (tb->methods); ++i) {
5116 MonoReflectionMethodBuilder *mb =
5117 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
5118 if (mb->override_method)
5123 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
5127 for (i = 0; i < mono_array_length (tb->methods); ++i) {
5128 MonoReflectionMethodBuilder *mb =
5129 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
5130 if (mb->override_method) {
5131 /* FIXME: What if 'override_method' is a MethodBuilder ? */
5132 overrides [onum * 2] =
5133 mb->override_method->method;
5134 overrides [onum * 2 + 1] =
5137 g_assert (mb->mhandle);
5144 mono_class_setup_vtable (klass, overrides, onum);
5148 typebuilder_setup_fields (MonoClass *klass)
5150 MonoReflectionTypeBuilder *tb = klass->reflection_info;
5151 MonoReflectionFieldBuilder *fb;
5152 MonoClassField *field;
5155 klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
5157 if (!klass->field.count)
5160 klass->fields = g_new0 (MonoClassField, klass->field.count);
5162 for (i = 0; i < klass->field.count; ++i) {
5163 fb = mono_array_get (tb->fields, gpointer, i);
5164 field = &klass->fields [i];
5165 field->name = mono_string_to_utf8 (fb->name);
5167 /* FIXME: handle type modifiers */
5168 field->type = g_memdup (fb->type->type, sizeof (MonoType));
5169 field->type->attrs = fb->attrs;
5171 field->type = fb->type->type;
5173 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
5174 field->data = mono_array_addr (fb->rva_data, char, 0);
5175 if (fb->offset != -1)
5176 field->offset = fb->offset;
5177 field->parent = klass;
5179 mono_save_custom_attrs (klass->image, field, fb->cattrs);
5181 mono_class_layout_fields (klass);
5185 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
5188 MonoReflectionType* res;
5190 MONO_ARCH_SAVE_REGS;
5192 klass = my_mono_class_from_mono_type (tb->type.type);
5194 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
5197 * Fields to set in klass:
5198 * the various flags: delegate/unicode/contextbound etc.
5203 klass->flags = tb->attrs;
5204 klass->element_class = klass;
5206 /* enums are done right away */
5207 if (!klass->enumtype)
5208 ensure_runtime_vtable (klass);
5210 /* fields and object layout */
5211 if (klass->parent) {
5212 if (!klass->parent->size_inited)
5213 mono_class_init (klass->parent);
5214 klass->instance_size += klass->parent->instance_size;
5215 klass->class_size += klass->parent->class_size;
5216 klass->min_align = klass->parent->min_align;
5218 klass->instance_size = sizeof (MonoObject);
5219 klass->min_align = 1;
5222 if (tb->nesting_type) {
5223 g_assert (tb->nesting_type->type);
5224 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
5227 /* FIXME: handle packing_size and instance_size */
5228 typebuilder_setup_fields (klass);
5230 /* FIXME: properties */
5232 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5233 /* with enums res == tb: need to fix that. */
5234 if (!klass->enumtype)
5235 g_assert (res != (MonoReflectionType*)tb);
5240 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
5242 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5243 guint32 na = mono_array_length (sig->arguments);
5248 MONO_ARCH_SAVE_REGS;
5250 p = buf = g_malloc (10 + na * 10);
5252 mono_metadata_encode_value (0x07, p, &p);
5253 mono_metadata_encode_value (na, p, &p);
5254 for (i = 0; i < na; ++i) {
5255 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5256 encode_reflection_type (assembly, type, p, &p);
5260 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5261 p = mono_array_addr (result, char, 0);
5262 memcpy (p, buf, buflen);
5269 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
5271 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5272 guint32 na = mono_array_length (sig->arguments);
5277 MONO_ARCH_SAVE_REGS;
5279 p = buf = g_malloc (10 + na * 10);
5281 mono_metadata_encode_value (0x06, p, &p);
5282 for (i = 0; i < na; ++i) {
5283 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5284 encode_reflection_type (assembly, type, p, &p);
5288 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5289 p = mono_array_addr (result, char, 0);
5290 memcpy (p, buf, buflen);
5297 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
5299 MonoDynamicAssembly *assembly = image->assembly->dynamic;
5303 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5306 if (strcmp (obj->vtable->klass->name, "String") == 0) {
5310 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
5311 MonoReflectionType *tb = (MonoReflectionType*)obj;
5312 result = mono_class_from_mono_type (tb->type);
5315 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
5316 result = ((MonoReflectionMethod*)obj)->method;
5319 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
5320 result = ((MonoReflectionMethod*)obj)->method;
5323 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
5324 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
5325 result = mb->mhandle;
5327 /* Type is not yet created */
5328 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5330 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5333 * Hopefully this has been filled in by calling CreateType() on the
5337 * TODO: This won't work if the application finishes another
5338 * TypeBuilder instance instead of this one.
5340 result = mb->mhandle;
5343 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
5344 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
5346 result = cb->mhandle;
5348 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
5350 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5351 result = cb->mhandle;
5354 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
5355 result = ((MonoReflectionField*)obj)->field;
5358 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
5359 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
5360 result = fb->handle;
5363 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
5365 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5366 result = fb->handle;
5369 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
5370 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
5373 klass = tb->type.type->data.klass;
5374 if (klass->wastypebuilder) {
5375 /* Already created */
5379 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5380 result = tb->type.type->data.klass;
5384 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
5385 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
5386 MonoMethodSignature *sig;
5389 if (helper->arguments)
5390 nargs = mono_array_length (helper->arguments);
5394 sig = mono_metadata_signature_alloc (image, nargs);
5395 sig->explicit_this = helper->call_conv & 64;
5396 sig->hasthis = helper->call_conv & 32;
5398 if (helper->call_conv == 0) /* unmanaged */
5399 sig->call_convention = helper->unmanaged_call_conv - 1;
5401 if (helper->call_conv & 0x02)
5402 sig->call_convention = MONO_CALL_VARARG;
5404 sig->call_convention = MONO_CALL_DEFAULT;
5406 sig->param_count = nargs;
5407 /* TODO: Copy type ? */
5408 sig->ret = helper->return_type->type;
5409 for (i = 0; i < nargs; ++i) {
5410 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
5411 sig->params [i] = rt->type;
5417 g_print (obj->vtable->klass->name);
5418 g_assert_not_reached ();