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;
52 } ReflectionMethodBuilder;
54 const unsigned char table_sizes [64] = {
64 MONO_INTERFACEIMPL_SIZE,
65 MONO_MEMBERREF_SIZE, /* 0x0A */
67 MONO_CUSTOM_ATTR_SIZE,
68 MONO_FIELD_MARSHAL_SIZE,
69 MONO_DECL_SECURITY_SIZE,
70 MONO_CLASS_LAYOUT_SIZE,
71 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
72 MONO_STAND_ALONE_SIGNATURE_SIZE,
76 MONO_PROPERTY_MAP_SIZE,
79 MONO_METHOD_SEMA_SIZE,
81 MONO_MODULEREF_SIZE, /* 0x1A */
87 MONO_ASSEMBLY_SIZE, /* 0x20 */
88 MONO_ASSEMBLY_PROCESSOR_SIZE,
90 MONO_ASSEMBLYREF_SIZE,
91 MONO_ASSEMBLYREFPROC_SIZE,
92 MONO_ASSEMBLYREFOS_SIZE,
96 MONO_NESTED_CLASS_SIZE,
100 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
101 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
102 static guint32 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper);
103 static guint32 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo);
106 alloc_table (MonoDynamicTable *table, guint nrows)
109 g_assert (table->columns);
110 table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
114 string_heap_insert (MonoDynamicStream *sh, const char *str)
118 gpointer oldkey, oldval;
120 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
121 return GPOINTER_TO_UINT (oldval);
123 len = strlen (str) + 1;
125 if (idx + len > sh->alloc_size) {
126 sh->alloc_size += len + 4096;
127 sh->data = g_realloc (sh->data, sh->alloc_size);
130 * We strdup the string even if we already copy them in sh->data
131 * so that the string pointers in the hash remain valid even if
132 * we need to realloc sh->data. We may want to avoid that later.
134 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
135 memcpy (sh->data + idx, str, len);
141 string_heap_init (MonoDynamicStream *sh)
144 sh->alloc_size = 4096;
145 sh->data = g_malloc (4096);
146 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
147 string_heap_insert (sh, "");
150 #if 0 /* never used */
152 string_heap_free (MonoDynamicStream *sh)
155 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
156 g_hash_table_destroy (sh->hash);
161 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
164 if (stream->alloc_size < stream->index + len) {
165 stream->alloc_size += len + 4096;
166 stream->data = g_realloc (stream->data, stream->alloc_size);
168 memcpy (stream->data + stream->index, data, len);
170 stream->index += len;
172 * align index? Not without adding an additional param that controls it since
173 * we may store a blob value in pieces.
179 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
182 if (stream->alloc_size < stream->index + len) {
183 stream->alloc_size += len + 4096;
184 stream->data = g_realloc (stream->data, stream->alloc_size);
186 memset (stream->data + stream->index, 0, len);
188 stream->index += len;
193 stream_data_align (MonoDynamicStream *stream)
196 guint32 count = stream->index % 4;
198 /* we assume the stream data will be aligned */
200 mono_image_add_stream_data (stream, buf, 4 - count);
204 mono_blob_entry_hash (const char* str)
208 len = mono_metadata_decode_blob_size (str, &str);
211 for (str += 1; str < end; str++)
212 h = (h << 5) - h + *str;
217 mono_blob_entry_equal (const char *str1, const char *str2) {
221 len = mono_metadata_decode_blob_size (str1, &end1);
222 len2 = mono_metadata_decode_blob_size (str2, &end2);
225 return memcmp (end1, end2, len) == 0;
229 add_to_blob_cached (MonoDynamicAssembly *assembly, char *b1, int s1, char *b2, int s2)
233 gpointer oldkey, oldval;
235 copy = g_malloc (s1+s2);
236 memcpy (copy, b1, s1);
237 memcpy (copy + s1, b2, s2);
238 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
240 idx = GPOINTER_TO_UINT (oldval);
242 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
243 mono_image_add_stream_data (&assembly->blob, b2, s2);
244 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
249 /* modified version needed to handle building corlib */
251 my_mono_class_from_mono_type (MonoType *type) {
252 switch (type->type) {
253 case MONO_TYPE_ARRAY:
255 case MONO_TYPE_SZARRAY:
256 return mono_class_from_mono_type (type);
258 /* should be always valid when we reach this case... */
259 return type->data.klass;
264 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
267 g_assert_not_reached ();
272 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
276 case MONO_TYPE_BOOLEAN:
290 case MONO_TYPE_STRING:
291 case MONO_TYPE_OBJECT:
292 case MONO_TYPE_TYPEDBYREF:
293 mono_metadata_encode_value (type->type, p, &p);
296 case MONO_TYPE_SZARRAY:
297 mono_metadata_encode_value (type->type, p, &p);
298 encode_type (assembly, type->data.type, p, &p);
300 case MONO_TYPE_VALUETYPE:
301 case MONO_TYPE_CLASS:
302 mono_metadata_encode_value (type->type, p, &p);
303 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
306 case MONO_TYPE_VALUETYPE:
307 case MONO_TYPE_CLASS: {
308 MonoClass *k = mono_class_from_mono_type (type);
309 mono_metadata_encode_value (type->type, p, &p);
310 /* ensure only non-byref gets passed to mono_image_typedef_or_ref() */
311 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
315 case MONO_TYPE_ARRAY:
316 mono_metadata_encode_value (type->type, p, &p);
317 encode_type (assembly, type->data.array->type, p, &p);
318 mono_metadata_encode_value (type->data.array->rank, p, &p);
319 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
320 mono_metadata_encode_value (0, p, &p);
323 g_error ("need to encode type %x", type->type);
329 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
332 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
336 encode_type (assembly, type->type, p, endbuf);
340 g_assert_not_reached ();
345 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
350 guint32 nparams = sig->param_count;
351 guint32 size = 10 + nparams * 10;
356 p = buf = g_malloc (size);
358 * FIXME: vararg, explicit_this, differenc call_conv values...
360 *p = sig->call_convention;
362 *p |= 0x20; /* hasthis */
364 mono_metadata_encode_value (nparams, p, &p);
365 encode_type (assembly, sig->ret, p, &p);
366 for (i = 0; i < nparams; ++i)
367 encode_type (assembly, sig->params [i], p, &p);
369 g_assert (p - buf < size);
370 mono_metadata_encode_value (p-buf, b, &b);
371 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
377 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
380 * FIXME: reuse code from method_encode_signature().
385 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
386 guint32 size = 10 + nparams * 10;
391 p = buf = g_malloc (size);
392 /* LAMESPEC: all the call conv spec is foobared */
393 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
394 if (mb->call_conv & 2)
395 *p |= 0x5; /* vararg */
396 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
397 *p |= 0x20; /* hasthis */
399 mono_metadata_encode_value (nparams, p, &p);
400 encode_reflection_type (assembly, mb->rtype, p, &p);
401 for (i = 0; i < nparams; ++i) {
402 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
403 encode_reflection_type (assembly, pt, p, &p);
406 g_assert (p - buf < size);
407 mono_metadata_encode_value (p-buf, b, &b);
408 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
414 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
416 MonoDynamicTable *table;
419 guint32 idx, sig_idx, size;
420 guint nl = mono_array_length (ilgen->locals);
427 p = buf = g_malloc (size);
428 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
429 idx = table->next_idx ++;
431 alloc_table (table, table->rows);
432 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
434 mono_metadata_encode_value (0x07, p, &p);
435 mono_metadata_encode_value (nl, p, &p);
436 for (i = 0; i < nl; ++i) {
437 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
438 encode_reflection_type (assembly, lb->type, p, &p);
440 g_assert (p - buf < size);
441 mono_metadata_encode_value (p-buf, b, &b);
442 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
445 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
451 method_count_clauses (MonoReflectionILGen *ilgen)
453 guint32 num_clauses = 0;
456 MonoILExceptionInfo *ex_info;
457 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
458 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
459 if (ex_info->handlers)
460 num_clauses += mono_array_length (ex_info->handlers);
468 static MonoExceptionClause*
469 method_encode_clauses (MonoDynamicAssembly *assembly,
470 MonoReflectionILGen *ilgen, guint32 num_clauses)
472 MonoExceptionClause *clauses;
473 MonoExceptionClause *clause;
474 MonoILExceptionInfo *ex_info;
475 MonoILExceptionBlock *ex_block;
476 guint32 finally_start;
477 int i, j, clause_index;;
479 clauses = g_new0 (MonoExceptionClause, num_clauses);
482 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
483 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
484 finally_start = ex_info->start + ex_info->len;
485 g_assert (ex_info->handlers);
486 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
487 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
488 clause = &(clauses [clause_index]);
490 clause->flags = ex_block->type;
491 clause->try_offset = ex_info->start;
493 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
494 clause->try_len = finally_start - ex_info->start;
496 clause->try_len = ex_info->len;
497 clause->handler_offset = ex_block->start;
498 clause->handler_len = ex_block->len;
499 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
500 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
501 if (ex_block->extype) {
502 mono_g_hash_table_insert (assembly->tokens,
503 GUINT_TO_POINTER (clause->token_or_filter),
506 finally_start = ex_block->start + ex_block->len;
516 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
522 gint32 num_locals = 0;
523 gint32 num_exception = 0;
526 char fat_header [12];
529 guint32 local_sig = 0;
530 guint32 header_size = 12;
533 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
534 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
535 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
536 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
540 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
542 code = mb->ilgen->code;
543 code_size = mb->ilgen->code_len;
544 max_stack = mb->ilgen->max_stack;
545 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
546 if (mb->ilgen->ex_handlers)
547 num_exception = method_count_clauses (mb->ilgen);
550 code_size = mono_array_length (code);
551 max_stack = 8; /* we probably need to run a verifier on the code... */
554 /* check for exceptions, maxstack, locals */
555 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
557 if (code_size < 64 && !(code_size & 1)) {
558 flags = (code_size << 2) | 0x2;
559 } else if (code_size < 32 && (code_size & 1)) {
560 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
564 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
565 /* add to the fixup todo list */
566 if (mb->ilgen && mb->ilgen->num_token_fixups)
567 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
568 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
569 return assembly->text_rva + idx;
573 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
575 * FIXME: need to set also the header size in fat_flags.
576 * (and more sects and init locals flags)
580 fat_flags |= METHOD_HEADER_MORE_SECTS;
582 fat_flags |= METHOD_HEADER_INIT_LOCALS;
583 fat_header [0] = fat_flags;
584 fat_header [1] = (header_size / 4 ) << 4;
585 shortp = (guint16*)(fat_header + 2);
586 *shortp = GUINT16_TO_LE (max_stack);
587 intp = (guint32*)(fat_header + 4);
588 *intp = GUINT32_TO_LE (code_size);
589 intp = (guint32*)(fat_header + 8);
590 *intp = GUINT32_TO_LE (local_sig);
591 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
592 /* add to the fixup todo list */
593 if (mb->ilgen && mb->ilgen->num_token_fixups)
594 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
596 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
598 unsigned char sheader [4];
599 MonoExceptionClause clause;
600 MonoILExceptionInfo * ex_info;
601 MonoILExceptionBlock * ex_block;
604 stream_data_align (&assembly->code);
605 /* always use fat format for now */
606 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
607 num_exception *= sizeof (MonoExceptionClause);
608 num_exception += 4; /* include the size of the header */
609 sheader [1] = num_exception & 0xff;
610 sheader [2] = (num_exception >> 8) & 0xff;
611 sheader [3] = (num_exception >> 16) & 0xff;
612 mono_image_add_stream_data (&assembly->code, sheader, 4);
613 /* fat header, so we are already aligned */
615 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
616 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
617 if (ex_info->handlers) {
618 int finally_start = ex_info->start + ex_info->len;
619 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
620 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
621 clause.flags = GUINT32_TO_LE (ex_block->type);
622 clause.try_offset = GUINT32_TO_LE (ex_info->start);
623 /* need fault, too, probably */
624 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
625 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
627 clause.try_len = GUINT32_TO_LE (ex_info->len);
628 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
629 clause.handler_len = GUINT32_TO_LE (ex_block->len);
630 finally_start = ex_block->start + ex_block->len;
631 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
632 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
633 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
634 /*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",
635 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);*/
636 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
639 g_error ("No clauses for ex info block %d", i);
643 return assembly->text_rva + idx;
647 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 token)
650 MonoDynamicTable *table;
653 table = &assembly->tables [table_idx];
655 g_assert (col < table->columns);
657 values = table->values + table->columns;
658 for (i = 1; i <= table->rows; ++i) {
659 if (values [col] == token)
661 values += table->columns;
667 * idx is the table index of the object
668 * type is one of CUSTOM_ATTR_*
671 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
673 MonoDynamicTable *table;
674 MonoReflectionCustomAttr *cattr;
676 guint32 count, i, token;
680 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
683 count = mono_array_length (cattrs);
684 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
685 table->rows += count;
686 alloc_table (table, table->rows);
687 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
688 idx <<= CUSTOM_ATTR_BITS;
690 for (i = 0; i < count; ++i) {
691 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
692 values [MONO_CUSTOM_ATTR_PARENT] = idx;
693 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
694 type = mono_metadata_token_index (token);
695 type <<= CUSTOM_ATTR_TYPE_BITS;
696 switch (mono_metadata_token_table (token)) {
697 case MONO_TABLE_METHOD:
698 type |= CUSTOM_ATTR_TYPE_METHODDEF;
700 case MONO_TABLE_MEMBERREF:
701 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
704 g_warning ("got wrong token in custom attr");
707 values [MONO_CUSTOM_ATTR_TYPE] = type;
709 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
710 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
711 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
712 values += MONO_CUSTOM_ATTR_SIZE;
718 * Fill in the MethodDef and ParamDef tables for a method.
719 * This is used for both normal methods and constructors.
722 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
724 MonoDynamicTable *table;
729 /* room in this table is already allocated */
730 table = &assembly->tables [MONO_TABLE_METHOD];
731 *mb->table_idx = table->next_idx ++;
732 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
734 name = mono_string_to_utf8 (mb->name);
735 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
737 } else { /* a constructor */
738 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
740 values [MONO_METHOD_FLAGS] = mb->attrs;
741 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
742 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
743 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
745 table = &assembly->tables [MONO_TABLE_PARAM];
746 values [MONO_METHOD_PARAMLIST] = table->next_idx;
749 MonoDynamicTable *mtable;
752 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
753 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
756 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
757 if (mono_array_get (mb->pinfo, gpointer, i))
760 table->rows += count;
761 alloc_table (table, table->rows);
762 values = table->values + table->next_idx * MONO_PARAM_SIZE;
763 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
764 MonoReflectionParamBuilder *pb;
765 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
766 values [MONO_PARAM_FLAGS] = pb->attrs;
767 values [MONO_PARAM_SEQUENCE] = i;
768 if (pb->name != NULL) {
769 name = mono_string_to_utf8 (pb->name);
770 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
774 values [MONO_PARAM_NAME] = 0;
775 values += MONO_PARAM_SIZE;
776 if (pb->marshal_info) {
778 alloc_table (mtable, mtable->rows);
779 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
780 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
781 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
783 pb->table_idx = table->next_idx++;
790 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
792 MonoDynamicTable *table;
795 ReflectionMethodBuilder rmb;
797 rmb.ilgen = mb->ilgen;
798 rmb.rtype = mb->rtype;
799 rmb.parameters = mb->parameters;
800 rmb.pinfo = mb->pinfo;
801 rmb.attrs = mb->attrs;
802 rmb.iattrs = mb->iattrs;
803 rmb.call_conv = mb->call_conv;
807 rmb.table_idx = &mb->table_idx;
808 rmb.init_locals = mb->init_locals;
810 mono_image_basic_method (&rmb, assembly);
812 if (mb->dll) { /* It's a P/Invoke method */
814 table = &assembly->tables [MONO_TABLE_IMPLMAP];
816 alloc_table (table, table->rows);
817 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
818 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
819 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
820 name = mono_string_to_utf8 (mb->dllentry);
821 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
823 name = mono_string_to_utf8 (mb->dll);
824 moduleref = string_heap_insert (&assembly->sheap, name);
826 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
827 table = &assembly->tables [MONO_TABLE_MODULEREF];
829 alloc_table (table, table->rows);
830 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
831 values [MONO_IMPLMAP_SCOPE] = table->rows;
834 if (mb->override_method) {
835 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
837 table = &assembly->tables [MONO_TABLE_METHODIMPL];
839 alloc_table (table, table->rows);
840 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
841 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
842 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
843 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
844 switch (mono_metadata_token_table (tok)) {
845 case MONO_TABLE_MEMBERREF:
846 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
848 case MONO_TABLE_METHOD:
849 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
852 g_assert_not_reached ();
854 values [MONO_METHODIMPL_DECLARATION] = tok;
859 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
861 ReflectionMethodBuilder rmb;
863 rmb.ilgen = mb->ilgen;
864 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
865 rmb.parameters = mb->parameters;
866 rmb.pinfo = mb->pinfo;
867 rmb.attrs = mb->attrs;
868 rmb.iattrs = mb->iattrs;
869 rmb.call_conv = mb->call_conv;
873 rmb.table_idx = &mb->table_idx;
874 rmb.init_locals = mb->init_locals;
876 mono_image_basic_method (&rmb, assembly);
881 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
889 p = buf = g_malloc (64);
891 mono_metadata_encode_value (0x06, p, &p);
892 /* encode custom attributes before the type */
893 encode_type (assembly, field->type, p, &p);
894 g_assert (p-buf < 64);
895 mono_metadata_encode_value (p-buf, b, &b);
896 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
902 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
910 p = buf = g_malloc (64);
912 mono_metadata_encode_value (0x06, p, &p);
913 /* encode custom attributes before the type */
914 encode_reflection_type (assembly, fb->type, p, &p);
915 g_assert (p-buf < 64);
916 mono_metadata_encode_value (p-buf, b, &b);
917 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
923 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
924 * dest may be misaligned.
927 swap_with_size (char *dest, const char* val, int len, int nelem) {
928 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
931 for (elem = 0; elem < nelem; ++elem) {
957 g_assert_not_reached ();
963 memcpy (dest, val, len * nelem);
968 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
973 guint32 idx, len, dummy = 0;
975 p = buf = g_malloc (64);
977 *ret_type = MONO_TYPE_CLASS;
979 box_val = (char*)&dummy;
981 box_val = ((char*)val) + sizeof (MonoObject);
982 *ret_type = val->vtable->klass->byval_arg.type;
986 case MONO_TYPE_BOOLEAN:
1006 case MONO_TYPE_VALUETYPE:
1007 if (val->vtable->klass->enumtype) {
1008 *ret_type = val->vtable->klass->enum_basetype->type;
1011 g_error ("we can't encode valuetypes");
1012 case MONO_TYPE_CLASS:
1014 case MONO_TYPE_STRING: {
1015 MonoString *str = (MonoString*)val;
1016 /* there is no signature */
1017 len = str->length * 2;
1018 mono_metadata_encode_value (len, b, &b);
1019 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1021 char *swapped = g_malloc (2 * mono_string_length (str));
1022 const char *p = (const char*)mono_string_chars (str);
1024 swap_with_size (swapped, p, 2, mono_string_length (str));
1025 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1029 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1036 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1039 /* there is no signature */
1040 mono_metadata_encode_value (len, b, &b);
1041 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1042 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1043 swap_with_size (blob_size, box_val, len, 1);
1044 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1046 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1054 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo) {
1055 char blob_size [64];
1056 char *b = blob_size;
1060 p = buf = g_malloc (256);
1062 switch (minfo->type) {
1063 case MONO_NATIVE_BYVALTSTR:
1064 case MONO_NATIVE_BYVALARRAY:
1065 mono_metadata_encode_value (minfo->type, p, &p);
1066 mono_metadata_encode_value (minfo->count, p, &p);
1068 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
1070 mono_metadata_encode_value (minfo->type, p, &p);
1074 mono_metadata_encode_value (len, b, &b);
1075 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1081 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
1083 MonoDynamicTable *table;
1087 /* maybe this fixup should be done in the C# code */
1088 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1089 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1090 table = &assembly->tables [MONO_TABLE_FIELD];
1091 fb->table_idx = table->next_idx ++;
1092 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1093 name = mono_string_to_utf8 (fb->name);
1094 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1096 values [MONO_FIELD_FLAGS] = fb->attrs;
1097 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1099 if (fb->offset != -1) {
1100 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1102 alloc_table (table, table->rows);
1103 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1104 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1105 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1107 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1108 guint32 field_type = 0;
1109 table = &assembly->tables [MONO_TABLE_CONSTANT];
1111 alloc_table (table, table->rows);
1112 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1113 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1114 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1115 values [MONO_CONSTANT_TYPE] = field_type;
1116 values [MONO_CONSTANT_PADDING] = 0;
1120 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1122 alloc_table (table, table->rows);
1123 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1124 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1126 * We store it in the code section because it's simpler for now.
1128 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1129 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1131 if (fb->marshal_info) {
1132 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1134 alloc_table (table, table->rows);
1135 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1136 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1137 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1142 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
1146 char *b = blob_size;
1147 guint32 nparams = 0;
1148 MonoReflectionMethodBuilder *mb = fb->get_method;
1149 MonoReflectionMethodBuilder *smb = fb->set_method;
1150 guint32 idx, i, size;
1152 if (mb && mb->parameters)
1153 nparams = mono_array_length (mb->parameters);
1154 if (!mb && smb && smb->parameters)
1155 nparams = mono_array_length (smb->parameters) - 1;
1156 size = 24 + nparams * 10;
1157 buf = p = g_malloc (size);
1160 mono_metadata_encode_value (nparams, p, &p);
1162 encode_reflection_type (assembly, mb->rtype, p, &p);
1163 for (i = 0; i < nparams; ++i) {
1164 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1165 encode_reflection_type (assembly, pt, p, &p);
1168 /* the property type is the last param */
1169 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1170 for (i = 0; i < nparams; ++i) {
1171 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1172 encode_reflection_type (assembly, pt, p, &p);
1176 g_assert (p - buf < size);
1177 mono_metadata_encode_value (p-buf, b, &b);
1178 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1184 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
1186 MonoDynamicTable *table;
1189 guint num_methods = 0;
1193 * we need to set things in the following tables:
1194 * PROPERTYMAP (info already filled in _get_type_info ())
1195 * PROPERTY (rows already preallocated in _get_type_info ())
1196 * METHOD (method info already done with the generic method code)
1199 table = &assembly->tables [MONO_TABLE_PROPERTY];
1200 pb->table_idx = table->next_idx ++;
1201 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1202 name = mono_string_to_utf8 (pb->name);
1203 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1205 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1206 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1208 /* FIXME: we still don't handle 'other' methods */
1209 if (pb->get_method) num_methods ++;
1210 if (pb->set_method) num_methods ++;
1212 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1213 table->rows += num_methods;
1214 alloc_table (table, table->rows);
1216 if (pb->get_method) {
1217 semaidx = table->next_idx ++;
1218 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1219 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1220 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1221 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1223 if (pb->set_method) {
1224 semaidx = table->next_idx ++;
1225 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1226 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1227 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1228 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1233 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
1235 MonoDynamicTable *table;
1238 guint num_methods = 0;
1242 * we need to set things in the following tables:
1243 * EVENTMAP (info already filled in _get_type_info ())
1244 * EVENT (rows already preallocated in _get_type_info ())
1245 * METHOD (method info already done with the generic method code)
1248 table = &assembly->tables [MONO_TABLE_EVENT];
1249 eb->table_idx = table->next_idx ++;
1250 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1251 name = mono_string_to_utf8 (eb->name);
1252 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1254 values [MONO_EVENT_FLAGS] = eb->attrs;
1255 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1258 * FIXME: we still don't handle 'other' methods
1260 if (eb->add_method) num_methods ++;
1261 if (eb->remove_method) num_methods ++;
1262 if (eb->raise_method) num_methods ++;
1264 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1265 table->rows += num_methods;
1266 alloc_table (table, table->rows);
1268 if (eb->add_method) {
1269 semaidx = table->next_idx ++;
1270 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1271 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1272 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1273 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1275 if (eb->remove_method) {
1276 semaidx = table->next_idx ++;
1277 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1278 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1279 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1280 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1282 if (eb->raise_method) {
1283 semaidx = table->next_idx ++;
1284 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1285 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1286 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1287 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1292 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
1294 MonoDynamicTable *table;
1297 guint32 cols [MONO_ASSEMBLY_SIZE];
1301 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1304 if (image->assembly->dynamic)
1306 memset (cols, 0, sizeof (cols));
1308 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1310 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1311 token = table->next_idx ++;
1313 alloc_table (table, table->rows);
1314 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1315 if (strcmp ("corlib", image->assembly_name) == 0)
1316 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1318 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1319 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1320 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1321 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1322 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1323 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1324 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1325 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1327 if ((pubkey = mono_image_get_public_key (image, &publen))) {
1328 guchar pubtoken [9];
1330 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
1331 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
1334 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
1335 * This is currently only a problem with references to System.Xml (see bug#27706),
1336 * but there may be other cases that makes this necessary. Note, we need to set
1337 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
1338 * recognized by ms, yuck!
1339 * FIXME: need to add more assembly names, as needed.
1341 if (strcmp (image->assembly_name, "corlib") == 0 ||
1342 strcmp (image->assembly_name, "mscorlib") == 0 ||
1343 strcmp (image->assembly_name, "System") == 0 ||
1344 strcmp (image->assembly_name, "System.Xml") == 0 ||
1345 strcmp (image->assembly_name, "System.Data") == 0 ||
1346 strcmp (image->assembly_name, "System.Drawing") == 0 ||
1347 strcmp (image->assembly_name, "System.Web") == 0) {
1348 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
1349 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1350 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1351 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1353 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1356 token <<= RESOLTION_SCOPE_BITS;
1357 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1358 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1359 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), image);
1364 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1366 MonoDynamicTable *table;
1372 char *b = blob_size;
1374 switch (type->type) {
1375 case MONO_TYPE_FNPTR:
1377 case MONO_TYPE_SZARRAY:
1378 case MONO_TYPE_ARRAY:
1379 encode_type (assembly, type, p, &p);
1385 g_assert (p-sig < 128);
1386 mono_metadata_encode_value (p-sig, b, &b);
1387 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
1389 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1390 alloc_table (table, table->rows + 1);
1391 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1392 values [MONO_TYPESPEC_SIGNATURE] = token;
1394 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1395 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1401 * Despite the name, we handle also TypeSpec (with the above helper).
1404 mono_image_typedef_or_ref_aux (MonoDynamicAssembly *assembly, MonoType *type,
1407 MonoDynamicTable *table;
1409 guint32 token, scope, enclosing;
1412 #define COMPILE_CORLIB 0
1414 /* nasty hack, need to find the proper solution */
1415 if (type->type == MONO_TYPE_OBJECT)
1416 return TYPEDEFORREF_TYPEDEF | (2 << TYPEDEFORREF_BITS);
1418 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1421 token = create_typespec (assembly, type);
1424 klass = my_mono_class_from_mono_type (type);
1426 klass = mono_class_from_mono_type (type);
1429 * If it's in the same module:
1431 if (!force_ref && (klass->image == assembly->assembly.image)) {
1432 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1433 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1434 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
1438 if (klass->nested_in) {
1439 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1440 /* get the typeref idx of the enclosing type */
1441 enclosing >>= TYPEDEFORREF_BITS;
1442 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1444 scope = resolution_scope_from_image (assembly, klass->image);
1446 table = &assembly->tables [MONO_TABLE_TYPEREF];
1447 alloc_table (table, table->rows + 1);
1448 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1449 values [MONO_TYPEREF_SCOPE] = scope;
1450 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1451 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1452 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1453 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1455 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
1460 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1462 return mono_image_typedef_or_ref_aux (assembly, type, FALSE);
1466 * Insert a memberef row into the metadata: the token that point to the memberref
1467 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1468 * mono_image_get_fieldref_token()).
1469 * The sig param is an index to an already built signature.
1472 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1474 MonoDynamicTable *table;
1476 guint32 token, pclass;
1479 parent = mono_image_typedef_or_ref_aux (assembly, type, TRUE);
1480 switch (parent & TYPEDEFORREF_MASK) {
1481 case TYPEDEFORREF_TYPEREF:
1482 pclass = MEMBERREF_PARENT_TYPEREF;
1484 case TYPEDEFORREF_TYPESPEC:
1485 pclass = MEMBERREF_PARENT_TYPESPEC;
1487 case TYPEDEFORREF_TYPEDEF:
1488 /* should never get here */
1490 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
1493 /* extract the index */
1494 parent >>= TYPEDEFORREF_BITS;
1496 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1497 alloc_table (table, table->rows + 1);
1498 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1499 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1500 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1501 values [MONO_MEMBERREF_SIGNATURE] = sig;
1502 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1509 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1513 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1516 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1517 method->name, method_encode_signature (assembly, method->signature));
1518 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1523 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1527 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1530 field->parent = klass;
1531 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
1532 field->name, fieldref_encode_signature (assembly, field));
1533 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1538 mono_reflection_encode_sighelper (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1546 char *b = blob_size;
1549 g_assert (helper->type == 2);
1551 if (helper->arguments)
1552 nargs = mono_array_length (helper->arguments);
1556 size = 10 + (nargs * 10);
1558 p = buf = g_malloc (size);
1560 /* Encode calling convention */
1561 /* Change Any to Standard */
1562 if ((helper->call_conv & 0x03) == 0x03)
1563 helper->call_conv = 0x01;
1564 /* explicit_this implies has_this */
1565 if (helper->call_conv & 0x40)
1566 helper->call_conv &= 0x20;
1568 if (helper->call_conv == 0) /* Unmanaged */
1569 *p = helper->unmanaged_call_conv - 1;
1572 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
1573 if (helper->call_conv & 0x02) /* varargs */
1578 mono_metadata_encode_value (nargs, p, &p);
1579 encode_reflection_type (assembly, helper->return_type, p, &p);
1580 for (i = 0; i < nargs; ++i) {
1581 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
1582 encode_reflection_type (assembly, pt, p, &p);
1585 g_assert (p - buf < size);
1586 mono_metadata_encode_value (p-buf, b, &b);
1587 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1594 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1597 MonoDynamicTable *table;
1600 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1601 idx = table->next_idx ++;
1603 alloc_table (table, table->rows);
1604 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1606 values [MONO_STAND_ALONE_SIGNATURE] =
1607 mono_reflection_encode_sighelper (assembly, helper);
1613 reflection_cc_to_file (int call_conv) {
1614 switch (call_conv & 0x3) {
1616 case 1: return MONO_CALL_DEFAULT;
1617 case 2: return MONO_CALL_VARARG;
1619 g_assert_not_reached ();
1626 MonoMethodSignature *sig;
1632 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1637 MonoMethodSignature *sig;
1640 name = mono_string_to_utf8 (m->name);
1641 nparams = mono_array_length (m->parameters);
1642 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1644 sig->call_convention = reflection_cc_to_file (m->call_conv);
1645 sig->param_count = nparams;
1646 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1647 for (i = 0; i < nparams; ++i) {
1648 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1649 sig->params [i] = t->type;
1652 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1654 if (strcmp (name, am->name) == 0 &&
1655 mono_metadata_type_equal (am->parent, m->parent->type) &&
1656 mono_metadata_signature_equal (am->sig, sig)) {
1662 am = g_new0 (ArrayMethod, 1);
1665 am->parent = m->parent->type;
1666 am->token = mono_image_get_memberref_token (assembly, am->parent,
1667 name, method_encode_signature (assembly, sig));
1668 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1669 m->table_idx = am->token & 0xffffff;
1674 * Insert into the metadata tables all the info about the TypeBuilder tb.
1675 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1678 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1680 MonoDynamicTable *table;
1682 int i, is_object = 0, is_system = 0;
1685 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1686 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1687 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1688 n = mono_string_to_utf8 (tb->name);
1689 if (strcmp (n, "Object") == 0)
1691 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1693 n = mono_string_to_utf8 (tb->nspace);
1694 if (strcmp (n, "System") == 0)
1696 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1698 if (tb->parent && !(is_system && is_object) &&
1699 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
1700 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1702 values [MONO_TYPEDEF_EXTENDS] = 0;
1703 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1704 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1707 * if we have explicitlayout or sequentiallayouts, output data in the
1708 * ClassLayout table.
1710 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1711 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1713 alloc_table (table, table->rows);
1714 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1715 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1716 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1717 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1720 /* handle interfaces */
1721 if (tb->interfaces) {
1722 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1724 table->rows += mono_array_length (tb->interfaces);
1725 alloc_table (table, table->rows);
1726 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1727 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1728 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1729 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1730 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1731 values += MONO_INTERFACEIMPL_SIZE;
1737 table = &assembly->tables [MONO_TABLE_FIELD];
1738 table->rows += mono_array_length (tb->fields);
1739 alloc_table (table, table->rows);
1740 for (i = 0; i < mono_array_length (tb->fields); ++i)
1741 mono_image_get_field_info (
1742 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1745 /* handle constructors */
1747 table = &assembly->tables [MONO_TABLE_METHOD];
1748 table->rows += mono_array_length (tb->ctors);
1749 alloc_table (table, table->rows);
1750 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1751 mono_image_get_ctor_info (domain,
1752 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1755 /* handle methods */
1757 table = &assembly->tables [MONO_TABLE_METHOD];
1758 table->rows += mono_array_length (tb->methods);
1759 alloc_table (table, table->rows);
1760 for (i = 0; i < mono_array_length (tb->methods); ++i)
1761 mono_image_get_method_info (
1762 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1765 /* Do the same with properties etc.. */
1766 if (tb->events && mono_array_length (tb->events)) {
1767 table = &assembly->tables [MONO_TABLE_EVENT];
1768 table->rows += mono_array_length (tb->events);
1769 alloc_table (table, table->rows);
1770 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1772 alloc_table (table, table->rows);
1773 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1774 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1775 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1776 for (i = 0; i < mono_array_length (tb->events); ++i)
1777 mono_image_get_event_info (
1778 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1780 if (tb->properties && mono_array_length (tb->properties)) {
1781 table = &assembly->tables [MONO_TABLE_PROPERTY];
1782 table->rows += mono_array_length (tb->properties);
1783 alloc_table (table, table->rows);
1784 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1786 alloc_table (table, table->rows);
1787 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1788 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1789 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1790 for (i = 0; i < mono_array_length (tb->properties); ++i)
1791 mono_image_get_property_info (
1792 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1795 MonoDynamicTable *ntable;
1797 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1798 table->rows += mono_array_length (tb->subtypes);
1799 alloc_table (table, table->rows);
1801 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1802 ntable->rows += mono_array_length (tb->subtypes);
1803 alloc_table (ntable, ntable->rows);
1804 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1806 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1807 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1809 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1810 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1811 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1812 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1813 mono_string_to_utf8 (tb->name), tb->table_idx,
1814 ntable->next_idx, ntable->rows);*/
1815 values += MONO_NESTED_CLASS_SIZE;
1818 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1819 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1821 mono_image_get_type_info (domain, subtype, assembly);
1827 assign_type_idx (MonoReflectionTypeBuilder *type, MonoDynamicTable *table)
1831 type->table_idx = table->next_idx ++;
1832 if (!type->subtypes)
1834 for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1835 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1836 assign_type_idx (subtype, table);
1841 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
1846 for (i = 0; i < mono_array_length (pinfo); ++i) {
1847 MonoReflectionParamBuilder *pb;
1848 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
1851 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
1856 type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
1859 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1861 for (i = 0; i < mono_array_length (tb->fields); ++i) {
1862 MonoReflectionFieldBuilder* fb;
1863 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
1864 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
1868 for (i = 0; i < mono_array_length (tb->events); ++i) {
1869 MonoReflectionEventBuilder* eb;
1870 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
1871 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1874 if (tb->properties) {
1875 for (i = 0; i < mono_array_length (tb->properties); ++i) {
1876 MonoReflectionPropertyBuilder* pb;
1877 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
1878 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
1882 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
1883 MonoReflectionCtorBuilder* cb;
1884 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
1885 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
1886 params_add_cattrs (assembly, cb->pinfo);
1891 for (i = 0; i < mono_array_length (tb->methods); ++i) {
1892 MonoReflectionMethodBuilder* mb;
1893 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
1894 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
1895 params_add_cattrs (assembly, mb->pinfo);
1900 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
1901 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
1906 module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
1909 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1911 /* no types in the module */
1915 for (i = 0; i < mono_array_length (mb->types); ++i)
1916 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
1920 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1922 MonoDynamicTable *table;
1926 table = &assembly->tables [MONO_TABLE_MODULE];
1927 mb->table_idx = table->next_idx ++;
1928 name = mono_string_to_utf8 (mb->module.name);
1929 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1931 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1934 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1935 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1936 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1938 /* no types in the module */
1943 * fill-in info in other tables as well.
1945 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1946 table->rows += mono_array_length (mb->types);
1947 alloc_table (table, table->rows);
1949 * We assign here the typedef indexes to avoid mismatches if a type that
1950 * has not yet been stored in the tables is referenced by another type.
1952 for (i = 0; i < mono_array_length (mb->types); ++i) {
1953 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1954 assign_type_idx (type, table);
1956 for (i = 0; i < mono_array_length (mb->types); ++i)
1957 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1960 #define align_pointer(base,p)\
1962 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1964 (p) += 4 - (__diff & 3);\
1968 compare_semantics (const void *a, const void *b)
1970 const guint32 *a_values = a;
1971 const guint32 *b_values = b;
1972 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
1975 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
1979 compare_custom_attrs (const void *a, const void *b)
1981 const guint32 *a_values = a;
1982 const guint32 *b_values = b;
1984 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
1988 compare_field_marshal (const void *a, const void *b)
1990 const guint32 *a_values = a;
1991 const guint32 *b_values = b;
1993 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
1997 compare_nested (const void *a, const void *b)
1999 const guint32 *a_values = a;
2000 const guint32 *b_values = b;
2002 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
2006 * build_compressed_metadata() fills in the blob of data that represents the
2007 * raw metadata as it will be saved in the PE file. The five streams are output
2008 * and the metadata tables are comnpressed from the guint32 array representation,
2009 * to the compressed on-disk format.
2012 build_compressed_metadata (MonoDynamicAssembly *assembly)
2014 MonoDynamicTable *table;
2016 guint64 valid_mask = 0;
2017 guint64 sorted_mask;
2018 guint32 heapt_size = 0;
2019 guint32 meta_size = 256; /* allow for header and other stuff */
2020 guint32 table_offset;
2021 guint32 ntables = 0;
2028 * We need to use the current ms version or the ms runtime it won't find
2029 * the support dlls. D'oh!
2030 * const char *version = "mono-" VERSION;
2032 const char *version = "v1.0.3705";
2035 MonoDynamicStream *stream;
2036 } stream_desc [] = {
2037 {"#~", &assembly->tstream},
2038 {"#Strings", &assembly->sheap},
2039 {"#US", &assembly->us},
2040 {"#Blob", &assembly->blob},
2041 {"#GUID", &assembly->guid}
2044 /* tables that are sorted */
2045 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
2046 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
2047 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
2048 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
2049 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
2050 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
2052 /* Compute table sizes */
2053 /* the MonoImage has already been created in mono_image_basic_init() */
2054 meta = assembly->assembly.image;
2056 /* Setup the info used by compute_sizes () */
2057 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
2058 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
2059 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
2061 meta_size += assembly->blob.index;
2062 meta_size += assembly->guid.index;
2063 meta_size += assembly->sheap.index;
2064 meta_size += assembly->us.index;
2066 for (i=0; i < 64; ++i)
2067 meta->tables [i].rows = assembly->tables [i].rows;
2069 for (i = 0; i < 64; i++){
2070 if (meta->tables [i].rows == 0)
2072 valid_mask |= (guint64)1 << i;
2074 meta->tables [i].row_size = mono_metadata_compute_size (
2075 meta, i, &meta->tables [i].size_bitfield);
2076 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
2078 heapt_size += 24; /* #~ header size */
2079 heapt_size += ntables * 4;
2080 meta_size += heapt_size;
2081 meta->raw_metadata = g_malloc0 (meta_size);
2082 p = meta->raw_metadata;
2083 /* the metadata signature */
2084 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
2085 /* version numbers and 4 bytes reserved */
2086 int16val = (guint16*)p;
2087 *int16val++ = GUINT16_TO_LE (1);
2088 *int16val = GUINT16_TO_LE (1);
2090 /* version string */
2091 int32val = (guint32*)p;
2092 *int32val = GUINT32_TO_LE ((strlen (version) + 3) & (~3)); /* needs to be multiple of 4 */
2094 memcpy (p, version, GUINT32_FROM_LE (*int32val));
2095 p += GUINT32_FROM_LE (*int32val);
2096 align_pointer (meta->raw_metadata, p);
2097 int16val = (guint16*)p;
2098 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
2099 *int16val = GUINT16_TO_LE (5); /* number of streams */
2103 * write the stream info.
2105 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
2106 table_offset += 3; table_offset &= ~3;
2108 assembly->tstream.index = heapt_size;
2109 for (i = 0; i < 5; ++i) {
2110 int32val = (guint32*)p;
2111 stream_desc [i].stream->offset = table_offset;
2112 *int32val++ = GUINT32_TO_LE (table_offset);
2113 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
2114 table_offset += GUINT32_FROM_LE (*int32val);
2115 table_offset += 3; table_offset &= ~3;
2117 strcpy (p, stream_desc [i].name);
2118 p += strlen (stream_desc [i].name) + 1;
2119 align_pointer (meta->raw_metadata, p);
2122 * now copy the data, the table stream header and contents goes first.
2124 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
2125 p = meta->raw_metadata + assembly->tstream.offset;
2126 int32val = (guint32*)p;
2127 *int32val = GUINT32_TO_LE (0); /* reserved */
2129 *p++ = 1; /* version */
2131 if (meta->idx_string_wide)
2133 if (meta->idx_guid_wide)
2135 if (meta->idx_blob_wide)
2138 *p++ = 0; /* reserved */
2139 int64val = (guint64*)p;
2140 *int64val++ = GUINT64_TO_LE (valid_mask);
2141 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
2143 int32val = (guint32*)p;
2144 for (i = 0; i < 64; i++){
2145 if (meta->tables [i].rows == 0)
2147 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
2149 p = (unsigned char*)int32val;
2151 /* sort the tables that still need sorting */
2152 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2154 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
2155 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2157 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
2158 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2160 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
2161 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2163 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
2165 /* compress the tables */
2166 for (i = 0; i < 64; i++){
2169 guint32 bitfield = meta->tables [i].size_bitfield;
2170 if (!meta->tables [i].rows)
2172 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
2173 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
2174 meta->tables [i].base = p;
2175 for (row = 1; row <= meta->tables [i].rows; ++row) {
2176 values = assembly->tables [i].values + row * assembly->tables [i].columns;
2177 for (col = 0; col < assembly->tables [i].columns; ++col) {
2178 switch (mono_metadata_table_size (bitfield, col)) {
2180 *p++ = values [col];
2183 *p++ = values [col] & 0xff;
2184 *p++ = (values [col] >> 8) & 0xff;
2187 *p++ = values [col] & 0xff;
2188 *p++ = (values [col] >> 8) & 0xff;
2189 *p++ = (values [col] >> 16) & 0xff;
2190 *p++ = (values [col] >> 24) & 0xff;
2193 g_assert_not_reached ();
2197 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
2200 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
2201 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
2202 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
2203 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
2204 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
2206 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
2210 * Some tables in metadata need to be sorted according to some criteria, but
2211 * when methods and fields are first created with reflection, they may be assigned a token
2212 * that doesn't correspond to the final token they will get assigned after the sorting.
2213 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
2214 * with the reflection objects that represent them. Once all the tables are set up, the
2215 * reflection objects will contains the correct table index. fixup_method() will fixup the
2216 * tokens for the method with ILGenerator @ilgen.
2219 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
2220 guint32 code_idx = GPOINTER_TO_UINT (value);
2221 MonoReflectionILTokenInfo *iltoken;
2222 MonoReflectionFieldBuilder *field;
2223 MonoReflectionCtorBuilder *ctor;
2224 MonoReflectionMethodBuilder *method;
2225 MonoReflectionTypeBuilder *tb;
2227 unsigned char *target;
2229 for (i = 0; i < ilgen->num_token_fixups; ++i) {
2230 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
2231 target = assembly->code.data + code_idx + iltoken->code_pos;
2232 switch (target [3]) {
2233 case MONO_TABLE_FIELD:
2234 if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
2235 g_assert_not_reached ();
2236 field = (MonoReflectionFieldBuilder *)iltoken->member;
2237 idx = field->table_idx;
2239 case MONO_TABLE_METHOD:
2240 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
2241 method = (MonoReflectionMethodBuilder *)iltoken->member;
2242 idx = method->table_idx;
2243 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
2244 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
2245 idx = ctor->table_idx;
2247 g_assert_not_reached ();
2250 case MONO_TABLE_TYPEDEF:
2251 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
2252 g_assert_not_reached ();
2253 tb = (MonoReflectionTypeBuilder *)iltoken->member;
2254 idx = tb->table_idx;
2257 g_error ("got unexpected table 0x%02x in fixup", target [3]);
2259 target [0] = idx & 0xff;
2260 target [1] = (idx >> 8) & 0xff;
2261 target [2] = (idx >> 16) & 0xff;
2266 assembly_add_resource (MonoDynamicAssembly *assembly, MonoReflectionResource *rsrc)
2268 MonoDynamicTable *table;
2272 char *b = blob_size;
2274 guint32 idx, offset;
2276 if (rsrc->filename) {
2277 name = mono_string_to_utf8 (rsrc->filename);
2278 sname = g_path_get_basename (name);
2280 table = &assembly->tables [MONO_TABLE_FILE];
2282 alloc_table (table, table->rows);
2283 values = table->values + table->next_idx * MONO_FILE_SIZE;
2284 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
2285 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
2288 mono_sha1_get_digest_from_file (name, hash);
2289 mono_metadata_encode_value (20, b, &b);
2290 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2291 mono_image_add_stream_data (&assembly->blob, hash, 20);
2293 idx = table->next_idx++;
2294 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
2298 offset = mono_array_length (rsrc->data);
2299 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
2300 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
2301 offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
2302 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
2306 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
2308 alloc_table (table, table->rows);
2309 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
2310 values [MONO_MANIFEST_OFFSET] = offset;
2311 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
2312 name = mono_string_to_utf8 (rsrc->name);
2313 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
2315 values [MONO_MANIFEST_IMPLEMENTATION] = idx;
2320 set_version_from_string (MonoString *version, guint32 *values)
2322 gchar *ver, *p, *str;
2325 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
2326 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
2327 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
2328 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
2331 ver = str = mono_string_to_utf8 (version);
2332 for (i = 0; i < 4; ++i) {
2333 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
2339 /* handle Revision and Build */
2349 load_public_key (MonoString *fname, MonoDynamicAssembly *assembly) {
2350 char *name, *content;
2356 name = mono_string_to_utf8 (fname);
2357 if (g_file_get_contents (name, &content, &len, NULL)) {
2359 char *b = blob_size;
2360 /* check it's a public key or keypair */
2361 mono_metadata_encode_value (len, b, &b);
2362 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
2363 mono_image_add_stream_data (&assembly->blob, content, len);
2365 /* need to get the actual value from the key type... */
2366 assembly->strong_name_size = 128;
2367 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
2369 /* FIXME: how do we tell mcs if loading fails? */
2375 * mono_image_build_metadata() will fill the info in all the needed metadata tables
2376 * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
2377 * and recursively outputs the info for a module. Each module will output all the info
2378 * about it's types etc.
2379 * At the end of the process, method and field tokens are fixed up and the on-disk
2380 * compressed metadata representation is created.
2383 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
2385 MonoDynamicTable *table;
2386 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
2387 MonoDomain *domain = mono_object_domain (assemblyb);
2393 if (assembly->text_rva)
2396 assembly->text_rva = START_TEXT_RVA;
2398 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2399 alloc_table (table, 1);
2400 values = table->values + MONO_ASSEMBLY_SIZE;
2401 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2402 name = mono_string_to_utf8 (assemblyb->name);
2403 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
2405 if (assemblyb->culture) {
2406 name = mono_string_to_utf8 (assemblyb->culture);
2407 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
2410 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2412 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->keyfile, assembly);
2413 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2414 set_version_from_string (assemblyb->version, values);
2416 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2417 table->rows = 1; /* .<Module> */
2419 alloc_table (table, table->rows);
2421 * Set the first entry.
2423 values = table->values + table->columns;
2424 values [MONO_TYPEDEF_FLAGS] = 0;
2425 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2426 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2427 values [MONO_TYPEDEF_EXTENDS] = 0;
2428 values [MONO_TYPEDEF_FIELD_LIST] = 1;
2429 values [MONO_TYPEDEF_METHOD_LIST] = 1;
2432 * handle global methods
2433 * FIXME: test what to do when global methods are defined in multiple modules.
2435 if (assemblyb->modules) {
2436 MonoReflectionModuleBuilder *mod = mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, 0);
2437 if (mod->global_methods) {
2438 table = &assembly->tables [MONO_TABLE_METHOD];
2439 table->rows += mono_array_length (mod->global_methods);
2440 alloc_table (table, table->rows);
2441 for (i = 0; i < mono_array_length (mod->global_methods); ++i)
2442 mono_image_get_method_info (
2443 mono_array_get (mod->global_methods, MonoReflectionMethodBuilder*, i), assembly);
2447 if (assemblyb->modules) {
2448 len = mono_array_length (assemblyb->modules);
2449 table = &assembly->tables [MONO_TABLE_MODULE];
2450 alloc_table (table, len);
2451 for (i = 0; i < len; ++i)
2452 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
2454 table = &assembly->tables [MONO_TABLE_MODULE];
2456 alloc_table (table, table->rows);
2457 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
2462 * table->rows is already set above and in mono_image_fill_module_table.
2464 /* add all the custom attributes at the end, once all the indexes are stable */
2465 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
2467 if (assemblyb->modules) {
2468 len = mono_array_length (assemblyb->modules);
2469 for (i = 0; i < len; ++i)
2470 module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
2474 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2478 * mono_image_insert_string:
2479 * @assembly: assembly builder object
2482 * Insert @str into the user string stream of @assembly.
2485 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
2491 MONO_ARCH_SAVE_REGS;
2493 if (!assembly->dynamic_assembly)
2494 mono_image_basic_init (assembly);
2495 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
2496 idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
2497 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2499 char *swapped = g_malloc (2 * mono_string_length (str));
2500 const char *p = (const char*)mono_string_chars (str);
2502 swap_with_size (swapped, p, 2, mono_string_length (str));
2503 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2507 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2509 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2511 mono_g_hash_table_insert (assembly->dynamic_assembly->tokens,
2512 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
2514 return MONO_TOKEN_STRING | idx;
2518 * mono_image_create_token:
2519 * @assembly: a dynamic assembly
2522 * Get a token to insert in the IL code stream for the given MemberInfo.
2523 * @obj can be one of:
2524 * ConstructorBuilder
2534 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2540 g_error ("System.Array methods not yet supported");
2542 klass = obj->vtable->klass;
2543 if (strcmp (klass->name, "MethodBuilder") == 0) {
2544 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2545 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2546 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2548 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2549 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2550 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2551 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2553 else if (strcmp (klass->name, "FieldBuilder") == 0) {
2554 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2555 token = mb->table_idx | MONO_TOKEN_FIELD_DEF;
2557 else if (strcmp (klass->name, "TypeBuilder") == 0) {
2558 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2559 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
2561 else if (strcmp (klass->name, "MonoType") == 0) {
2562 MonoReflectionType *tb = (MonoReflectionType *)obj;
2563 token = mono_metadata_token_from_dor (
2564 mono_image_typedef_or_ref (assembly, tb->type));
2566 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
2567 strcmp (klass->name, "MonoMethod") == 0) {
2568 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2569 token = mono_image_get_methodref_token (assembly, m->method);
2570 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2572 else if (strcmp (klass->name, "MonoField") == 0) {
2573 MonoReflectionField *f = (MonoReflectionField *)obj;
2574 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2575 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2577 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2578 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2579 token = mono_image_get_array_token (assembly, m);
2581 else if (strcmp (klass->name, "SignatureHelper") == 0) {
2582 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
2583 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
2586 g_error ("requested token for %s\n", klass->name);
2588 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
2595 guint32 import_lookup_table;
2599 guint32 import_address_table_rva;
2607 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
2610 create_dynamic_mono_image (char *assembly_name, char *module_name)
2614 image = g_new0 (MonoImage, 1);
2616 /* keep in sync with image.c */
2617 image->name = assembly_name;
2618 image->assembly_name = image->name; /* they may be different */
2619 image->module_name = module_name;
2620 image->references = g_new0 (MonoAssembly*, 1);
2621 image->references [0] = NULL;
2623 image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2624 image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2625 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2626 image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2628 image->delegate_begin_invoke_cache =
2629 g_hash_table_new ((GHashFunc)mono_signature_hash,
2630 (GCompareFunc)mono_metadata_signature_equal);
2631 image->delegate_end_invoke_cache =
2632 g_hash_table_new ((GHashFunc)mono_signature_hash,
2633 (GCompareFunc)mono_metadata_signature_equal);
2634 image->delegate_invoke_cache =
2635 g_hash_table_new ((GHashFunc)mono_signature_hash,
2636 (GCompareFunc)mono_metadata_signature_equal);
2638 image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2639 image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2640 image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2641 image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2647 * mono_image_basic_init:
2648 * @assembly: an assembly builder object
2650 * Create the MonoImage that represents the assembly builder and setup some
2651 * of the helper hash table and the basic metadata streams.
2654 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2656 static const guchar entrycode [16] = {0xff, 0x25, 0};
2657 MonoDynamicAssembly *assembly;
2661 MONO_ARCH_SAVE_REGS;
2663 if (assemblyb->dynamic_assembly)
2667 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
2669 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2672 assembly->assembly.dynamic = assembly;
2673 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
2674 assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2675 assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2676 assembly->tokens = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2677 assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2678 assembly->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
2680 string_heap_init (&assembly->sheap);
2681 mono_image_add_stream_data (&assembly->us, "", 1);
2682 add_to_blob_cached (assembly, (char*) "", 1, NULL, 0);
2683 /* import tables... */
2684 mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2685 assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2686 assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2687 mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2688 assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2689 mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2690 assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2691 stream_data_align (&assembly->code);
2693 assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2695 for (i=0; i < 64; ++i) {
2696 assembly->tables [i].next_idx = 1;
2697 assembly->tables [i].columns = table_sizes [i];
2700 image = create_dynamic_mono_image (mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
2701 assembly->assembly.aname.name = image->name;
2702 image->assembly = (MonoAssembly*)assembly;
2703 assembly->assembly.image = image;
2705 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
2706 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
2710 calc_section_size (MonoDynamicAssembly *assembly)
2714 /* alignment constraints */
2715 assembly->code.index += 3;
2716 assembly->code.index &= ~3;
2717 assembly->meta_size += 3;
2718 assembly->meta_size &= ~3;
2719 assembly->resources.index += 3;
2720 assembly->resources.index &= ~3;
2722 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2723 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2726 assembly->sections [MONO_SECTION_RELOC].size = 12;
2727 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2734 * mono_image_create_pefile:
2735 * @assemblyb: an assembly builder object
2737 * When we need to save an assembly, we first call this function that ensures the metadata
2738 * tables are built for all the modules in the assembly. This function creates the PE-COFF
2739 * header, the image sections, the CLI header etc. all the data is written in
2740 * assembly->pefile where it can be easily retrieved later in chunks.
2743 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
2744 MonoMSDOSHeader *msdos;
2745 MonoDotNetHeader *header;
2746 MonoSectionTable *section;
2747 MonoCLIHeader *cli_header;
2748 guint32 size, image_size, virtual_base, text_offset;
2749 guint32 header_start, section_start, file_offset, virtual_offset;
2750 MonoDynamicAssembly *assembly;
2751 MonoDynamicStream *pefile;
2753 guint32 *rva, value;
2756 static const unsigned char msheader[] = {
2757 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2758 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2759 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2760 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2761 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2762 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2763 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2764 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2767 mono_image_basic_init (assemblyb);
2768 assembly = assemblyb->dynamic_assembly;
2770 /* already created */
2771 if (assembly->pefile.index)
2774 mono_image_build_metadata (assemblyb);
2776 if (assemblyb->resources) {
2777 int len = mono_array_length (assemblyb->resources);
2778 for (i = 0; i < len; ++i)
2779 assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
2783 build_compressed_metadata (assembly);
2785 nsections = calc_section_size (assembly);
2787 pefile = &assembly->pefile;
2789 /* The DOS header and stub */
2790 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2791 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
2793 /* the dotnet header */
2794 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2796 /* the section tables */
2797 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2799 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2800 virtual_offset = VIRT_ALIGN;
2803 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2804 if (!assembly->sections [i].size)
2807 file_offset += FILE_ALIGN - 1;
2808 file_offset &= ~(FILE_ALIGN - 1);
2809 virtual_offset += VIRT_ALIGN - 1;
2810 virtual_offset &= ~(VIRT_ALIGN - 1);
2812 assembly->sections [i].offset = file_offset;
2813 assembly->sections [i].rva = virtual_offset;
2815 file_offset += assembly->sections [i].size;
2816 virtual_offset += assembly->sections [i].size;
2817 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2820 file_offset += FILE_ALIGN - 1;
2821 file_offset &= ~(FILE_ALIGN - 1);
2822 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
2824 image_size += section_start + sizeof (MonoSectionTable) * nsections;
2826 /* back-patch info */
2827 msdos = (MonoMSDOSHeader*)pefile->data;
2828 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
2829 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
2830 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2832 header = (MonoDotNetHeader*)(pefile->data + header_start);
2833 header->pesig [0] = 'P';
2834 header->pesig [1] = 'E';
2836 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
2837 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2838 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2839 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2840 if (assemblyb->pekind == 1) {
2842 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
2845 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2848 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2850 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2851 header->pe.pe_major = 6;
2852 header->pe.pe_minor = 0;
2853 size = assembly->sections [MONO_SECTION_TEXT].size;
2854 size += FILE_ALIGN - 1;
2855 size &= ~(FILE_ALIGN - 1);
2856 header->pe.pe_code_size = size;
2857 size = assembly->sections [MONO_SECTION_RSRC].size;
2858 size += FILE_ALIGN - 1;
2859 size &= ~(FILE_ALIGN - 1);
2860 header->pe.pe_data_size = size;
2861 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2862 header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
2863 header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
2864 /* pe_rva_entry_point always at the beginning of the text section */
2865 header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
2867 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2868 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2869 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2870 header->nt.pe_os_major = GUINT16_FROM_LE (4);
2871 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2872 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2873 size = section_start;
2874 size += FILE_ALIGN - 1;
2875 size &= ~(FILE_ALIGN - 1);
2876 header->nt.pe_header_size = GUINT32_FROM_LE (size);
2878 size += VIRT_ALIGN - 1;
2879 size &= ~(VIRT_ALIGN - 1);
2880 header->nt.pe_image_size = GUINT32_FROM_LE (size);
2883 // Translate the PEFileKind value to the value expected by the Windows loader
2886 short kind = assemblyb->pekind;
2889 // PEFileKinds.ConsoleApplication == 2
2890 // PEFileKinds.WindowApplication == 3
2893 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
2894 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
2900 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
2902 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2903 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2904 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2905 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2906 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2907 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2909 /* fill data directory entries */
2911 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2912 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2914 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2915 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2917 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2918 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2919 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2920 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2921 /* patch imported function RVA name */
2922 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2923 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2925 /* the import table */
2926 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2927 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2928 /* patch imported dll RVA name and other entries in the dir */
2929 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2930 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
2931 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2932 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2933 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2934 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2936 p = (assembly->code.data + assembly->ilt_offset);
2937 value = (assembly->text_rva + assembly->imp_names_offset - 2);
2938 *p++ = (value) & 0xff;
2939 *p++ = (value >> 8) & (0xff);
2940 *p++ = (value >> 16) & (0xff);
2941 *p++ = (value >> 24) & (0xff);
2943 /* the CLI header info */
2944 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2945 cli_header->ch_size = GUINT32_FROM_LE (72);
2946 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
2947 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
2948 if (assemblyb->entry_point)
2949 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
2951 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
2952 /* The embedded managed resources */
2953 text_offset = assembly->text_rva + assembly->code.index;
2954 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
2955 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
2956 text_offset += assembly->resources.index;
2957 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
2958 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
2959 text_offset += assembly->meta_size;
2960 if (assembly->strong_name_size) {
2961 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
2962 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
2963 text_offset += assembly->strong_name_size;
2966 /* write the section tables and section content */
2967 section = (MonoSectionTable*)(pefile->data + section_start);
2968 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2969 static const char *section_names [] = {
2970 ".text", ".rsrc", ".reloc"
2972 if (!assembly->sections [i].size)
2974 strcpy (section->st_name, section_names [i]);
2975 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
2976 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
2977 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
2978 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
2979 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
2980 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
2981 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
2983 case MONO_SECTION_TEXT:
2984 /* patch entry point */
2985 p = (assembly->code.data + 2);
2986 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
2987 *p++ = (value) & 0xff;
2988 *p++ = (value >> 8) & 0xff;
2989 *p++ = (value >> 16) & 0xff;
2990 *p++ = (value >> 24) & 0xff;
2992 text_offset = assembly->sections [i].offset;
2993 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
2994 text_offset += assembly->code.index;
2995 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
2996 text_offset += assembly->resources.index;
2997 memcpy (pefile->data + text_offset, assembly->assembly.image->raw_metadata, assembly->meta_size);
2998 text_offset += assembly->meta_size;
2999 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
3001 case MONO_SECTION_RELOC:
3002 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
3003 *rva = GUINT32_FROM_LE (assembly->text_rva);
3005 *rva = GUINT32_FROM_LE (12);
3007 data16 = (guint16*)rva;
3009 * the entrypoint is always at the start of the text section
3010 * 3 is IMAGE_REL_BASED_HIGHLOW
3011 * 2 is patch_size_rva - text_rva
3013 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
3015 *data16 = 0; /* terminate */
3017 case MONO_SECTION_RSRC:
3019 g_assert_not_reached ();
3024 /* check that the file is properly padded */
3027 FILE *f = fopen ("mypetest.exe", "w");
3028 fwrite (pefile->data, pefile->index, 1, f);
3035 * We need to return always the same object for MethodInfo, FieldInfo etc..
3036 * but we need to consider the reflected type.
3037 * type uses a different hash, since it uses custom hash/equal functions.
3042 MonoClass *refclass;
3046 reflected_equal (gconstpointer a, gconstpointer b) {
3047 const ReflectedEntry *ea = a;
3048 const ReflectedEntry *eb = b;
3050 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
3054 reflected_hash (gconstpointer a) {
3055 const ReflectedEntry *ea = a;
3056 return GPOINTER_TO_UINT (ea->item);
3059 #define CHECK_OBJECT(t,p,k) \
3065 mono_domain_lock (domain); \
3066 if (!domain->refobject_hash) \
3067 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
3068 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
3069 mono_domain_unlock (domain); \
3075 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
3077 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
3080 #define CACHE_OBJECT(p,o,k) \
3082 ReflectedEntry *e = ALLOC_REFENTRY; \
3084 e->refclass = (k); \
3085 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
3086 mono_domain_unlock (domain); \
3090 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
3092 /* this is done only once */
3093 mono_domain_lock (domain);
3094 CACHE_OBJECT (assembly, res, NULL);
3098 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoImage *module)
3100 /* this is done only once */
3101 mono_domain_lock (domain);
3102 CACHE_OBJECT (module, res, NULL);
3106 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
3108 MonoImage *image = moduleb->module.image;
3109 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
3112 /* a MonoImage was already created in mono_image_basic_init () */
3113 image = ab->dynamic_assembly->assembly.image;
3115 image = create_dynamic_mono_image (mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.name));
3117 moduleb->module.image = image;
3118 register_module (mono_object_domain (moduleb), moduleb, image);
3123 * mono_assembly_get_object:
3124 * @domain: an app domain
3125 * @assembly: an assembly
3127 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
3129 MonoReflectionAssembly*
3130 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
3132 static MonoClass *System_Reflection_Assembly;
3133 MonoReflectionAssembly *res;
3135 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
3136 if (!System_Reflection_Assembly)
3137 System_Reflection_Assembly = mono_class_from_name (
3138 mono_defaults.corlib, "System.Reflection", "Assembly");
3139 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
3140 res->assembly = assembly;
3141 CACHE_OBJECT (assembly, res, NULL);
3146 MonoReflectionModule*
3147 mono_module_get_object (MonoDomain *domain, MonoImage *image)
3149 static MonoClass *System_Reflection_Module;
3150 MonoReflectionModule *res;
3152 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
3153 if (!System_Reflection_Module)
3154 System_Reflection_Module = mono_class_from_name (
3155 mono_defaults.corlib, "System.Reflection", "Module");
3156 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
3159 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
3161 res->fqname = mono_string_new (domain, image->name);
3162 res->name = mono_string_new (domain, image->name);
3163 res->scopename = mono_string_new (domain, image->module_name);
3165 CACHE_OBJECT (image, res, NULL);
3171 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
3173 if ((t1->type != t2->type) ||
3174 (t1->byref != t2->byref))
3178 case MONO_TYPE_VOID:
3179 case MONO_TYPE_BOOLEAN:
3180 case MONO_TYPE_CHAR:
3191 case MONO_TYPE_STRING:
3194 case MONO_TYPE_OBJECT:
3195 case MONO_TYPE_TYPEDBYREF:
3197 case MONO_TYPE_VALUETYPE:
3198 case MONO_TYPE_CLASS:
3199 return t1->data.klass == t2->data.klass;
3201 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3202 case MONO_TYPE_SZARRAY:
3204 if (t1->data.type->type != t2->data.type->type)
3206 if (t1->data.type->type == MONO_TYPE_CLASS || t1->data.type->type == MONO_TYPE_VALUETYPE)
3207 return t1->data.type->data.klass == t2->data.type->data.klass;
3208 if (t1->data.type->type == MONO_TYPE_SZARRAY) {
3213 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3214 case MONO_TYPE_ARRAY:
3215 if (t1->data.array->rank != t2->data.array->rank)
3217 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
3219 g_error ("implement type compare for %0x!", t1->type);
3227 mymono_metadata_type_hash (MonoType *t1)
3233 hash |= t1->byref << 6; /* do not collide with t1->type values */
3235 case MONO_TYPE_VALUETYPE:
3236 case MONO_TYPE_CLASS:
3237 /* check if the distribution is good enough */
3238 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
3240 case MONO_TYPE_SZARRAY:
3241 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
3247 * mono_type_get_object:
3248 * @domain: an app domain
3251 * Return an System.MonoType object representing the type @type.
3254 mono_type_get_object (MonoDomain *domain, MonoType *type)
3256 MonoReflectionType *res;
3257 MonoClass *klass = mono_class_from_mono_type (type);
3259 mono_domain_lock (domain);
3260 if (!domain->type_hash)
3261 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
3262 (GCompareFunc)mymono_metadata_type_equal);
3263 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
3264 mono_domain_unlock (domain);
3267 if (klass->reflection_info && !klass->wastypebuilder) {
3268 //g_assert_not_reached ();
3269 /* should this be considered an error condition? */
3271 mono_domain_unlock (domain);
3272 return klass->reflection_info;
3275 mono_class_init (klass);
3276 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
3278 mono_g_hash_table_insert (domain->type_hash, type, res);
3279 mono_domain_unlock (domain);
3284 * mono_method_get_object:
3285 * @domain: an app domain
3287 * @refclass: the reflected type (can be NULL)
3289 * Return an System.Reflection.MonoMethod object representing the method @method.
3291 MonoReflectionMethod*
3292 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
3295 * We use the same C representation for methods and constructors, but the type
3296 * name in C# is different.
3300 MonoReflectionMethod *ret;
3303 refclass = method->klass;
3305 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
3306 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3307 cname = "MonoCMethod";
3309 cname = "MonoMethod";
3310 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
3312 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
3313 ret->method = method;
3314 ret->name = mono_string_new (domain, method->name);
3315 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
3316 CACHE_OBJECT (method, ret, refclass);
3321 * mono_field_get_object:
3322 * @domain: an app domain
3326 * Return an System.Reflection.MonoField object representing the field @field
3329 MonoReflectionField*
3330 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
3332 MonoReflectionField *res;
3335 CHECK_OBJECT (MonoReflectionField *, field, klass);
3336 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
3337 res = (MonoReflectionField *)mono_object_new (domain, oklass);
3340 CACHE_OBJECT (field, res, klass);
3345 * mono_property_get_object:
3346 * @domain: an app domain
3348 * @property: a property
3350 * Return an System.Reflection.MonoProperty object representing the property @property
3353 MonoReflectionProperty*
3354 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
3356 MonoReflectionProperty *res;
3359 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
3360 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
3361 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
3363 res->property = property;
3364 CACHE_OBJECT (property, res, klass);
3369 * mono_event_get_object:
3370 * @domain: an app domain
3374 * Return an System.Reflection.MonoEvent object representing the event @event
3377 MonoReflectionEvent*
3378 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
3380 MonoReflectionEvent *res;
3383 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
3384 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
3385 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
3388 CACHE_OBJECT (event, res, klass);
3393 * mono_param_get_objects:
3394 * @domain: an app domain
3397 * Return an System.Reflection.ParameterInfo array object representing the parameters
3398 * in the method @method.
3400 MonoReflectionParameter**
3401 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
3403 MonoReflectionParameter **res;
3404 MonoReflectionMethod *member;
3409 if (!method->signature->param_count)
3412 member = mono_method_get_object (domain, method, NULL);
3413 names = g_new (char *, method->signature->param_count);
3414 mono_method_get_param_names (method, (const char **) names);
3416 /* Note: the cache is based on the address of the signature into the method
3417 * since we already cache MethodInfos with the method as keys.
3419 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature), NULL);
3420 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
3422 res = GC_MALLOC (sizeof (MonoReflectionParameter*) * method->signature->param_count);
3424 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
3426 for (i = 0; i < method->signature->param_count; ++i) {
3427 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
3428 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
3429 res [i]->DefaultValueImpl = NULL; /* FIXME */
3430 res [i]->MemberImpl = (MonoObject*)member;
3431 res [i]->NameImpl = mono_string_new (domain, names [i]);
3432 res [i]->PositionImpl = i + 1;
3433 res [i]->AttrsImpl = method->signature->params [i]->attrs;
3436 CACHE_OBJECT (&(method->signature), res, NULL);
3441 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
3445 memset (assembly, 0, sizeof (MonoAssemblyName));
3447 assembly->culture = "";
3449 while (*p && (isalnum (*p) || *p == '.'))
3452 while (*p == ' ' || *p == ',') {
3461 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
3463 assembly->major = strtoul (p, &s, 10);
3464 if (s == p || *s != '.')
3467 assembly->minor = strtoul (p, &s, 10);
3468 if (s == p || *s != '.')
3471 assembly->build = strtoul (p, &s, 10);
3472 if (s == p || *s != '.')
3475 assembly->revision = strtoul (p, &s, 10);
3478 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
3480 if (strncmp (p, "neutral", 7) == 0) {
3481 assembly->culture = "";
3484 assembly->culture = p;
3485 while (*p && *p != ',') {
3489 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
3492 while (*s && isxdigit (*s)) {
3496 assembly->hash_len = s - p;
3497 if (!(s-p) || ((s-p) & 1))
3499 assembly->hash_value = s = p;
3500 while (*s && isxdigit (*s)) {
3502 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3505 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3510 while (*p && *p != ',')
3514 while (*p == ' ' || *p == ',') {
3528 * mono_reflection_parse_type:
3531 * Parse a type name as accepted by the GetType () method and output the info
3532 * extracted in the info structure.
3533 * the name param will be mangled, so, make a copy before passing it to this function.
3534 * The fields in info will be valid until the memory pointed to by name is valid.
3535 * Returns 0 on parse error.
3536 * See also mono_type_get_name () below.
3539 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
3541 char *start, *p, *w, *last_point, *startn;
3542 int in_modifiers = 0;
3543 int isbyref = 0, rank;
3545 start = p = w = name;
3547 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
3548 info->name = info->name_space = NULL;
3549 info->nested = NULL;
3550 info->modifiers = NULL;
3552 /* last_point separates the namespace from the name */
3558 *p = 0; /* NULL terminate the name */
3560 /* we have parsed the nesting namespace + name */
3562 info->nested = g_list_append (info->nested, startn);
3566 info->name_space = start;
3568 info->name = last_point + 1;
3570 info->name_space = (char *)"";
3595 info->nested = g_list_append (info->nested, startn);
3598 info->name_space = start;
3600 info->name = last_point + 1;
3602 info->name_space = (char *)"";
3609 if (isbyref) /* only one level allowed by the spec */
3612 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
3616 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
3627 else if (*p != '*') /* '*' means unknown lower bound */
3633 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
3645 return 0; /* missing assembly name */
3646 if (!assembly_name_to_aname (&info->assembly, p))
3652 if (info->assembly.name)
3655 *w = 0; /* terminate class name */
3656 if (!info->name || !*info->name)
3658 /* add other consistency checks */
3663 mono_type_get_name_recurse (MonoType *type, GString *str)
3667 switch (type->type) {
3668 case MONO_TYPE_ARRAY: {
3669 int i, rank = type->data.array->rank;
3671 mono_type_get_name_recurse (type->data.array->type, str);
3672 g_string_append_c (str, '[');
3673 for (i = 1; i < rank; i++)
3674 g_string_append_c (str, ',');
3675 g_string_append_c (str, ']');
3678 case MONO_TYPE_SZARRAY:
3679 mono_type_get_name_recurse (type->data.type, str);
3680 g_string_append (str, "[]");
3683 mono_type_get_name_recurse (type->data.type, str);
3684 g_string_append_c (str, '*');
3687 klass = mono_class_from_mono_type (type);
3688 if (klass->nested_in) {
3689 mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
3690 g_string_append_c (str, '+');
3692 if (*klass->name_space) {
3693 g_string_append (str, klass->name_space);
3694 g_string_append_c (str, '.');
3696 g_string_append (str, klass->name);
3702 * mono_type_get_name:
3705 * Returns the string representation for type as required by System.Reflection.
3706 * The inverse of mono_reflection_parse_type ().
3709 mono_type_get_name (MonoType *type)
3711 GString* result = g_string_new ("");
3712 mono_type_get_name_recurse (type, result);
3715 g_string_append_c (result, '&');
3717 return g_string_free (result, FALSE);
3721 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3728 image = mono_defaults.corlib;
3731 klass = mono_class_from_name_case (image, info->name_space, info->name);
3733 klass = mono_class_from_name (image, info->name_space, info->name);
3736 for (mod = info->nested; mod; mod = mod->next) {
3739 mono_class_init (klass);
3740 nested = klass->nested_classes;
3743 klass = nested->data;
3745 if (g_strcasecmp (klass->name, mod->data) == 0)
3748 if (strcmp (klass->name, mod->data) == 0)
3752 nested = nested->next;
3759 mono_class_init (klass);
3760 for (mod = info->modifiers; mod; mod = mod->next) {
3761 modval = GPOINTER_TO_UINT (mod->data);
3762 if (!modval) { /* byref: must be last modifier */
3763 return &klass->this_arg;
3764 } else if (modval == -1) {
3765 klass = mono_ptr_class_get (&klass->byval_arg);
3766 } else { /* array rank */
3767 klass = mono_array_class_get (&klass->byval_arg, modval);
3769 mono_class_init (klass);
3772 return &klass->byval_arg;
3776 * mono_reflection_get_type:
3777 * @image: a metadata context
3778 * @info: type description structure
3779 * @ignorecase: flag for case-insensitive string compares
3781 * Build a MonoType from the type description in @info.
3786 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3789 MonoReflectionAssembly *assembly;
3793 type = mono_reflection_get_type_internal (image, info, ignorecase);
3796 if (!image || !mono_domain_has_type_resolve (mono_domain_get ()))
3799 // Reconstruct the type name
3800 fullName = g_string_new ("");
3801 if (info->name_space && (info->name_space [0] != '\0'))
3802 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
3804 g_string_printf (fullName, info->name);
3805 for (mod = info->nested; mod; mod = mod->next)
3806 g_string_append_printf (fullName, "+%s", (char*)mod->data);
3809 mono_domain_try_type_resolve (
3810 mono_domain_get (), fullName->str, NULL);
3812 type = mono_reflection_get_type_internal (assembly->assembly->image,
3814 g_string_free (fullName, TRUE);
3819 * mono_reflection_type_from_name:
3821 * @image: a metadata context (can be NULL).
3823 * Retrieves a MonoType from its @name. If the name is not fully qualified,
3824 * it defaults to get the type from @image or, if @image is NULL or loading
3825 * from it fails, uses corlib.
3829 mono_reflection_type_from_name (char *name, MonoImage *image)
3832 MonoTypeNameParse info;
3834 /*g_print ("requested type %s\n", str);*/
3835 if (!mono_reflection_parse_type (name, &info)) {
3836 g_list_free (info.modifiers);
3837 g_list_free (info.nested);
3841 if (info.assembly.name) {
3842 image = mono_image_loaded (info.assembly.name);
3843 /* do we need to load if it's not already loaded? */
3845 g_list_free (info.modifiers);
3846 g_list_free (info.nested);
3849 } else if (image == NULL) {
3850 image = mono_defaults.corlib;
3853 type = mono_reflection_get_type (image, &info, FALSE);
3854 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
3855 image = mono_defaults.corlib;
3856 type = mono_reflection_get_type (image, &info, FALSE);
3859 g_list_free (info.modifiers);
3860 g_list_free (info.nested);
3865 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
3867 int slen, type = t->type;
3872 case MONO_TYPE_BOOLEAN: {
3873 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
3878 case MONO_TYPE_CHAR:
3880 case MONO_TYPE_I2: {
3881 guint16 *val = g_malloc (sizeof (guint16));
3886 #if SIZEOF_VOID_P == 4
3892 case MONO_TYPE_I4: {
3893 guint32 *val = g_malloc (sizeof (guint32));
3898 #if SIZEOF_VOID_P == 8
3899 case MONO_TYPE_U: /* error out instead? this should probably not happen */
3904 case MONO_TYPE_I8: {
3905 guint64 *val = g_malloc (sizeof (guint64));
3910 case MONO_TYPE_VALUETYPE:
3911 if (t->data.klass->enumtype) {
3912 type = t->data.klass->enum_basetype->type;
3915 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
3918 case MONO_TYPE_STRING:
3919 if (*p == (char)0xFF) {
3923 slen = mono_metadata_decode_value (p, &p);
3925 return mono_string_new_len (mono_domain_get (), p, slen);
3926 case MONO_TYPE_CLASS: {
3930 slen = mono_metadata_decode_value (p, &p);
3931 n = g_memdup (p, slen + 1);
3933 t = mono_reflection_type_from_name (n, image);
3935 g_warning ("Cannot load type '%s'", n);
3938 return mono_type_get_object (mono_domain_get (), t);
3940 case MONO_TYPE_OBJECT: {
3948 } else if (subt == 0x55) {
3951 slen = mono_metadata_decode_value (p, &p);
3952 n = g_memdup (p, slen + 1);
3954 t = mono_reflection_type_from_name (n, image);
3956 g_warning ("Cannot load type '%s'", n);
3959 subc = mono_class_from_mono_type (t);
3960 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
3961 MonoType simple_type = {{0}};
3962 simple_type.type = subt;
3963 subc = mono_class_from_mono_type (&simple_type);
3965 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
3967 val = load_cattr_value (image, &subc->byval_arg, p, end);
3968 obj = mono_object_new (mono_domain_get (), subc);
3969 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
3973 case MONO_TYPE_SZARRAY:
3979 arr=mono_array_new(mono_domain_get(),mono_class_from_mono_type(t->data.type),alen);
3980 switch (t->data.type->type)
3984 case MONO_TYPE_BOOLEAN:
3985 for (i=0;i<alen;i++)
3987 MonoBoolean val=*p++;
3988 mono_array_set(arr,MonoBoolean,i,val);
3991 case MONO_TYPE_CHAR:
3994 for (i=0;i<alen;i++)
3996 guint16 val=read16(p);
3997 mono_array_set(arr,guint16,i,val);
4004 for (i=0;i<alen;i++)
4006 guint32 val=read32(p);
4007 mono_array_set(arr,guint32,i,val);
4014 for (i=0;i<alen;i++)
4016 guint64 val=read64(p);
4017 mono_array_set(arr,guint64,i,val);
4021 case MONO_TYPE_STRING:
4022 for (i=0;i<alen;i++)
4026 mono_array_set(arr,gpointer,i,NULL);
4031 slen=mono_metadata_decode_value(p,&p);
4032 mono_array_set(arr,gpointer,i,mono_string_new_len(mono_domain_get(),p,slen));
4038 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
4044 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
4050 type_is_reference (MonoType *type)
4052 switch (type->type) {
4053 case MONO_TYPE_BOOLEAN:
4054 case MONO_TYPE_CHAR:
4067 case MONO_TYPE_VALUETYPE:
4075 free_param_data (MonoMethodSignature *sig, void **params) {
4077 for (i = 0; i < sig->param_count; ++i) {
4078 if (!type_is_reference (sig->params [i]))
4079 g_free (params [i]);
4084 * Find the method index in the metadata methodDef table.
4085 * Later put these three helper methods in metadata and export them.
4088 find_method_index (MonoMethod *method) {
4089 MonoClass *klass = method->klass;
4092 for (i = 0; i < klass->method.count; ++i) {
4093 if (method == klass->methods [i])
4094 return klass->method.first + 1 + i;
4100 * Find the field index in the metadata FieldDef table.
4103 find_field_index (MonoClass *klass, MonoClassField *field) {
4106 for (i = 0; i < klass->field.count; ++i) {
4107 if (field == &klass->fields [i])
4108 return klass->field.first + 1 + i;
4114 * Find the property index in the metadata Property table.
4117 find_property_index (MonoClass *klass, MonoProperty *property) {
4120 for (i = 0; i < klass->property.count; ++i) {
4121 if (property == &klass->properties [i])
4122 return klass->property.first + 1 + i;
4128 * Find the event index in the metadata Event table.
4131 find_event_index (MonoClass *klass, MonoEvent *event) {
4134 for (i = 0; i < klass->event.count; ++i) {
4135 if (event == &klass->events [i])
4136 return klass->event.first + 1 + i;
4142 create_custom_attr (MonoImage *image, MonoMethod *method,
4143 const char *data, guint32 len)
4145 const char *p = data;
4147 guint32 i, j, num_named;
4151 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
4154 mono_class_init (method->klass);
4155 /*g_print ("got attr %s\n", method->klass->name);*/
4157 params = g_new (void*, method->signature->param_count);
4161 for (i = 0; i < method->signature->param_count; ++i) {
4162 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
4166 attr = mono_object_new (mono_domain_get (), method->klass);
4167 mono_runtime_invoke (method, attr, params, NULL);
4168 free_param_data (method->signature, params);
4170 num_named = read16 (named);
4172 for (j = 0; j < num_named; j++) {
4174 char *name, named_type;
4175 named_type = *named++;
4176 named++; /* type of data */
4177 name_len = mono_metadata_decode_blob_size (named, &named);
4178 name = g_malloc (name_len + 1);
4179 memcpy (name, named, name_len);
4180 name [name_len] = 0;
4182 if (named_type == 0x53) {
4183 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
4184 void *val = load_cattr_value (image, field->type, named, &named);
4185 mono_field_set_value (attr, field, val);
4186 if (!type_is_reference (field->type))
4188 } else if (named_type == 0x54) {
4189 MonoProperty *prop = mono_class_get_property_from_name (mono_object_class (attr), name);
4191 MonoType *prop_type;
4192 /* can we have more that 1 arg in a custom attr named property? */
4193 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
4194 pparams [0] = load_cattr_value (image, prop_type, named, &named);
4195 mono_property_set_value (prop, attr, pparams, NULL);
4196 if (!type_is_reference (prop_type))
4197 g_free (pparams [0]);
4206 * mono_reflection_get_custom_attrs:
4207 * @obj: a reflection object handle
4209 * Return an array with all the custom attributes defined of the
4210 * reflection handle @obj. The objects are fully build.
4213 mono_reflection_get_custom_attrs (MonoObject *obj)
4215 guint32 idx, mtoken, i, len;
4216 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
4224 MonoArray *dynamic_attrs = NULL;
4226 MONO_ARCH_SAVE_REGS;
4228 klass = obj->vtable->klass;
4229 /* FIXME: need to handle: Module */
4230 if (klass == mono_defaults.monotype_class) {
4231 MonoReflectionType *rtype = (MonoReflectionType*)obj;
4232 klass = mono_class_from_mono_type (rtype->type);
4233 idx = mono_metadata_token_index (klass->type_token);
4234 idx <<= CUSTOM_ATTR_BITS;
4235 idx |= CUSTOM_ATTR_TYPEDEF;
4236 image = klass->image;
4237 } else if (strcmp ("Assembly", klass->name) == 0) {
4238 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
4239 idx = 1; /* there is only one assembly */
4240 idx <<= CUSTOM_ATTR_BITS;
4241 idx |= CUSTOM_ATTR_ASSEMBLY;
4242 image = rassembly->assembly->image;
4243 } else if (strcmp ("MonoProperty", klass->name) == 0) {
4244 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
4245 idx = find_property_index (rprop->klass, rprop->property);
4246 idx <<= CUSTOM_ATTR_BITS;
4247 idx |= CUSTOM_ATTR_PROPERTY;
4248 image = rprop->klass->image;
4249 } else if (strcmp ("MonoEvent", klass->name) == 0) {
4250 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
4251 idx = find_event_index (revent->klass, revent->event);
4252 idx <<= CUSTOM_ATTR_BITS;
4253 idx |= CUSTOM_ATTR_EVENT;
4254 image = revent->klass->image;
4255 } else if (strcmp ("MonoField", klass->name) == 0) {
4256 MonoReflectionField *rfield = (MonoReflectionField*)obj;
4257 idx = find_field_index (rfield->klass, rfield->field);
4258 idx <<= CUSTOM_ATTR_BITS;
4259 idx |= CUSTOM_ATTR_FIELDDEF;
4260 image = rfield->klass->image;
4261 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
4262 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
4263 idx = find_method_index (rmethod->method);
4264 idx <<= CUSTOM_ATTR_BITS;
4265 idx |= CUSTOM_ATTR_METHODDEF;
4266 image = rmethod->method->klass->image;
4267 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
4268 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
4269 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
4270 guint32 method_index = find_method_index (rmethod->method);
4271 guint32 param_list, param_last, param_pos, found;
4273 image = rmethod->method->klass->image;
4274 ca = &image->tables [MONO_TABLE_METHOD];
4276 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
4277 if (method_index == ca->rows) {
4278 ca = &image->tables [MONO_TABLE_PARAM];
4279 param_last = ca->rows + 1;
4281 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
4282 ca = &image->tables [MONO_TABLE_PARAM];
4285 for (i = param_list; i < param_last; ++i) {
4286 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
4287 if (param_pos == param->PositionImpl) {
4293 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
4295 idx <<= CUSTOM_ATTR_BITS;
4296 idx |= CUSTOM_ATTR_PARAMDEF;
4297 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
4298 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
4299 dynamic_attrs = assemblyb->cattrs;
4301 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
4302 } else { /* handle other types here... */
4303 g_error ("get custom attrs not yet supported for %s", klass->name);
4306 if (dynamic_attrs) {
4307 len = mono_array_length (dynamic_attrs);
4308 for (i = 0; i < len; ++i) {
4309 MonoReflectionCustomAttr *cattr = (MonoReflectionCustomAttr*)mono_array_get (dynamic_attrs, gpointer, i);
4310 attr = create_custom_attr (image, cattr->ctor->method, mono_array_addr (cattr->data, int, 0), mono_array_length (cattr->data));
4311 list = g_list_prepend (list, attr);
4315 /* at this point image and index are set correctly for searching the custom attr */
4316 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4317 /* the table is not sorted */
4318 for (i = 0; i < ca->rows; ++i) {
4319 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
4320 if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
4322 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
4323 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
4324 case CUSTOM_ATTR_TYPE_METHODDEF:
4325 mtoken |= MONO_TOKEN_METHOD_DEF;
4327 case CUSTOM_ATTR_TYPE_MEMBERREF:
4328 mtoken |= MONO_TOKEN_MEMBER_REF;
4331 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
4334 method = mono_get_method (image, mtoken, NULL);
4336 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
4340 const char *data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
4341 data_len = mono_metadata_decode_value (data, &data);
4343 attr = create_custom_attr (image, method, data, data_len);
4345 list = g_list_prepend (list, attr);
4349 len = g_list_length (list);
4351 * The return type is really object[], but System/Attribute.cs does a cast
4352 * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
4353 * probably fix that.
4355 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
4356 result = mono_array_new (mono_domain_get (), klass, len);
4357 for (i = 0; i < len; ++i) {
4358 mono_array_set (result, gpointer, i, list->data);
4361 g_list_free (g_list_first (list));
4366 static MonoMethodSignature*
4367 parameters_to_signature (MonoArray *parameters) {
4368 MonoMethodSignature *sig;
4371 count = parameters? mono_array_length (parameters): 0;
4373 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
4374 sig->param_count = count;
4375 sig->sentinelpos = -1; /* FIXME */
4376 for (i = 0; i < count; ++i) {
4377 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
4378 sig->params [i] = pt->type;
4383 static MonoMethodSignature*
4384 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
4385 MonoMethodSignature *sig;
4387 sig = parameters_to_signature (ctor->parameters);
4388 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4389 sig->ret = &mono_defaults.void_class->byval_arg;
4393 static MonoMethodSignature*
4394 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
4395 MonoMethodSignature *sig;
4397 sig = parameters_to_signature (method->parameters);
4398 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4399 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
4404 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
4406 MonoClass *klass = mono_object_class (prop);
4407 if (strcmp (klass->name, "PropertyBuilder") == 0) {
4408 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
4409 *name = mono_string_to_utf8 (pb->name);
4410 *type = pb->type->type;
4412 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
4413 *name = g_strdup (p->property->name);
4414 if (p->property->get)
4415 *type = p->property->get->signature->ret;
4417 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
4422 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
4424 MonoClass *klass = mono_object_class (field);
4425 if (strcmp (klass->name, "FieldBuilder") == 0) {
4426 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
4427 *name = mono_string_to_utf8 (fb->name);
4428 *type = fb->type->type;
4430 MonoReflectionField *f = (MonoReflectionField *)field;
4431 *name = g_strdup (f->field->name);
4432 *type = f->field->type;
4437 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
4438 char *name, *result;
4442 name = mono_type_get_name (type);
4443 klass = my_mono_class_from_mono_type (type);
4444 ta = klass->image->assembly;
4445 if (ta == ass || klass->image == mono_defaults.corlib)
4448 /* missing public key */
4449 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
4450 name, ta->aname.name,
4451 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
4452 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
4458 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
4461 MonoTypeEnum simple_type;
4463 if ((p-buffer) + 10 >= *buflen) {
4466 newbuf = g_realloc (buffer, *buflen);
4467 p = newbuf + (p-buffer);
4470 argval = ((char*)arg + sizeof (MonoObject));
4471 simple_type = type->type;
4473 switch (simple_type) {
4474 case MONO_TYPE_BOOLEAN:
4479 case MONO_TYPE_CHAR:
4482 swap_with_size (p, argval, 2, 1);
4488 swap_with_size (p, argval, 4, 1);
4494 swap_with_size (p, argval, 8, 1);
4497 case MONO_TYPE_VALUETYPE:
4498 if (type->data.klass->enumtype) {
4499 simple_type = type->data.klass->enum_basetype->type;
4502 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
4505 case MONO_TYPE_STRING: {
4512 str = mono_string_to_utf8 ((MonoString*)arg);
4513 slen = strlen (str);
4514 if ((p-buffer) + 10 + slen >= *buflen) {
4518 newbuf = g_realloc (buffer, *buflen);
4519 p = newbuf + (p-buffer);
4522 mono_metadata_encode_value (slen, p, &p);
4523 memcpy (p, str, slen);
4528 case MONO_TYPE_CLASS: {
4531 MonoClass *k = mono_object_class (arg);
4532 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
4533 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
4534 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
4536 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
4537 slen = strlen (str);
4538 if ((p-buffer) + 10 + slen >= *buflen) {
4542 newbuf = g_realloc (buffer, *buflen);
4543 p = newbuf + (p-buffer);
4546 mono_metadata_encode_value (slen, p, &p);
4547 memcpy (p, str, slen);
4552 /* it may be a boxed value or a Type */
4553 case MONO_TYPE_OBJECT: {
4554 MonoClass *klass = mono_object_class (arg);
4558 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
4561 } else if (klass->enumtype) {
4563 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
4564 *p++ = simple_type = klass->byval_arg.type;
4567 g_error ("unhandled type in custom attr");
4569 str = type_get_qualified_name (klass->enum_basetype, NULL);
4570 slen = strlen (str);
4571 if ((p-buffer) + 10 + slen >= *buflen) {
4575 newbuf = g_realloc (buffer, *buflen);
4576 p = newbuf + (p-buffer);
4579 mono_metadata_encode_value (slen, p, &p);
4580 memcpy (p, str, slen);
4583 simple_type = klass->enum_basetype->type;
4587 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
4590 *retbuffer = buffer;
4594 * mono_reflection_get_custom_attrs_blob:
4595 * @ctor: custom attribute constructor
4596 * @ctorArgs: arguments o the constructor
4602 * Creates the blob of data that needs to be saved in the metadata and that represents
4603 * the custom attributed described by @ctor, @ctorArgs etc.
4604 * Returns: a Byte array representing the blob of data.
4607 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
4610 MonoMethodSignature *sig;
4615 MONO_ARCH_SAVE_REGS;
4617 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4618 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
4620 sig = ((MonoReflectionMethod*)ctor)->method->signature;
4623 p = buffer = g_malloc (buflen);
4624 /* write the prolog */
4627 for (i = 0; i < sig->param_count; ++i) {
4628 if (sig->params[i]->type==MONO_TYPE_SZARRAY)
4630 guint32 alen=mono_array_length(ctorArgs) - i;
4632 if ((p-buffer) + 10 >= buflen) {
4635 newbuf = g_realloc (buffer, buflen);
4636 p = newbuf + (p-buffer);
4640 *p++=(alen>>8)&0xff;
4641 *p++=(alen>>16)&0xff;
4642 *p++=(alen>>24)&0xff;
4643 for (j=0;j<alen;j++)
4645 arg=(MonoObject*)mono_array_get(ctorArgs,gpointer,i+j);
4646 encode_cattr_value(buffer,p,&buffer,&p,&buflen,sig->params[i]->data.type,arg);
4651 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
4652 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
4657 i += mono_array_length (properties);
4659 i += mono_array_length (fields);
4661 *p++ = (i >> 8) & 0xff;
4664 for (i = 0; i < mono_array_length (properties); ++i) {
4669 prop = mono_array_get (properties, gpointer, i);
4670 get_prop_name_and_type (prop, &pname, &ptype);
4671 *p++ = 0x54; /* PROPERTY signature */
4672 mono_metadata_encode_value (ptype->type, p, &p);
4673 len = strlen (pname);
4674 mono_metadata_encode_value (len, p, &p);
4675 memcpy (p, pname, len);
4677 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
4684 for (i = 0; i < mono_array_length (fields); ++i) {
4689 field = mono_array_get (fields, gpointer, i);
4690 get_field_name_and_type (field, &fname, &ftype);
4691 *p++ = 0x53; /* FIELD signature */
4692 mono_metadata_encode_value (ftype->type, p, &p);
4693 len = strlen (fname);
4694 mono_metadata_encode_value (len, p, &p);
4695 memcpy (p, fname, len);
4697 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
4702 g_assert (p - buffer <= buflen);
4703 buflen = p - buffer;
4704 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
4705 p = mono_array_addr (result, char, 0);
4706 memcpy (p, buffer, buflen);
4708 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
4714 * mono_reflection_setup_internal_class:
4715 * @tb: a TypeBuilder object
4717 * Creates a MonoClass that represents the TypeBuilder.
4718 * This is a trick that lets us simplify a lot of reflection code
4719 * (and will allow us to support Build and Run assemblies easier).
4722 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
4724 MonoClass *klass, *parent;
4726 MONO_ARCH_SAVE_REGS;
4728 klass = g_new0 (MonoClass, 1);
4730 klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
4733 /* check so we can compile corlib correctly */
4734 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
4735 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
4736 parent = tb->parent->type->data.klass;
4738 parent = my_mono_class_from_mono_type (tb->parent->type);
4742 klass->inited = 1; /* we lie to the runtime */
4743 klass->name = mono_string_to_utf8 (tb->name);
4744 klass->name_space = mono_string_to_utf8 (tb->nspace);
4745 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
4746 klass->flags = tb->attrs;
4748 klass->element_class = klass;
4749 klass->reflection_info = tb; /* need to pin. */
4751 /* Put into cache so mono_class_get () will find it */
4752 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
4755 mono_g_hash_table_insert (tb->module->assemblyb->dynamic_assembly->tokens,
4756 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
4760 mono_class_setup_parent (klass, parent);
4761 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
4762 const char *old_n = klass->name;
4763 /* trick to get relative numbering right when compiling corlib */
4764 klass->name = "BuildingObject";
4765 mono_class_setup_parent (klass, mono_defaults.object_class);
4766 klass->name = old_n;
4768 mono_class_setup_mono_type (klass);
4771 * FIXME: handle interfaces.
4774 tb->type.type = &klass->byval_arg;
4776 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
4780 * mono_reflection_create_internal_class:
4781 * @tb: a TypeBuilder object
4783 * Actually create the MonoClass that is associated with the TypeBuilder.
4786 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
4790 MONO_ARCH_SAVE_REGS;
4792 klass = my_mono_class_from_mono_type (tb->type.type);
4794 if (klass->enumtype && klass->enum_basetype == NULL) {
4795 MonoReflectionFieldBuilder *fb;
4797 g_assert (tb->fields != NULL);
4798 g_assert (mono_array_length (tb->fields) >= 1);
4800 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
4802 klass->enum_basetype = fb->type->type;
4803 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
4804 if (!klass->element_class)
4805 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
4806 klass->instance_size = klass->element_class->instance_size;
4807 klass->size_inited = 1;
4809 * this is almost safe to do with enums and it's needed to be able
4810 * to create objects of the enum type (for use in SetConstant).
4812 /* FIXME: Does this mean enums can't have method overrides ? */
4813 mono_class_setup_vtable (klass, NULL, 0);
4818 reflection_methodbuilder_to_mono_method (MonoClass *klass,
4819 ReflectionMethodBuilder *rmb,
4820 MonoMethodSignature *sig)
4823 MonoMethodNormal *pm;
4825 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
4826 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
4827 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
4829 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
4831 pm = (MonoMethodNormal*)m;
4834 m->flags = rmb->attrs;
4835 m->iflags = rmb->iattrs;
4836 m->name = mono_string_to_utf8 (rmb->name);
4840 /* TODO: What about m->token ? */
4841 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
4842 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
4845 m->addr = mono_lookup_internal_call (m);
4846 m->signature->pinvoke = 1;
4847 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
4849 m->signature->pinvoke = 1;
4851 } else if (!m->klass->dummy &&
4852 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
4853 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
4854 MonoMethodHeader *header;
4856 gint32 max_stack, i;
4857 gint32 num_locals = 0;
4858 gint32 num_clauses = 0;
4862 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
4863 code_size = rmb->ilgen->code_len;
4864 max_stack = rmb->ilgen->max_stack;
4865 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
4866 if (rmb->ilgen->ex_handlers)
4867 num_clauses = method_count_clauses (rmb->ilgen);
4870 code = mono_array_addr (rmb->code, guint8, 0);
4871 code_size = mono_array_length (rmb->code);
4872 /* we probably need to run a verifier on the code... */
4882 header = g_malloc0 (sizeof (MonoMethodHeader) +
4883 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
4884 header->code_size = code_size;
4885 header->code = g_malloc (code_size);
4886 memcpy ((char*)header->code, code, code_size);
4887 header->max_stack = max_stack;
4888 header->init_locals = rmb->init_locals;
4889 header->num_locals = num_locals;
4891 for (i = 0; i < num_locals; ++i) {
4892 MonoReflectionLocalBuilder *lb =
4893 mono_array_get (rmb->ilgen->locals,
4894 MonoReflectionLocalBuilder*, i);
4896 header->locals [i] = g_new0 (MonoType, 1);
4897 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
4900 header->num_clauses = num_clauses;
4902 header->clauses = method_encode_clauses (klass->image->assembly->dynamic,
4907 pm->header = header;
4914 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
4916 ReflectionMethodBuilder rmb;
4918 MonoMethodSignature *sig;
4920 name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
4922 sig = ctor_builder_to_signature (mb);
4924 rmb.ilgen = mb->ilgen;
4925 rmb.parameters = mb->parameters;
4926 rmb.pinfo = mb->pinfo;
4927 rmb.attrs = mb->attrs;
4928 rmb.iattrs = mb->iattrs;
4929 rmb.call_conv = mb->call_conv;
4930 rmb.type = mb->type;
4931 rmb.name = mono_string_new (mono_domain_get (), name);
4932 rmb.table_idx = &mb->table_idx;
4933 rmb.init_locals = mb->init_locals;
4936 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
4941 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
4943 ReflectionMethodBuilder rmb;
4944 MonoMethodSignature *sig;
4946 sig = method_builder_to_signature (mb);
4948 rmb.ilgen = mb->ilgen;
4949 rmb.parameters = mb->parameters;
4950 rmb.pinfo = mb->pinfo;
4951 rmb.attrs = mb->attrs;
4952 rmb.iattrs = mb->iattrs;
4953 rmb.call_conv = mb->call_conv;
4954 rmb.type = mb->type;
4955 rmb.name = mb->name;
4956 rmb.table_idx = &mb->table_idx;
4957 rmb.init_locals = mb->init_locals;
4958 rmb.code = mb->code;
4960 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
4965 ensure_runtime_vtable (MonoClass *klass)
4967 MonoReflectionTypeBuilder *tb = klass->reflection_info;
4968 int i, num, j, onum;
4969 MonoMethod **overrides;
4971 if (!tb || klass->wastypebuilder)
4974 ensure_runtime_vtable (klass->parent);
4976 num = tb->ctors? mono_array_length (tb->ctors): 0;
4977 num += tb->methods? mono_array_length (tb->methods): 0;
4978 klass->method.count = num;
4979 klass->methods = g_new (MonoMethod*, num);
4980 num = tb->ctors? mono_array_length (tb->ctors): 0;
4981 for (i = 0; i < num; ++i)
4982 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
4983 num = tb->methods? mono_array_length (tb->methods): 0;
4985 for (i = 0; i < num; ++i)
4986 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
4988 klass->wastypebuilder = TRUE;
4989 if (tb->interfaces) {
4990 klass->interface_count = mono_array_length (tb->interfaces);
4991 klass->interfaces = g_new (MonoClass*, klass->interface_count);
4992 for (i = 0; i < klass->interface_count; ++i) {
4993 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
4994 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
5001 for (i = 0; i < mono_array_length (tb->methods); ++i) {
5002 MonoReflectionMethodBuilder *mb =
5003 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
5004 if (mb->override_method)
5009 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
5013 for (i = 0; i < mono_array_length (tb->methods); ++i) {
5014 MonoReflectionMethodBuilder *mb =
5015 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
5016 if (mb->override_method) {
5017 /* FIXME: What if 'override_method' is a MethodBuilder ? */
5018 overrides [onum * 2] =
5019 mb->override_method->method;
5020 overrides [onum * 2 + 1] =
5023 g_assert (mb->mhandle);
5030 mono_class_setup_vtable (klass, overrides, onum);
5034 typebuilder_setup_fields (MonoClass *klass)
5036 MonoReflectionTypeBuilder *tb = klass->reflection_info;
5037 MonoReflectionFieldBuilder *fb;
5038 MonoClassField *field;
5041 klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
5043 if (!klass->field.count)
5046 klass->fields = g_new0 (MonoClassField, klass->field.count);
5048 for (i = 0; i < klass->field.count; ++i) {
5049 fb = mono_array_get (tb->fields, gpointer, i);
5050 field = &klass->fields [i];
5051 field->name = mono_string_to_utf8 (fb->name);
5053 /* FIXME: handle type modifiers */
5054 field->type = g_memdup (fb->type->type, sizeof (MonoType));
5055 field->type->attrs = fb->attrs;
5057 field->type = fb->type->type;
5059 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
5060 field->data = mono_array_addr (fb->rva_data, char, 0);
5061 if (fb->offset != -1)
5062 field->offset = fb->offset;
5063 field->parent = klass;
5066 mono_class_layout_fields (klass);
5070 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
5073 MonoReflectionType* res;
5075 MONO_ARCH_SAVE_REGS;
5077 klass = my_mono_class_from_mono_type (tb->type.type);
5080 * Fields to set in klass:
5081 * the various flags: delegate/unicode/contextbound etc.
5087 klass->flags = tb->attrs;
5088 klass->element_class = klass;
5090 /* enums are done right away */
5091 if (!klass->enumtype)
5092 ensure_runtime_vtable (klass);
5094 /* fields and object layout */
5095 if (klass->parent) {
5096 if (!klass->parent->size_inited)
5097 mono_class_init (klass->parent);
5098 klass->instance_size += klass->parent->instance_size;
5099 klass->class_size += klass->parent->class_size;
5100 klass->min_align = klass->parent->min_align;
5102 klass->instance_size = sizeof (MonoObject);
5103 klass->min_align = 1;
5105 /* FIXME: handle packing_size and instance_size */
5106 typebuilder_setup_fields (klass);
5108 /* FIXME: properties */
5110 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5111 /* with enums res == tb: need to fix that. */
5112 if (!klass->enumtype)
5113 g_assert (res != (MonoReflectionType*)tb);
5118 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
5120 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5121 guint32 na = mono_array_length (sig->arguments);
5126 MONO_ARCH_SAVE_REGS;
5128 p = buf = g_malloc (10 + na * 10);
5130 mono_metadata_encode_value (0x07, p, &p);
5131 mono_metadata_encode_value (na, p, &p);
5132 for (i = 0; i < na; ++i) {
5133 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5134 encode_reflection_type (assembly, type, p, &p);
5138 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5139 p = mono_array_addr (result, char, 0);
5140 memcpy (p, buf, buflen);
5147 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
5149 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5150 guint32 na = mono_array_length (sig->arguments);
5155 MONO_ARCH_SAVE_REGS;
5157 p = buf = g_malloc (10 + na * 10);
5159 mono_metadata_encode_value (0x06, p, &p);
5160 for (i = 0; i < na; ++i) {
5161 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5162 encode_reflection_type (assembly, type, p, &p);
5166 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5167 p = mono_array_addr (result, char, 0);
5168 memcpy (p, buf, buflen);
5175 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
5177 MonoDynamicAssembly *assembly = image->assembly->dynamic;
5181 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5184 if (strcmp (obj->vtable->klass->name, "String") == 0) {
5188 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
5189 MonoReflectionType *tb = (MonoReflectionType*)obj;
5190 result = mono_class_from_mono_type (tb->type);
5193 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
5194 result = ((MonoReflectionMethod*)obj)->method;
5197 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
5198 result = ((MonoReflectionMethod*)obj)->method;
5201 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
5202 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
5203 result = mb->mhandle;
5205 /* Type is not yet created */
5206 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5208 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5211 * Hopefully this has been filled in by calling CreateType() on the
5215 * TODO: This won't work if the application finishes another
5216 * TypeBuilder instance instead of this one.
5218 result = mb->mhandle;
5221 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
5222 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
5224 result = cb->mhandle;
5226 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
5228 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5229 result = cb->mhandle;
5232 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
5233 result = ((MonoReflectionField*)obj)->field;
5236 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
5237 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
5238 result = fb->handle;
5241 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
5243 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5244 result = fb->handle;
5247 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
5248 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
5251 klass = tb->type.type->data.klass;
5252 if (klass->wastypebuilder) {
5253 /* Already created */
5257 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5258 result = tb->type.type->data.klass;
5262 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
5263 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
5264 MonoMethodSignature *sig;
5267 if (helper->arguments)
5268 nargs = mono_array_length (helper->arguments);
5272 sig = mono_metadata_signature_alloc (image, nargs);
5273 sig->explicit_this = helper->call_conv & 64;
5274 sig->hasthis = helper->call_conv & 32;
5276 if (helper->call_conv == 0) /* unmanaged */
5277 sig->call_convention = helper->unmanaged_call_conv - 1;
5279 if (helper->call_conv & 0x02)
5280 sig->call_convention = MONO_CALL_VARARG;
5282 sig->call_convention = MONO_CALL_DEFAULT;
5284 sig->param_count = nargs;
5285 /* TODO: Copy type ? */
5286 sig->ret = helper->return_type->type;
5287 for (i = 0; i < nargs; ++i) {
5288 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
5289 sig->params [i] = rt->type;
5295 g_print (obj->vtable->klass->name);
5296 g_assert_not_reached ();