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);
1428 * If it's in the same module:
1430 if (!force_ref && (klass->image == assembly->assembly.image)) {
1431 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1432 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1433 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
1437 if (klass->nested_in) {
1438 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1439 /* get the typeref idx of the enclosing type */
1440 enclosing >>= TYPEDEFORREF_BITS;
1441 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1443 scope = resolution_scope_from_image (assembly, klass->image);
1445 table = &assembly->tables [MONO_TABLE_TYPEREF];
1446 alloc_table (table, table->rows + 1);
1447 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1448 values [MONO_TYPEREF_SCOPE] = scope;
1449 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1450 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1451 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1452 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1454 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
1459 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1461 return mono_image_typedef_or_ref_aux (assembly, type, FALSE);
1465 * Insert a memberef row into the metadata: the token that point to the memberref
1466 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1467 * mono_image_get_fieldref_token()).
1468 * The sig param is an index to an already built signature.
1471 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1473 MonoDynamicTable *table;
1475 guint32 token, pclass;
1478 parent = mono_image_typedef_or_ref_aux (assembly, type, TRUE);
1479 switch (parent & TYPEDEFORREF_MASK) {
1480 case TYPEDEFORREF_TYPEREF:
1481 pclass = MEMBERREF_PARENT_TYPEREF;
1483 case TYPEDEFORREF_TYPESPEC:
1484 pclass = MEMBERREF_PARENT_TYPESPEC;
1486 case TYPEDEFORREF_TYPEDEF:
1487 /* should never get here */
1489 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
1492 /* extract the index */
1493 parent >>= TYPEDEFORREF_BITS;
1495 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1496 alloc_table (table, table->rows + 1);
1497 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1498 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1499 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1500 values [MONO_MEMBERREF_SIGNATURE] = sig;
1501 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1508 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1512 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1515 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1516 method->name, method_encode_signature (assembly, method->signature));
1517 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1522 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1526 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1529 field->parent = klass;
1530 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
1531 field->name, fieldref_encode_signature (assembly, field));
1532 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1537 mono_reflection_encode_sighelper (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1545 char *b = blob_size;
1548 g_assert (helper->type == 2);
1550 if (helper->arguments)
1551 nargs = mono_array_length (helper->arguments);
1555 size = 10 + (nargs * 10);
1557 p = buf = g_malloc (size);
1559 /* Encode calling convention */
1560 /* Change Any to Standard */
1561 if ((helper->call_conv & 0x03) == 0x03)
1562 helper->call_conv = 0x01;
1563 /* explicit_this implies has_this */
1564 if (helper->call_conv & 0x40)
1565 helper->call_conv &= 0x20;
1567 if (helper->call_conv == 0) /* Unmanaged */
1568 *p = helper->unmanaged_call_conv - 1;
1571 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
1572 if (helper->call_conv & 0x02) /* varargs */
1577 mono_metadata_encode_value (nargs, p, &p);
1578 encode_reflection_type (assembly, helper->return_type, p, &p);
1579 for (i = 0; i < nargs; ++i) {
1580 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
1581 encode_reflection_type (assembly, pt, p, &p);
1584 g_assert (p - buf < size);
1585 mono_metadata_encode_value (p-buf, b, &b);
1586 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1593 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1596 MonoDynamicTable *table;
1599 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1600 idx = table->next_idx ++;
1602 alloc_table (table, table->rows);
1603 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1605 values [MONO_STAND_ALONE_SIGNATURE] =
1606 mono_reflection_encode_sighelper (assembly, helper);
1612 reflection_cc_to_file (int call_conv) {
1613 switch (call_conv & 0x3) {
1615 case 1: return MONO_CALL_DEFAULT;
1616 case 2: return MONO_CALL_VARARG;
1618 g_assert_not_reached ();
1625 MonoMethodSignature *sig;
1631 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1636 MonoMethodSignature *sig;
1639 name = mono_string_to_utf8 (m->name);
1640 nparams = mono_array_length (m->parameters);
1641 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1643 sig->call_convention = reflection_cc_to_file (m->call_conv);
1644 sig->param_count = nparams;
1645 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1646 for (i = 0; i < nparams; ++i) {
1647 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1648 sig->params [i] = t->type;
1651 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1653 if (strcmp (name, am->name) == 0 &&
1654 mono_metadata_type_equal (am->parent, m->parent->type) &&
1655 mono_metadata_signature_equal (am->sig, sig)) {
1661 am = g_new0 (ArrayMethod, 1);
1664 am->parent = m->parent->type;
1665 am->token = mono_image_get_memberref_token (assembly, am->parent,
1666 name, method_encode_signature (assembly, sig));
1667 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1668 m->table_idx = am->token & 0xffffff;
1673 * Insert into the metadata tables all the info about the TypeBuilder tb.
1674 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1677 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1679 MonoDynamicTable *table;
1681 int i, is_object = 0, is_system = 0;
1684 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1685 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1686 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1687 n = mono_string_to_utf8 (tb->name);
1688 if (strcmp (n, "Object") == 0)
1690 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1692 n = mono_string_to_utf8 (tb->nspace);
1693 if (strcmp (n, "System") == 0)
1695 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1697 if (tb->parent && !(is_system && is_object) &&
1698 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
1699 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1701 values [MONO_TYPEDEF_EXTENDS] = 0;
1702 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1703 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1706 * if we have explicitlayout or sequentiallayouts, output data in the
1707 * ClassLayout table.
1709 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1710 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1712 alloc_table (table, table->rows);
1713 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1714 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1715 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1716 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1719 /* handle interfaces */
1720 if (tb->interfaces) {
1721 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1723 table->rows += mono_array_length (tb->interfaces);
1724 alloc_table (table, table->rows);
1725 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1726 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1727 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1728 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1729 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1730 values += MONO_INTERFACEIMPL_SIZE;
1736 table = &assembly->tables [MONO_TABLE_FIELD];
1737 table->rows += mono_array_length (tb->fields);
1738 alloc_table (table, table->rows);
1739 for (i = 0; i < mono_array_length (tb->fields); ++i)
1740 mono_image_get_field_info (
1741 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1744 /* handle constructors */
1746 table = &assembly->tables [MONO_TABLE_METHOD];
1747 table->rows += mono_array_length (tb->ctors);
1748 alloc_table (table, table->rows);
1749 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1750 mono_image_get_ctor_info (domain,
1751 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1754 /* handle methods */
1756 table = &assembly->tables [MONO_TABLE_METHOD];
1757 table->rows += mono_array_length (tb->methods);
1758 alloc_table (table, table->rows);
1759 for (i = 0; i < mono_array_length (tb->methods); ++i)
1760 mono_image_get_method_info (
1761 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1764 /* Do the same with properties etc.. */
1765 if (tb->events && mono_array_length (tb->events)) {
1766 table = &assembly->tables [MONO_TABLE_EVENT];
1767 table->rows += mono_array_length (tb->events);
1768 alloc_table (table, table->rows);
1769 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1771 alloc_table (table, table->rows);
1772 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1773 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1774 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1775 for (i = 0; i < mono_array_length (tb->events); ++i)
1776 mono_image_get_event_info (
1777 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1779 if (tb->properties && mono_array_length (tb->properties)) {
1780 table = &assembly->tables [MONO_TABLE_PROPERTY];
1781 table->rows += mono_array_length (tb->properties);
1782 alloc_table (table, table->rows);
1783 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1785 alloc_table (table, table->rows);
1786 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1787 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1788 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1789 for (i = 0; i < mono_array_length (tb->properties); ++i)
1790 mono_image_get_property_info (
1791 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1794 MonoDynamicTable *ntable;
1796 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1797 table->rows += mono_array_length (tb->subtypes);
1798 alloc_table (table, table->rows);
1800 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1801 ntable->rows += mono_array_length (tb->subtypes);
1802 alloc_table (ntable, ntable->rows);
1803 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1805 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1806 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1808 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1809 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1810 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1811 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1812 mono_string_to_utf8 (tb->name), tb->table_idx,
1813 ntable->next_idx, ntable->rows);*/
1814 values += MONO_NESTED_CLASS_SIZE;
1817 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1818 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1820 mono_image_get_type_info (domain, subtype, assembly);
1826 assign_type_idx (MonoReflectionTypeBuilder *type, MonoDynamicTable *table)
1830 type->table_idx = table->next_idx ++;
1831 if (!type->subtypes)
1833 for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1834 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1835 assign_type_idx (subtype, table);
1840 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
1845 for (i = 0; i < mono_array_length (pinfo); ++i) {
1846 MonoReflectionParamBuilder *pb;
1847 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
1850 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
1855 type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
1858 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1860 for (i = 0; i < mono_array_length (tb->fields); ++i) {
1861 MonoReflectionFieldBuilder* fb;
1862 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
1863 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
1867 for (i = 0; i < mono_array_length (tb->events); ++i) {
1868 MonoReflectionEventBuilder* eb;
1869 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
1870 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1873 if (tb->properties) {
1874 for (i = 0; i < mono_array_length (tb->properties); ++i) {
1875 MonoReflectionPropertyBuilder* pb;
1876 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
1877 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
1881 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
1882 MonoReflectionCtorBuilder* cb;
1883 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
1884 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
1885 params_add_cattrs (assembly, cb->pinfo);
1890 for (i = 0; i < mono_array_length (tb->methods); ++i) {
1891 MonoReflectionMethodBuilder* mb;
1892 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
1893 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
1894 params_add_cattrs (assembly, mb->pinfo);
1899 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
1900 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
1905 module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
1908 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1910 /* no types in the module */
1914 for (i = 0; i < mono_array_length (mb->types); ++i)
1915 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
1919 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1921 MonoDynamicTable *table;
1925 table = &assembly->tables [MONO_TABLE_MODULE];
1926 mb->table_idx = table->next_idx ++;
1927 name = mono_string_to_utf8 (mb->module.name);
1928 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1930 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1933 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1934 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1935 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1937 /* no types in the module */
1942 * fill-in info in other tables as well.
1944 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1945 table->rows += mono_array_length (mb->types);
1946 alloc_table (table, table->rows);
1948 * We assign here the typedef indexes to avoid mismatches if a type that
1949 * has not yet been stored in the tables is referenced by another type.
1951 for (i = 0; i < mono_array_length (mb->types); ++i) {
1952 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1953 assign_type_idx (type, table);
1955 for (i = 0; i < mono_array_length (mb->types); ++i)
1956 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1959 #define align_pointer(base,p)\
1961 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1963 (p) += 4 - (__diff & 3);\
1967 compare_semantics (const void *a, const void *b)
1969 const guint32 *a_values = a;
1970 const guint32 *b_values = b;
1971 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
1974 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
1978 compare_custom_attrs (const void *a, const void *b)
1980 const guint32 *a_values = a;
1981 const guint32 *b_values = b;
1983 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
1987 compare_field_marshal (const void *a, const void *b)
1989 const guint32 *a_values = a;
1990 const guint32 *b_values = b;
1992 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
1996 compare_nested (const void *a, const void *b)
1998 const guint32 *a_values = a;
1999 const guint32 *b_values = b;
2001 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
2005 * build_compressed_metadata() fills in the blob of data that represents the
2006 * raw metadata as it will be saved in the PE file. The five streams are output
2007 * and the metadata tables are comnpressed from the guint32 array representation,
2008 * to the compressed on-disk format.
2011 build_compressed_metadata (MonoDynamicAssembly *assembly)
2013 MonoDynamicTable *table;
2015 guint64 valid_mask = 0;
2016 guint64 sorted_mask;
2017 guint32 heapt_size = 0;
2018 guint32 meta_size = 256; /* allow for header and other stuff */
2019 guint32 table_offset;
2020 guint32 ntables = 0;
2027 * We need to use the current ms version or the ms runtime it won't find
2028 * the support dlls. D'oh!
2029 * const char *version = "mono-" VERSION;
2031 const char *version = "v1.0.3705";
2034 MonoDynamicStream *stream;
2035 } stream_desc [] = {
2036 {"#~", &assembly->tstream},
2037 {"#Strings", &assembly->sheap},
2038 {"#US", &assembly->us},
2039 {"#Blob", &assembly->blob},
2040 {"#GUID", &assembly->guid}
2043 /* tables that are sorted */
2044 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
2045 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
2046 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
2047 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
2048 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
2049 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
2051 /* Compute table sizes */
2052 /* the MonoImage has already been created in mono_image_basic_init() */
2053 meta = assembly->assembly.image;
2055 /* Setup the info used by compute_sizes () */
2056 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
2057 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
2058 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
2060 meta_size += assembly->blob.index;
2061 meta_size += assembly->guid.index;
2062 meta_size += assembly->sheap.index;
2063 meta_size += assembly->us.index;
2065 for (i=0; i < 64; ++i)
2066 meta->tables [i].rows = assembly->tables [i].rows;
2068 for (i = 0; i < 64; i++){
2069 if (meta->tables [i].rows == 0)
2071 valid_mask |= (guint64)1 << i;
2073 meta->tables [i].row_size = mono_metadata_compute_size (
2074 meta, i, &meta->tables [i].size_bitfield);
2075 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
2077 heapt_size += 24; /* #~ header size */
2078 heapt_size += ntables * 4;
2079 meta_size += heapt_size;
2080 meta->raw_metadata = g_malloc0 (meta_size);
2081 p = meta->raw_metadata;
2082 /* the metadata signature */
2083 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
2084 /* version numbers and 4 bytes reserved */
2085 int16val = (guint16*)p;
2086 *int16val++ = GUINT16_TO_LE (1);
2087 *int16val = GUINT16_TO_LE (1);
2089 /* version string */
2090 int32val = (guint32*)p;
2091 *int32val = GUINT32_TO_LE ((strlen (version) + 3) & (~3)); /* needs to be multiple of 4 */
2093 memcpy (p, version, GUINT32_FROM_LE (*int32val));
2094 p += GUINT32_FROM_LE (*int32val);
2095 align_pointer (meta->raw_metadata, p);
2096 int16val = (guint16*)p;
2097 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
2098 *int16val = GUINT16_TO_LE (5); /* number of streams */
2102 * write the stream info.
2104 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
2105 table_offset += 3; table_offset &= ~3;
2107 assembly->tstream.index = heapt_size;
2108 for (i = 0; i < 5; ++i) {
2109 int32val = (guint32*)p;
2110 stream_desc [i].stream->offset = table_offset;
2111 *int32val++ = GUINT32_TO_LE (table_offset);
2112 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
2113 table_offset += GUINT32_FROM_LE (*int32val);
2114 table_offset += 3; table_offset &= ~3;
2116 strcpy (p, stream_desc [i].name);
2117 p += strlen (stream_desc [i].name) + 1;
2118 align_pointer (meta->raw_metadata, p);
2121 * now copy the data, the table stream header and contents goes first.
2123 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
2124 p = meta->raw_metadata + assembly->tstream.offset;
2125 int32val = (guint32*)p;
2126 *int32val = GUINT32_TO_LE (0); /* reserved */
2128 *p++ = 1; /* version */
2130 if (meta->idx_string_wide)
2132 if (meta->idx_guid_wide)
2134 if (meta->idx_blob_wide)
2137 *p++ = 0; /* reserved */
2138 int64val = (guint64*)p;
2139 *int64val++ = GUINT64_TO_LE (valid_mask);
2140 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
2142 int32val = (guint32*)p;
2143 for (i = 0; i < 64; i++){
2144 if (meta->tables [i].rows == 0)
2146 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
2148 p = (unsigned char*)int32val;
2150 /* sort the tables that still need sorting */
2151 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2153 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
2154 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2156 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
2157 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2159 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
2160 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2162 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
2164 /* compress the tables */
2165 for (i = 0; i < 64; i++){
2168 guint32 bitfield = meta->tables [i].size_bitfield;
2169 if (!meta->tables [i].rows)
2171 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
2172 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
2173 meta->tables [i].base = p;
2174 for (row = 1; row <= meta->tables [i].rows; ++row) {
2175 values = assembly->tables [i].values + row * assembly->tables [i].columns;
2176 for (col = 0; col < assembly->tables [i].columns; ++col) {
2177 switch (mono_metadata_table_size (bitfield, col)) {
2179 *p++ = values [col];
2182 *p++ = values [col] & 0xff;
2183 *p++ = (values [col] >> 8) & 0xff;
2186 *p++ = values [col] & 0xff;
2187 *p++ = (values [col] >> 8) & 0xff;
2188 *p++ = (values [col] >> 16) & 0xff;
2189 *p++ = (values [col] >> 24) & 0xff;
2192 g_assert_not_reached ();
2196 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
2199 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
2200 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
2201 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
2202 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
2203 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
2205 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
2209 * Some tables in metadata need to be sorted according to some criteria, but
2210 * when methods and fields are first created with reflection, they may be assigned a token
2211 * that doesn't correspond to the final token they will get assigned after the sorting.
2212 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
2213 * with the reflection objects that represent them. Once all the tables are set up, the
2214 * reflection objects will contains the correct table index. fixup_method() will fixup the
2215 * tokens for the method with ILGenerator @ilgen.
2218 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
2219 guint32 code_idx = GPOINTER_TO_UINT (value);
2220 MonoReflectionILTokenInfo *iltoken;
2221 MonoReflectionFieldBuilder *field;
2222 MonoReflectionCtorBuilder *ctor;
2223 MonoReflectionMethodBuilder *method;
2224 MonoReflectionTypeBuilder *tb;
2226 unsigned char *target;
2228 for (i = 0; i < ilgen->num_token_fixups; ++i) {
2229 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
2230 target = assembly->code.data + code_idx + iltoken->code_pos;
2231 switch (target [3]) {
2232 case MONO_TABLE_FIELD:
2233 if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
2234 g_assert_not_reached ();
2235 field = (MonoReflectionFieldBuilder *)iltoken->member;
2236 idx = field->table_idx;
2238 case MONO_TABLE_METHOD:
2239 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
2240 method = (MonoReflectionMethodBuilder *)iltoken->member;
2241 idx = method->table_idx;
2242 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
2243 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
2244 idx = ctor->table_idx;
2246 g_assert_not_reached ();
2249 case MONO_TABLE_TYPEDEF:
2250 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
2251 g_assert_not_reached ();
2252 tb = (MonoReflectionTypeBuilder *)iltoken->member;
2253 idx = tb->table_idx;
2256 g_error ("got unexpected table 0x%02x in fixup", target [3]);
2258 target [0] = idx & 0xff;
2259 target [1] = (idx >> 8) & 0xff;
2260 target [2] = (idx >> 16) & 0xff;
2265 assembly_add_resource (MonoDynamicAssembly *assembly, MonoReflectionResource *rsrc)
2267 MonoDynamicTable *table;
2271 char *b = blob_size;
2273 guint32 idx, offset;
2275 if (rsrc->filename) {
2276 name = mono_string_to_utf8 (rsrc->filename);
2277 sname = g_path_get_basename (name);
2279 table = &assembly->tables [MONO_TABLE_FILE];
2281 alloc_table (table, table->rows);
2282 values = table->values + table->next_idx * MONO_FILE_SIZE;
2283 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
2284 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
2287 mono_sha1_get_digest_from_file (name, hash);
2288 mono_metadata_encode_value (20, b, &b);
2289 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2290 mono_image_add_stream_data (&assembly->blob, hash, 20);
2292 idx = table->next_idx++;
2293 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
2297 offset = mono_array_length (rsrc->data);
2298 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
2299 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
2300 offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
2301 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
2305 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
2307 alloc_table (table, table->rows);
2308 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
2309 values [MONO_MANIFEST_OFFSET] = offset;
2310 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
2311 name = mono_string_to_utf8 (rsrc->name);
2312 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
2314 values [MONO_MANIFEST_IMPLEMENTATION] = idx;
2319 set_version_from_string (MonoString *version, guint32 *values)
2321 gchar *ver, *p, *str;
2324 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
2325 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
2326 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
2327 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
2330 ver = str = mono_string_to_utf8 (version);
2331 for (i = 0; i < 4; ++i) {
2332 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
2338 /* handle Revision and Build */
2348 load_public_key (MonoString *fname, MonoDynamicAssembly *assembly) {
2349 char *name, *content;
2355 name = mono_string_to_utf8 (fname);
2356 if (g_file_get_contents (name, &content, &len, NULL)) {
2358 char *b = blob_size;
2359 /* check it's a public key or keypair */
2360 mono_metadata_encode_value (len, b, &b);
2361 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
2362 mono_image_add_stream_data (&assembly->blob, content, len);
2364 /* need to get the actual value from the key type... */
2365 assembly->strong_name_size = 128;
2366 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
2368 /* FIXME: how do we tell mcs if loading fails? */
2374 * mono_image_build_metadata() will fill the info in all the needed metadata tables
2375 * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
2376 * and recursively outputs the info for a module. Each module will output all the info
2377 * about it's types etc.
2378 * At the end of the process, method and field tokens are fixed up and the on-disk
2379 * compressed metadata representation is created.
2382 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
2384 MonoDynamicTable *table;
2385 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
2386 MonoDomain *domain = mono_object_domain (assemblyb);
2392 if (assembly->text_rva)
2395 assembly->text_rva = START_TEXT_RVA;
2397 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2398 alloc_table (table, 1);
2399 values = table->values + MONO_ASSEMBLY_SIZE;
2400 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2401 name = mono_string_to_utf8 (assemblyb->name);
2402 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
2404 if (assemblyb->culture) {
2405 name = mono_string_to_utf8 (assemblyb->culture);
2406 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
2409 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2411 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->keyfile, assembly);
2412 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2413 set_version_from_string (assemblyb->version, values);
2415 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2416 table->rows = 1; /* .<Module> */
2418 alloc_table (table, table->rows);
2420 * Set the first entry.
2422 values = table->values + table->columns;
2423 values [MONO_TYPEDEF_FLAGS] = 0;
2424 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2425 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2426 values [MONO_TYPEDEF_EXTENDS] = 0;
2427 values [MONO_TYPEDEF_FIELD_LIST] = 1;
2428 values [MONO_TYPEDEF_METHOD_LIST] = 1;
2431 * handle global methods
2432 * FIXME: test what to do when global methods are defined in multiple modules.
2434 if (assemblyb->modules) {
2435 MonoReflectionModuleBuilder *mod = mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, 0);
2436 if (mod->global_methods) {
2437 table = &assembly->tables [MONO_TABLE_METHOD];
2438 table->rows += mono_array_length (mod->global_methods);
2439 alloc_table (table, table->rows);
2440 for (i = 0; i < mono_array_length (mod->global_methods); ++i)
2441 mono_image_get_method_info (
2442 mono_array_get (mod->global_methods, MonoReflectionMethodBuilder*, i), assembly);
2446 if (assemblyb->modules) {
2447 len = mono_array_length (assemblyb->modules);
2448 table = &assembly->tables [MONO_TABLE_MODULE];
2449 alloc_table (table, len);
2450 for (i = 0; i < len; ++i)
2451 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
2453 table = &assembly->tables [MONO_TABLE_MODULE];
2455 alloc_table (table, table->rows);
2456 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
2461 * table->rows is already set above and in mono_image_fill_module_table.
2463 /* add all the custom attributes at the end, once all the indexes are stable */
2464 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
2466 if (assemblyb->modules) {
2467 len = mono_array_length (assemblyb->modules);
2468 for (i = 0; i < len; ++i)
2469 module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
2473 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2477 * mono_image_insert_string:
2478 * @assembly: assembly builder object
2481 * Insert @str into the user string stream of @assembly.
2484 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
2490 MONO_ARCH_SAVE_REGS;
2492 if (!assembly->dynamic_assembly)
2493 mono_image_basic_init (assembly);
2494 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
2495 idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
2496 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2498 char *swapped = g_malloc (2 * mono_string_length (str));
2499 const char *p = (const char*)mono_string_chars (str);
2501 swap_with_size (swapped, p, 2, mono_string_length (str));
2502 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2506 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2508 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2510 mono_g_hash_table_insert (assembly->dynamic_assembly->tokens,
2511 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
2513 return MONO_TOKEN_STRING | idx;
2517 * mono_image_create_token:
2518 * @assembly: a dynamic assembly
2521 * Get a token to insert in the IL code stream for the given MemberInfo.
2522 * @obj can be one of:
2523 * ConstructorBuilder
2533 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2539 g_error ("System.Array methods not yet supported");
2541 klass = obj->vtable->klass;
2542 if (strcmp (klass->name, "MethodBuilder") == 0) {
2543 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2544 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2545 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2547 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2548 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2549 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2550 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2552 else if (strcmp (klass->name, "FieldBuilder") == 0) {
2553 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2554 token = mb->table_idx | MONO_TOKEN_FIELD_DEF;
2556 else if (strcmp (klass->name, "TypeBuilder") == 0) {
2557 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2558 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
2560 else if (strcmp (klass->name, "MonoType") == 0) {
2561 MonoReflectionType *tb = (MonoReflectionType *)obj;
2562 token = mono_metadata_token_from_dor (
2563 mono_image_typedef_or_ref (assembly, tb->type));
2565 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
2566 strcmp (klass->name, "MonoMethod") == 0) {
2567 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2568 token = mono_image_get_methodref_token (assembly, m->method);
2569 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2571 else if (strcmp (klass->name, "MonoField") == 0) {
2572 MonoReflectionField *f = (MonoReflectionField *)obj;
2573 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2574 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2576 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2577 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2578 token = mono_image_get_array_token (assembly, m);
2580 else if (strcmp (klass->name, "SignatureHelper") == 0) {
2581 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
2582 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
2585 g_error ("requested token for %s\n", klass->name);
2587 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
2594 guint32 import_lookup_table;
2598 guint32 import_address_table_rva;
2606 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
2609 create_dynamic_mono_image (char *assembly_name, char *module_name)
2613 image = g_new0 (MonoImage, 1);
2615 /* keep in sync with image.c */
2616 image->name = assembly_name;
2617 image->assembly_name = image->name; /* they may be different */
2618 image->module_name = module_name;
2619 image->references = g_new0 (MonoAssembly*, 1);
2620 image->references [0] = NULL;
2622 image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2623 image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2624 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2625 image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2627 image->delegate_begin_invoke_cache =
2628 g_hash_table_new ((GHashFunc)mono_signature_hash,
2629 (GCompareFunc)mono_metadata_signature_equal);
2630 image->delegate_end_invoke_cache =
2631 g_hash_table_new ((GHashFunc)mono_signature_hash,
2632 (GCompareFunc)mono_metadata_signature_equal);
2633 image->delegate_invoke_cache =
2634 g_hash_table_new ((GHashFunc)mono_signature_hash,
2635 (GCompareFunc)mono_metadata_signature_equal);
2637 image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2638 image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2639 image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2640 image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2646 * mono_image_basic_init:
2647 * @assembly: an assembly builder object
2649 * Create the MonoImage that represents the assembly builder and setup some
2650 * of the helper hash table and the basic metadata streams.
2653 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2655 static const guchar entrycode [16] = {0xff, 0x25, 0};
2656 MonoDynamicAssembly *assembly;
2660 MONO_ARCH_SAVE_REGS;
2662 if (assemblyb->dynamic_assembly)
2666 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
2668 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2671 assembly->assembly.dynamic = assembly;
2672 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
2673 assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2674 assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2675 assembly->tokens = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2676 assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2677 assembly->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
2679 string_heap_init (&assembly->sheap);
2680 mono_image_add_stream_data (&assembly->us, "", 1);
2681 add_to_blob_cached (assembly, (char*) "", 1, NULL, 0);
2682 /* import tables... */
2683 mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2684 assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2685 assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2686 mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2687 assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2688 mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2689 assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2690 stream_data_align (&assembly->code);
2692 assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2694 for (i=0; i < 64; ++i) {
2695 assembly->tables [i].next_idx = 1;
2696 assembly->tables [i].columns = table_sizes [i];
2699 image = create_dynamic_mono_image (mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
2700 assembly->assembly.aname.name = image->name;
2701 image->assembly = (MonoAssembly*)assembly;
2702 assembly->assembly.image = image;
2704 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
2705 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
2709 calc_section_size (MonoDynamicAssembly *assembly)
2713 /* alignment constraints */
2714 assembly->code.index += 3;
2715 assembly->code.index &= ~3;
2716 assembly->meta_size += 3;
2717 assembly->meta_size &= ~3;
2718 assembly->resources.index += 3;
2719 assembly->resources.index &= ~3;
2721 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2722 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2725 assembly->sections [MONO_SECTION_RELOC].size = 12;
2726 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2733 * mono_image_create_pefile:
2734 * @assemblyb: an assembly builder object
2736 * When we need to save an assembly, we first call this function that ensures the metadata
2737 * tables are built for all the modules in the assembly. This function creates the PE-COFF
2738 * header, the image sections, the CLI header etc. all the data is written in
2739 * assembly->pefile where it can be easily retrieved later in chunks.
2742 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
2743 MonoMSDOSHeader *msdos;
2744 MonoDotNetHeader *header;
2745 MonoSectionTable *section;
2746 MonoCLIHeader *cli_header;
2747 guint32 size, image_size, virtual_base, text_offset;
2748 guint32 header_start, section_start, file_offset, virtual_offset;
2749 MonoDynamicAssembly *assembly;
2750 MonoDynamicStream *pefile;
2752 guint32 *rva, value;
2755 static const unsigned char msheader[] = {
2756 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2757 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2758 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2759 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2760 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2761 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2762 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2763 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2766 mono_image_basic_init (assemblyb);
2767 assembly = assemblyb->dynamic_assembly;
2769 /* already created */
2770 if (assembly->pefile.index)
2773 mono_image_build_metadata (assemblyb);
2775 if (assemblyb->resources) {
2776 int len = mono_array_length (assemblyb->resources);
2777 for (i = 0; i < len; ++i)
2778 assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
2782 build_compressed_metadata (assembly);
2784 nsections = calc_section_size (assembly);
2786 pefile = &assembly->pefile;
2788 /* The DOS header and stub */
2789 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2790 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
2792 /* the dotnet header */
2793 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2795 /* the section tables */
2796 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2798 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2799 virtual_offset = VIRT_ALIGN;
2802 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2803 if (!assembly->sections [i].size)
2806 file_offset += FILE_ALIGN - 1;
2807 file_offset &= ~(FILE_ALIGN - 1);
2808 virtual_offset += VIRT_ALIGN - 1;
2809 virtual_offset &= ~(VIRT_ALIGN - 1);
2811 assembly->sections [i].offset = file_offset;
2812 assembly->sections [i].rva = virtual_offset;
2814 file_offset += assembly->sections [i].size;
2815 virtual_offset += assembly->sections [i].size;
2816 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2819 file_offset += FILE_ALIGN - 1;
2820 file_offset &= ~(FILE_ALIGN - 1);
2821 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
2823 image_size += section_start + sizeof (MonoSectionTable) * nsections;
2825 /* back-patch info */
2826 msdos = (MonoMSDOSHeader*)pefile->data;
2827 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
2828 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
2829 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2831 header = (MonoDotNetHeader*)(pefile->data + header_start);
2832 header->pesig [0] = 'P';
2833 header->pesig [1] = 'E';
2835 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
2836 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2837 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2838 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2839 if (assemblyb->pekind == 1) {
2841 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
2844 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2847 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2849 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2850 header->pe.pe_major = 6;
2851 header->pe.pe_minor = 0;
2852 size = assembly->sections [MONO_SECTION_TEXT].size;
2853 size += FILE_ALIGN - 1;
2854 size &= ~(FILE_ALIGN - 1);
2855 header->pe.pe_code_size = size;
2856 size = assembly->sections [MONO_SECTION_RSRC].size;
2857 size += FILE_ALIGN - 1;
2858 size &= ~(FILE_ALIGN - 1);
2859 header->pe.pe_data_size = size;
2860 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2861 header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
2862 header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
2863 /* pe_rva_entry_point always at the beginning of the text section */
2864 header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
2866 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2867 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2868 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2869 header->nt.pe_os_major = GUINT16_FROM_LE (4);
2870 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2871 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2872 size = section_start;
2873 size += FILE_ALIGN - 1;
2874 size &= ~(FILE_ALIGN - 1);
2875 header->nt.pe_header_size = GUINT32_FROM_LE (size);
2877 size += VIRT_ALIGN - 1;
2878 size &= ~(VIRT_ALIGN - 1);
2879 header->nt.pe_image_size = GUINT32_FROM_LE (size);
2882 // Translate the PEFileKind value to the value expected by the Windows loader
2885 short kind = assemblyb->pekind;
2888 // PEFileKinds.ConsoleApplication == 2
2889 // PEFileKinds.WindowApplication == 3
2892 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
2893 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
2899 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
2901 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2902 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2903 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2904 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2905 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2906 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2908 /* fill data directory entries */
2910 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2911 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2913 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2914 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2916 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2917 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2918 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2919 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2920 /* patch imported function RVA name */
2921 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2922 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2924 /* the import table */
2925 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2926 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2927 /* patch imported dll RVA name and other entries in the dir */
2928 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2929 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
2930 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2931 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2932 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2933 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2935 p = (assembly->code.data + assembly->ilt_offset);
2936 value = (assembly->text_rva + assembly->imp_names_offset - 2);
2937 *p++ = (value) & 0xff;
2938 *p++ = (value >> 8) & (0xff);
2939 *p++ = (value >> 16) & (0xff);
2940 *p++ = (value >> 24) & (0xff);
2942 /* the CLI header info */
2943 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2944 cli_header->ch_size = GUINT32_FROM_LE (72);
2945 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
2946 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
2947 if (assemblyb->entry_point)
2948 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
2950 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
2951 /* The embedded managed resources */
2952 text_offset = assembly->text_rva + assembly->code.index;
2953 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
2954 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
2955 text_offset += assembly->resources.index;
2956 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
2957 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
2958 text_offset += assembly->meta_size;
2959 if (assembly->strong_name_size) {
2960 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
2961 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
2962 text_offset += assembly->strong_name_size;
2965 /* write the section tables and section content */
2966 section = (MonoSectionTable*)(pefile->data + section_start);
2967 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2968 static const char *section_names [] = {
2969 ".text", ".rsrc", ".reloc"
2971 if (!assembly->sections [i].size)
2973 strcpy (section->st_name, section_names [i]);
2974 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
2975 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
2976 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
2977 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
2978 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
2979 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
2980 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
2982 case MONO_SECTION_TEXT:
2983 /* patch entry point */
2984 p = (assembly->code.data + 2);
2985 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
2986 *p++ = (value) & 0xff;
2987 *p++ = (value >> 8) & 0xff;
2988 *p++ = (value >> 16) & 0xff;
2989 *p++ = (value >> 24) & 0xff;
2991 text_offset = assembly->sections [i].offset;
2992 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
2993 text_offset += assembly->code.index;
2994 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
2995 text_offset += assembly->resources.index;
2996 memcpy (pefile->data + text_offset, assembly->assembly.image->raw_metadata, assembly->meta_size);
2997 text_offset += assembly->meta_size;
2998 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
3000 case MONO_SECTION_RELOC:
3001 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
3002 *rva = GUINT32_FROM_LE (assembly->text_rva);
3004 *rva = GUINT32_FROM_LE (12);
3006 data16 = (guint16*)rva;
3008 * the entrypoint is always at the start of the text section
3009 * 3 is IMAGE_REL_BASED_HIGHLOW
3010 * 2 is patch_size_rva - text_rva
3012 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
3014 *data16 = 0; /* terminate */
3016 case MONO_SECTION_RSRC:
3018 g_assert_not_reached ();
3023 /* check that the file is properly padded */
3026 FILE *f = fopen ("mypetest.exe", "w");
3027 fwrite (pefile->data, pefile->index, 1, f);
3034 * We need to return always the same object for MethodInfo, FieldInfo etc..
3035 * but we need to consider the reflected type.
3036 * type uses a different hash, since it uses custom hash/equal functions.
3041 MonoClass *refclass;
3045 reflected_equal (gconstpointer a, gconstpointer b) {
3046 const ReflectedEntry *ea = a;
3047 const ReflectedEntry *eb = b;
3049 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
3053 reflected_hash (gconstpointer a) {
3054 const ReflectedEntry *ea = a;
3055 return GPOINTER_TO_UINT (ea->item);
3058 #define CHECK_OBJECT(t,p,k) \
3064 mono_domain_lock (domain); \
3065 if (!domain->refobject_hash) \
3066 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
3067 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
3068 mono_domain_unlock (domain); \
3074 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
3076 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
3079 #define CACHE_OBJECT(p,o,k) \
3081 ReflectedEntry *e = ALLOC_REFENTRY; \
3083 e->refclass = (k); \
3084 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
3085 mono_domain_unlock (domain); \
3089 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
3091 /* this is done only once */
3092 mono_domain_lock (domain);
3093 CACHE_OBJECT (assembly, res, NULL);
3097 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoImage *module)
3099 /* this is done only once */
3100 mono_domain_lock (domain);
3101 CACHE_OBJECT (module, res, NULL);
3105 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
3107 MonoImage *image = moduleb->module.image;
3108 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
3111 /* a MonoImage was already created in mono_image_basic_init () */
3112 image = ab->dynamic_assembly->assembly.image;
3114 image = create_dynamic_mono_image (mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.name));
3116 moduleb->module.image = image;
3117 register_module (mono_object_domain (moduleb), moduleb, image);
3122 * mono_assembly_get_object:
3123 * @domain: an app domain
3124 * @assembly: an assembly
3126 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
3128 MonoReflectionAssembly*
3129 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
3131 static MonoClass *System_Reflection_Assembly;
3132 MonoReflectionAssembly *res;
3134 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
3135 if (!System_Reflection_Assembly)
3136 System_Reflection_Assembly = mono_class_from_name (
3137 mono_defaults.corlib, "System.Reflection", "Assembly");
3138 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
3139 res->assembly = assembly;
3140 CACHE_OBJECT (assembly, res, NULL);
3145 MonoReflectionModule*
3146 mono_module_get_object (MonoDomain *domain, MonoImage *image)
3148 static MonoClass *System_Reflection_Module;
3149 MonoReflectionModule *res;
3151 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
3152 if (!System_Reflection_Module)
3153 System_Reflection_Module = mono_class_from_name (
3154 mono_defaults.corlib, "System.Reflection", "Module");
3155 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
3158 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
3160 res->fqname = mono_string_new (domain, image->name);
3161 res->name = mono_string_new (domain, image->name);
3162 res->scopename = mono_string_new (domain, image->module_name);
3164 CACHE_OBJECT (image, res, NULL);
3170 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
3172 if ((t1->type != t2->type) ||
3173 (t1->byref != t2->byref))
3177 case MONO_TYPE_VOID:
3178 case MONO_TYPE_BOOLEAN:
3179 case MONO_TYPE_CHAR:
3190 case MONO_TYPE_STRING:
3193 case MONO_TYPE_OBJECT:
3194 case MONO_TYPE_TYPEDBYREF:
3196 case MONO_TYPE_VALUETYPE:
3197 case MONO_TYPE_CLASS:
3198 return t1->data.klass == t2->data.klass;
3200 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3201 case MONO_TYPE_SZARRAY:
3203 if (t1->data.type->type != t2->data.type->type)
3205 if (t1->data.type->type == MONO_TYPE_CLASS || t1->data.type->type == MONO_TYPE_VALUETYPE)
3206 return t1->data.type->data.klass == t2->data.type->data.klass;
3207 if (t1->data.type->type == MONO_TYPE_SZARRAY) {
3212 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3213 case MONO_TYPE_ARRAY:
3214 if (t1->data.array->rank != t2->data.array->rank)
3216 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
3218 g_error ("implement type compare for %0x!", t1->type);
3226 mymono_metadata_type_hash (MonoType *t1)
3232 hash |= t1->byref << 6; /* do not collide with t1->type values */
3234 case MONO_TYPE_VALUETYPE:
3235 case MONO_TYPE_CLASS:
3236 /* check if the distribution is good enough */
3237 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
3239 case MONO_TYPE_SZARRAY:
3240 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
3246 * mono_type_get_object:
3247 * @domain: an app domain
3250 * Return an System.MonoType object representing the type @type.
3253 mono_type_get_object (MonoDomain *domain, MonoType *type)
3255 MonoReflectionType *res;
3256 MonoClass *klass = mono_class_from_mono_type (type);
3258 mono_domain_lock (domain);
3259 if (!domain->type_hash)
3260 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
3261 (GCompareFunc)mymono_metadata_type_equal);
3262 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
3263 mono_domain_unlock (domain);
3266 if (klass->reflection_info && !klass->wastypebuilder) {
3267 //g_assert_not_reached ();
3268 /* should this be considered an error condition? */
3270 mono_domain_unlock (domain);
3271 return klass->reflection_info;
3274 mono_class_init (klass);
3275 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
3277 mono_g_hash_table_insert (domain->type_hash, type, res);
3278 mono_domain_unlock (domain);
3283 * mono_method_get_object:
3284 * @domain: an app domain
3286 * @refclass: the reflected type (can be NULL)
3288 * Return an System.Reflection.MonoMethod object representing the method @method.
3290 MonoReflectionMethod*
3291 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
3294 * We use the same C representation for methods and constructors, but the type
3295 * name in C# is different.
3299 MonoReflectionMethod *ret;
3302 refclass = method->klass;
3304 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
3305 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3306 cname = "MonoCMethod";
3308 cname = "MonoMethod";
3309 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
3311 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
3312 ret->method = method;
3313 ret->name = mono_string_new (domain, method->name);
3314 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
3315 CACHE_OBJECT (method, ret, refclass);
3320 * mono_field_get_object:
3321 * @domain: an app domain
3325 * Return an System.Reflection.MonoField object representing the field @field
3328 MonoReflectionField*
3329 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
3331 MonoReflectionField *res;
3334 CHECK_OBJECT (MonoReflectionField *, field, klass);
3335 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
3336 res = (MonoReflectionField *)mono_object_new (domain, oklass);
3339 CACHE_OBJECT (field, res, klass);
3344 * mono_property_get_object:
3345 * @domain: an app domain
3347 * @property: a property
3349 * Return an System.Reflection.MonoProperty object representing the property @property
3352 MonoReflectionProperty*
3353 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
3355 MonoReflectionProperty *res;
3358 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
3359 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
3360 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
3362 res->property = property;
3363 CACHE_OBJECT (property, res, klass);
3368 * mono_event_get_object:
3369 * @domain: an app domain
3373 * Return an System.Reflection.MonoEvent object representing the event @event
3376 MonoReflectionEvent*
3377 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
3379 MonoReflectionEvent *res;
3382 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
3383 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
3384 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
3387 CACHE_OBJECT (event, res, klass);
3392 * mono_param_get_objects:
3393 * @domain: an app domain
3396 * Return an System.Reflection.ParameterInfo array object representing the parameters
3397 * in the method @method.
3399 MonoReflectionParameter**
3400 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
3402 MonoReflectionParameter **res;
3403 MonoReflectionMethod *member;
3408 if (!method->signature->param_count)
3411 member = mono_method_get_object (domain, method, NULL);
3412 names = g_new (char *, method->signature->param_count);
3413 mono_method_get_param_names (method, (const char **) names);
3415 /* Note: the cache is based on the address of the signature into the method
3416 * since we already cache MethodInfos with the method as keys.
3418 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature), NULL);
3419 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
3421 res = GC_MALLOC (sizeof (MonoReflectionParameter*) * method->signature->param_count);
3423 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
3425 for (i = 0; i < method->signature->param_count; ++i) {
3426 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
3427 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
3428 res [i]->DefaultValueImpl = NULL; /* FIXME */
3429 res [i]->MemberImpl = (MonoObject*)member;
3430 res [i]->NameImpl = mono_string_new (domain, names [i]);
3431 res [i]->PositionImpl = i + 1;
3432 res [i]->AttrsImpl = method->signature->params [i]->attrs;
3435 CACHE_OBJECT (&(method->signature), res, NULL);
3440 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
3444 memset (assembly, 0, sizeof (MonoAssemblyName));
3446 assembly->culture = "";
3448 while (*p && (isalnum (*p) || *p == '.'))
3451 while (*p == ' ' || *p == ',') {
3460 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
3462 assembly->major = strtoul (p, &s, 10);
3463 if (s == p || *s != '.')
3466 assembly->minor = strtoul (p, &s, 10);
3467 if (s == p || *s != '.')
3470 assembly->build = strtoul (p, &s, 10);
3471 if (s == p || *s != '.')
3474 assembly->revision = strtoul (p, &s, 10);
3477 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
3479 if (strncmp (p, "neutral", 7) == 0) {
3480 assembly->culture = "";
3483 assembly->culture = p;
3484 while (*p && *p != ',') {
3488 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
3491 while (*s && isxdigit (*s)) {
3495 assembly->hash_len = s - p;
3496 if (!(s-p) || ((s-p) & 1))
3498 assembly->hash_value = s = p;
3499 while (*s && isxdigit (*s)) {
3501 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3504 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3509 while (*p && *p != ',')
3513 while (*p == ' ' || *p == ',') {
3527 * mono_reflection_parse_type:
3530 * Parse a type name as accepted by the GetType () method and output the info
3531 * extracted in the info structure.
3532 * the name param will be mangled, so, make a copy before passing it to this function.
3533 * The fields in info will be valid until the memory pointed to by name is valid.
3534 * Returns 0 on parse error.
3535 * See also mono_type_get_name () below.
3538 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
3540 char *start, *p, *w, *last_point, *startn;
3541 int in_modifiers = 0;
3542 int isbyref = 0, rank;
3544 start = p = w = name;
3546 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
3547 info->name = info->name_space = NULL;
3548 info->nested = NULL;
3549 info->modifiers = NULL;
3551 /* last_point separates the namespace from the name */
3557 *p = 0; /* NULL terminate the name */
3559 /* we have parsed the nesting namespace + name */
3561 info->nested = g_list_append (info->nested, startn);
3565 info->name_space = start;
3567 info->name = last_point + 1;
3569 info->name_space = (char *)"";
3594 info->nested = g_list_append (info->nested, startn);
3597 info->name_space = start;
3599 info->name = last_point + 1;
3601 info->name_space = (char *)"";
3608 if (isbyref) /* only one level allowed by the spec */
3611 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
3615 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
3626 else if (*p != '*') /* '*' means unknown lower bound */
3632 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
3644 return 0; /* missing assembly name */
3645 if (!assembly_name_to_aname (&info->assembly, p))
3651 if (info->assembly.name)
3654 *w = 0; /* terminate class name */
3655 if (!info->name || !*info->name)
3657 /* add other consistency checks */
3662 mono_type_get_name_recurse (MonoType *type, GString *str)
3666 switch (type->type) {
3667 case MONO_TYPE_ARRAY: {
3668 int i, rank = type->data.array->rank;
3670 mono_type_get_name_recurse (type->data.array->type, str);
3671 g_string_append_c (str, '[');
3672 for (i = 1; i < rank; i++)
3673 g_string_append_c (str, ',');
3674 g_string_append_c (str, ']');
3677 case MONO_TYPE_SZARRAY:
3678 mono_type_get_name_recurse (type->data.type, str);
3679 g_string_append (str, "[]");
3682 mono_type_get_name_recurse (type->data.type, str);
3683 g_string_append_c (str, '*');
3686 klass = mono_class_from_mono_type (type);
3687 if (klass->nested_in) {
3688 mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
3689 g_string_append_c (str, '+');
3691 if (*klass->name_space) {
3692 g_string_append (str, klass->name_space);
3693 g_string_append_c (str, '.');
3695 g_string_append (str, klass->name);
3701 * mono_type_get_name:
3704 * Returns the string representation for type as required by System.Reflection.
3705 * The inverse of mono_reflection_parse_type ().
3708 mono_type_get_name (MonoType *type)
3710 GString* result = g_string_new ("");
3711 mono_type_get_name_recurse (type, result);
3714 g_string_append_c (result, '&');
3716 return g_string_free (result, FALSE);
3720 * mono_reflection_get_type:
3721 * @image: a metadata context
3722 * @info: type description structure
3723 * @ignorecase: flag for case-insensitive string compares
3725 * Build a MonoType from the type description in @info.
3729 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3736 image = mono_defaults.corlib;
3739 klass = mono_class_from_name_case (image, info->name_space, info->name);
3741 klass = mono_class_from_name (image, info->name_space, info->name);
3744 for (mod = info->nested; mod; mod = mod->next) {
3747 mono_class_init (klass);
3748 nested = klass->nested_classes;
3751 klass = nested->data;
3753 if (g_strcasecmp (klass->name, mod->data) == 0)
3756 if (strcmp (klass->name, mod->data) == 0)
3760 nested = nested->next;
3767 mono_class_init (klass);
3768 for (mod = info->modifiers; mod; mod = mod->next) {
3769 modval = GPOINTER_TO_UINT (mod->data);
3770 if (!modval) { /* byref: must be last modifier */
3771 return &klass->this_arg;
3772 } else if (modval == -1) {
3773 klass = mono_ptr_class_get (&klass->byval_arg);
3774 } else { /* array rank */
3775 klass = mono_array_class_get (&klass->byval_arg, modval);
3777 mono_class_init (klass);
3779 return &klass->byval_arg;
3783 * mono_reflection_type_from_name:
3785 * @image: a metadata context (can be NULL).
3787 * Retrieves a MonoType from its @name. If the name is not fully qualified,
3788 * it defaults to get the type from @image or, if @image is NULL or loading
3789 * from it fails, uses corlib.
3793 mono_reflection_type_from_name (char *name, MonoImage *image)
3796 MonoTypeNameParse info;
3798 /*g_print ("requested type %s\n", str);*/
3799 if (!mono_reflection_parse_type (name, &info)) {
3800 g_list_free (info.modifiers);
3801 g_list_free (info.nested);
3805 if (info.assembly.name) {
3806 image = mono_image_loaded (info.assembly.name);
3807 /* do we need to load if it's not already loaded? */
3809 g_list_free (info.modifiers);
3810 g_list_free (info.nested);
3813 } else if (image == NULL) {
3814 image = mono_defaults.corlib;
3817 type = mono_reflection_get_type (image, &info, FALSE);
3818 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
3819 image = mono_defaults.corlib;
3820 type = mono_reflection_get_type (image, &info, FALSE);
3823 g_list_free (info.modifiers);
3824 g_list_free (info.nested);
3829 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
3831 int slen, type = t->type;
3836 case MONO_TYPE_BOOLEAN: {
3837 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
3842 case MONO_TYPE_CHAR:
3844 case MONO_TYPE_I2: {
3845 guint16 *val = g_malloc (sizeof (guint16));
3850 #if SIZEOF_VOID_P == 4
3856 case MONO_TYPE_I4: {
3857 guint32 *val = g_malloc (sizeof (guint32));
3862 #if SIZEOF_VOID_P == 8
3863 case MONO_TYPE_U: /* error out instead? this should probably not happen */
3868 case MONO_TYPE_I8: {
3869 guint64 *val = g_malloc (sizeof (guint64));
3874 case MONO_TYPE_VALUETYPE:
3875 if (t->data.klass->enumtype) {
3876 type = t->data.klass->enum_basetype->type;
3879 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
3882 case MONO_TYPE_STRING:
3883 if (*p == (char)0xFF) {
3887 slen = mono_metadata_decode_value (p, &p);
3889 return mono_string_new_len (mono_domain_get (), p, slen);
3890 case MONO_TYPE_CLASS: {
3894 slen = mono_metadata_decode_value (p, &p);
3895 n = g_memdup (p, slen + 1);
3897 t = mono_reflection_type_from_name (n, image);
3899 g_warning ("Cannot load type '%s'", n);
3902 return mono_type_get_object (mono_domain_get (), t);
3904 case MONO_TYPE_OBJECT: {
3912 } else if (subt == 0x55) {
3915 slen = mono_metadata_decode_value (p, &p);
3916 n = g_memdup (p, slen + 1);
3918 t = mono_reflection_type_from_name (n, image);
3920 g_warning ("Cannot load type '%s'", n);
3923 subc = mono_class_from_mono_type (t);
3924 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
3925 MonoType simple_type = {{0}};
3926 simple_type.type = subt;
3927 subc = mono_class_from_mono_type (&simple_type);
3929 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
3931 val = load_cattr_value (image, &subc->byval_arg, p, end);
3932 obj = mono_object_new (mono_domain_get (), subc);
3933 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
3937 case MONO_TYPE_SZARRAY:
3943 arr=mono_array_new(mono_domain_get(),mono_class_from_mono_type(t->data.type),alen);
3944 switch (t->data.type->type)
3948 case MONO_TYPE_BOOLEAN:
3949 for (i=0;i<alen;i++)
3951 MonoBoolean val=*p++;
3952 mono_array_set(arr,MonoBoolean,i,val);
3955 case MONO_TYPE_CHAR:
3958 for (i=0;i<alen;i++)
3960 guint16 val=read16(p);
3961 mono_array_set(arr,guint16,i,val);
3968 for (i=0;i<alen;i++)
3970 guint32 val=read32(p);
3971 mono_array_set(arr,guint32,i,val);
3978 for (i=0;i<alen;i++)
3980 guint64 val=read64(p);
3981 mono_array_set(arr,guint64,i,val);
3985 case MONO_TYPE_STRING:
3986 for (i=0;i<alen;i++)
3990 mono_array_set(arr,gpointer,i,NULL);
3995 slen=mono_metadata_decode_value(p,&p);
3996 mono_array_set(arr,gpointer,i,mono_string_new_len(mono_domain_get(),p,slen));
4002 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
4008 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
4014 type_is_reference (MonoType *type)
4016 switch (type->type) {
4017 case MONO_TYPE_BOOLEAN:
4018 case MONO_TYPE_CHAR:
4031 case MONO_TYPE_VALUETYPE:
4039 free_param_data (MonoMethodSignature *sig, void **params) {
4041 for (i = 0; i < sig->param_count; ++i) {
4042 if (!type_is_reference (sig->params [i]))
4043 g_free (params [i]);
4048 * Find the method index in the metadata methodDef table.
4049 * Later put these three helper methods in metadata and export them.
4052 find_method_index (MonoMethod *method) {
4053 MonoClass *klass = method->klass;
4056 for (i = 0; i < klass->method.count; ++i) {
4057 if (method == klass->methods [i])
4058 return klass->method.first + 1 + i;
4064 * Find the field index in the metadata FieldDef table.
4067 find_field_index (MonoClass *klass, MonoClassField *field) {
4070 for (i = 0; i < klass->field.count; ++i) {
4071 if (field == &klass->fields [i])
4072 return klass->field.first + 1 + i;
4078 * Find the property index in the metadata Property table.
4081 find_property_index (MonoClass *klass, MonoProperty *property) {
4084 for (i = 0; i < klass->property.count; ++i) {
4085 if (property == &klass->properties [i])
4086 return klass->property.first + 1 + i;
4092 * Find the event index in the metadata Event table.
4095 find_event_index (MonoClass *klass, MonoEvent *event) {
4098 for (i = 0; i < klass->event.count; ++i) {
4099 if (event == &klass->events [i])
4100 return klass->event.first + 1 + i;
4106 create_custom_attr (MonoImage *image, MonoMethod *method,
4107 const char *data, guint32 len)
4109 const char *p = data;
4111 guint32 i, j, num_named;
4115 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
4118 mono_class_init (method->klass);
4119 /*g_print ("got attr %s\n", method->klass->name);*/
4121 params = g_new (void*, method->signature->param_count);
4125 for (i = 0; i < method->signature->param_count; ++i) {
4126 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
4130 attr = mono_object_new (mono_domain_get (), method->klass);
4131 mono_runtime_invoke (method, attr, params, NULL);
4132 free_param_data (method->signature, params);
4134 num_named = read16 (named);
4136 for (j = 0; j < num_named; j++) {
4138 char *name, named_type;
4139 named_type = *named++;
4140 named++; /* type of data */
4141 name_len = mono_metadata_decode_blob_size (named, &named);
4142 name = g_malloc (name_len + 1);
4143 memcpy (name, named, name_len);
4144 name [name_len] = 0;
4146 if (named_type == 0x53) {
4147 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
4148 void *val = load_cattr_value (image, field->type, named, &named);
4149 mono_field_set_value (attr, field, val);
4150 if (!type_is_reference (field->type))
4152 } else if (named_type == 0x54) {
4153 MonoProperty *prop = mono_class_get_property_from_name (mono_object_class (attr), name);
4155 MonoType *prop_type;
4156 /* can we have more that 1 arg in a custom attr named property? */
4157 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
4158 pparams [0] = load_cattr_value (image, prop_type, named, &named);
4159 mono_property_set_value (prop, attr, pparams, NULL);
4160 if (!type_is_reference (prop_type))
4161 g_free (pparams [0]);
4170 * mono_reflection_get_custom_attrs:
4171 * @obj: a reflection object handle
4173 * Return an array with all the custom attributes defined of the
4174 * reflection handle @obj. The objects are fully build.
4177 mono_reflection_get_custom_attrs (MonoObject *obj)
4179 guint32 idx, mtoken, i, len;
4180 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
4188 MonoArray *dynamic_attrs = NULL;
4190 MONO_ARCH_SAVE_REGS;
4192 klass = obj->vtable->klass;
4193 /* FIXME: need to handle: Module */
4194 if (klass == mono_defaults.monotype_class) {
4195 MonoReflectionType *rtype = (MonoReflectionType*)obj;
4196 klass = mono_class_from_mono_type (rtype->type);
4197 idx = mono_metadata_token_index (klass->type_token);
4198 idx <<= CUSTOM_ATTR_BITS;
4199 idx |= CUSTOM_ATTR_TYPEDEF;
4200 image = klass->image;
4201 } else if (strcmp ("Assembly", klass->name) == 0) {
4202 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
4203 idx = 1; /* there is only one assembly */
4204 idx <<= CUSTOM_ATTR_BITS;
4205 idx |= CUSTOM_ATTR_ASSEMBLY;
4206 image = rassembly->assembly->image;
4207 } else if (strcmp ("MonoProperty", klass->name) == 0) {
4208 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
4209 idx = find_property_index (rprop->klass, rprop->property);
4210 idx <<= CUSTOM_ATTR_BITS;
4211 idx |= CUSTOM_ATTR_PROPERTY;
4212 image = rprop->klass->image;
4213 } else if (strcmp ("MonoEvent", klass->name) == 0) {
4214 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
4215 idx = find_event_index (revent->klass, revent->event);
4216 idx <<= CUSTOM_ATTR_BITS;
4217 idx |= CUSTOM_ATTR_EVENT;
4218 image = revent->klass->image;
4219 } else if (strcmp ("MonoField", klass->name) == 0) {
4220 MonoReflectionField *rfield = (MonoReflectionField*)obj;
4221 idx = find_field_index (rfield->klass, rfield->field);
4222 idx <<= CUSTOM_ATTR_BITS;
4223 idx |= CUSTOM_ATTR_FIELDDEF;
4224 image = rfield->klass->image;
4225 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
4226 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
4227 idx = find_method_index (rmethod->method);
4228 idx <<= CUSTOM_ATTR_BITS;
4229 idx |= CUSTOM_ATTR_METHODDEF;
4230 image = rmethod->method->klass->image;
4231 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
4232 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
4233 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
4234 guint32 method_index = find_method_index (rmethod->method);
4235 guint32 param_list, param_last, param_pos, found;
4237 image = rmethod->method->klass->image;
4238 ca = &image->tables [MONO_TABLE_METHOD];
4240 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
4241 if (method_index == ca->rows) {
4242 ca = &image->tables [MONO_TABLE_PARAM];
4243 param_last = ca->rows + 1;
4245 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
4246 ca = &image->tables [MONO_TABLE_PARAM];
4249 for (i = param_list; i < param_last; ++i) {
4250 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
4251 if (param_pos == param->PositionImpl) {
4257 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
4259 idx <<= CUSTOM_ATTR_BITS;
4260 idx |= CUSTOM_ATTR_PARAMDEF;
4261 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
4262 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
4263 dynamic_attrs = assemblyb->cattrs;
4265 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
4266 } else { /* handle other types here... */
4267 g_error ("get custom attrs not yet supported for %s", klass->name);
4270 if (dynamic_attrs) {
4271 len = mono_array_length (dynamic_attrs);
4272 for (i = 0; i < len; ++i) {
4273 MonoReflectionCustomAttr *cattr = (MonoReflectionCustomAttr*)mono_array_get (dynamic_attrs, gpointer, i);
4274 attr = create_custom_attr (image, cattr->ctor->method, mono_array_addr (cattr->data, int, 0), mono_array_length (cattr->data));
4275 list = g_list_prepend (list, attr);
4279 /* at this point image and index are set correctly for searching the custom attr */
4280 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4281 /* the table is not sorted */
4282 for (i = 0; i < ca->rows; ++i) {
4283 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
4284 if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
4286 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
4287 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
4288 case CUSTOM_ATTR_TYPE_METHODDEF:
4289 mtoken |= MONO_TOKEN_METHOD_DEF;
4291 case CUSTOM_ATTR_TYPE_MEMBERREF:
4292 mtoken |= MONO_TOKEN_MEMBER_REF;
4295 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
4298 method = mono_get_method (image, mtoken, NULL);
4300 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
4304 const char *data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
4305 data_len = mono_metadata_decode_value (data, &data);
4307 attr = create_custom_attr (image, method, data, data_len);
4309 list = g_list_prepend (list, attr);
4313 len = g_list_length (list);
4315 * The return type is really object[], but System/Attribute.cs does a cast
4316 * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
4317 * probably fix that.
4319 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
4320 result = mono_array_new (mono_domain_get (), klass, len);
4321 for (i = 0; i < len; ++i) {
4322 mono_array_set (result, gpointer, i, list->data);
4325 g_list_free (g_list_first (list));
4330 static MonoMethodSignature*
4331 parameters_to_signature (MonoArray *parameters) {
4332 MonoMethodSignature *sig;
4335 count = parameters? mono_array_length (parameters): 0;
4337 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
4338 sig->param_count = count;
4339 sig->sentinelpos = -1; /* FIXME */
4340 for (i = 0; i < count; ++i) {
4341 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
4342 sig->params [i] = pt->type;
4347 static MonoMethodSignature*
4348 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
4349 MonoMethodSignature *sig;
4351 sig = parameters_to_signature (ctor->parameters);
4352 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4353 sig->ret = &mono_defaults.void_class->byval_arg;
4357 static MonoMethodSignature*
4358 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
4359 MonoMethodSignature *sig;
4361 sig = parameters_to_signature (method->parameters);
4362 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4363 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
4368 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
4370 MonoClass *klass = mono_object_class (prop);
4371 if (strcmp (klass->name, "PropertyBuilder") == 0) {
4372 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
4373 *name = mono_string_to_utf8 (pb->name);
4374 *type = pb->type->type;
4376 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
4377 *name = g_strdup (p->property->name);
4378 if (p->property->get)
4379 *type = p->property->get->signature->ret;
4381 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
4386 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
4388 MonoClass *klass = mono_object_class (field);
4389 if (strcmp (klass->name, "FieldBuilder") == 0) {
4390 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
4391 *name = mono_string_to_utf8 (fb->name);
4392 *type = fb->type->type;
4394 MonoReflectionField *f = (MonoReflectionField *)field;
4395 *name = g_strdup (f->field->name);
4396 *type = f->field->type;
4401 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
4402 char *name, *result;
4406 name = mono_type_get_name (type);
4407 klass = my_mono_class_from_mono_type (type);
4408 ta = klass->image->assembly;
4409 if (ta == ass || klass->image == mono_defaults.corlib)
4412 /* missing public key */
4413 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
4414 name, ta->aname.name,
4415 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
4416 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
4422 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
4425 MonoTypeEnum simple_type;
4427 if ((p-buffer) + 10 >= *buflen) {
4430 newbuf = g_realloc (buffer, *buflen);
4431 p = newbuf + (p-buffer);
4434 argval = ((char*)arg + sizeof (MonoObject));
4435 simple_type = type->type;
4437 switch (simple_type) {
4438 case MONO_TYPE_BOOLEAN:
4443 case MONO_TYPE_CHAR:
4446 swap_with_size (p, argval, 2, 1);
4452 swap_with_size (p, argval, 4, 1);
4458 swap_with_size (p, argval, 8, 1);
4461 case MONO_TYPE_VALUETYPE:
4462 if (type->data.klass->enumtype) {
4463 simple_type = type->data.klass->enum_basetype->type;
4466 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
4469 case MONO_TYPE_STRING: {
4476 str = mono_string_to_utf8 ((MonoString*)arg);
4477 slen = strlen (str);
4478 if ((p-buffer) + 10 + slen >= *buflen) {
4482 newbuf = g_realloc (buffer, *buflen);
4483 p = newbuf + (p-buffer);
4486 mono_metadata_encode_value (slen, p, &p);
4487 memcpy (p, str, slen);
4492 case MONO_TYPE_CLASS: {
4495 MonoClass *k = mono_object_class (arg);
4496 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
4497 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
4498 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
4500 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
4501 slen = strlen (str);
4502 if ((p-buffer) + 10 + slen >= *buflen) {
4506 newbuf = g_realloc (buffer, *buflen);
4507 p = newbuf + (p-buffer);
4510 mono_metadata_encode_value (slen, p, &p);
4511 memcpy (p, str, slen);
4516 /* it may be a boxed value or a Type */
4517 case MONO_TYPE_OBJECT: {
4518 MonoClass *klass = mono_object_class (arg);
4522 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
4525 } else if (klass->enumtype) {
4527 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
4528 *p++ = simple_type = klass->byval_arg.type;
4531 g_error ("unhandled type in custom attr");
4533 str = type_get_qualified_name (klass->enum_basetype, NULL);
4534 slen = strlen (str);
4535 if ((p-buffer) + 10 + slen >= *buflen) {
4539 newbuf = g_realloc (buffer, *buflen);
4540 p = newbuf + (p-buffer);
4543 mono_metadata_encode_value (slen, p, &p);
4544 memcpy (p, str, slen);
4547 simple_type = klass->enum_basetype->type;
4551 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
4554 *retbuffer = buffer;
4558 * mono_reflection_get_custom_attrs_blob:
4559 * @ctor: custom attribute constructor
4560 * @ctorArgs: arguments o the constructor
4566 * Creates the blob of data that needs to be saved in the metadata and that represents
4567 * the custom attributed described by @ctor, @ctorArgs etc.
4568 * Returns: a Byte array representing the blob of data.
4571 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
4574 MonoMethodSignature *sig;
4579 MONO_ARCH_SAVE_REGS;
4581 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4582 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
4584 sig = ((MonoReflectionMethod*)ctor)->method->signature;
4587 p = buffer = g_malloc (buflen);
4588 /* write the prolog */
4591 for (i = 0; i < sig->param_count; ++i) {
4592 if (sig->params[i]->type==MONO_TYPE_SZARRAY)
4594 guint32 alen=mono_array_length(ctorArgs) - i;
4596 if ((p-buffer) + 10 >= buflen) {
4599 newbuf = g_realloc (buffer, buflen);
4600 p = newbuf + (p-buffer);
4604 *p++=(alen>>8)&0xff;
4605 *p++=(alen>>16)&0xff;
4606 *p++=(alen>>24)&0xff;
4607 for (j=0;j<alen;j++)
4609 arg=(MonoObject*)mono_array_get(ctorArgs,gpointer,i+j);
4610 encode_cattr_value(buffer,p,&buffer,&p,&buflen,sig->params[i]->data.type,arg);
4615 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
4616 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
4621 i += mono_array_length (properties);
4623 i += mono_array_length (fields);
4625 *p++ = (i >> 8) & 0xff;
4628 for (i = 0; i < mono_array_length (properties); ++i) {
4633 prop = mono_array_get (properties, gpointer, i);
4634 get_prop_name_and_type (prop, &pname, &ptype);
4635 *p++ = 0x54; /* PROPERTY signature */
4636 mono_metadata_encode_value (ptype->type, p, &p);
4637 len = strlen (pname);
4638 mono_metadata_encode_value (len, p, &p);
4639 memcpy (p, pname, len);
4641 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
4648 for (i = 0; i < mono_array_length (fields); ++i) {
4653 field = mono_array_get (fields, gpointer, i);
4654 get_field_name_and_type (field, &fname, &ftype);
4655 *p++ = 0x53; /* FIELD signature */
4656 mono_metadata_encode_value (ftype->type, p, &p);
4657 len = strlen (fname);
4658 mono_metadata_encode_value (len, p, &p);
4659 memcpy (p, fname, len);
4661 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
4666 g_assert (p - buffer <= buflen);
4667 buflen = p - buffer;
4668 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
4669 p = mono_array_addr (result, char, 0);
4670 memcpy (p, buffer, buflen);
4672 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
4678 * mono_reflection_setup_internal_class:
4679 * @tb: a TypeBuilder object
4681 * Creates a MonoClass that represents the TypeBuilder.
4682 * This is a trick that lets us simplify a lot of reflection code
4683 * (and will allow us to support Build and Run assemblies easier).
4686 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
4688 MonoClass *klass, *parent;
4690 MONO_ARCH_SAVE_REGS;
4692 klass = g_new0 (MonoClass, 1);
4694 klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
4697 /* check so we can compile corlib correctly */
4698 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
4699 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
4700 parent = tb->parent->type->data.klass;
4702 parent = my_mono_class_from_mono_type (tb->parent->type);
4706 klass->inited = 1; /* we lie to the runtime */
4707 klass->name = mono_string_to_utf8 (tb->name);
4708 klass->name_space = mono_string_to_utf8 (tb->nspace);
4709 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
4710 klass->flags = tb->attrs;
4712 klass->element_class = klass;
4713 klass->reflection_info = tb; /* need to pin. */
4715 /* Put into cache so mono_class_get () will find it */
4716 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
4719 mono_g_hash_table_insert (tb->module->assemblyb->dynamic_assembly->tokens,
4720 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
4724 mono_class_setup_parent (klass, parent);
4725 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
4726 const char *old_n = klass->name;
4727 /* trick to get relative numbering right when compiling corlib */
4728 klass->name = "BuildingObject";
4729 mono_class_setup_parent (klass, mono_defaults.object_class);
4730 klass->name = old_n;
4732 mono_class_setup_mono_type (klass);
4735 * FIXME: handle interfaces.
4738 tb->type.type = &klass->byval_arg;
4740 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
4744 * mono_reflection_create_internal_class:
4745 * @tb: a TypeBuilder object
4747 * Actually create the MonoClass that is associated with the TypeBuilder.
4750 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
4754 MONO_ARCH_SAVE_REGS;
4756 klass = my_mono_class_from_mono_type (tb->type.type);
4758 if (klass->enumtype && klass->enum_basetype == NULL) {
4759 MonoReflectionFieldBuilder *fb;
4761 g_assert (tb->fields != NULL);
4762 g_assert (mono_array_length (tb->fields) >= 1);
4764 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
4766 klass->enum_basetype = fb->type->type;
4767 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
4768 if (!klass->element_class)
4769 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
4770 klass->instance_size = klass->element_class->instance_size;
4771 klass->size_inited = 1;
4773 * this is almost safe to do with enums and it's needed to be able
4774 * to create objects of the enum type (for use in SetConstant).
4776 /* FIXME: Does this mean enums can't have method overrides ? */
4777 mono_class_setup_vtable (klass, NULL, 0);
4782 reflection_methodbuilder_to_mono_method (MonoClass *klass,
4783 ReflectionMethodBuilder *rmb,
4784 MonoMethodSignature *sig)
4787 MonoMethodNormal *pm;
4789 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
4790 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
4791 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
4793 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
4795 pm = (MonoMethodNormal*)m;
4798 m->flags = rmb->attrs;
4799 m->iflags = rmb->iattrs;
4800 m->name = mono_string_to_utf8 (rmb->name);
4804 /* TODO: What about m->token ? */
4805 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
4806 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
4809 m->addr = mono_lookup_internal_call (m);
4810 m->signature->pinvoke = 1;
4811 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
4813 m->signature->pinvoke = 1;
4815 } else if (!m->klass->dummy &&
4816 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
4817 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
4818 MonoMethodHeader *header;
4820 gint32 max_stack, i;
4821 gint32 num_locals = 0;
4822 gint32 num_clauses = 0;
4826 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
4827 code_size = rmb->ilgen->code_len;
4828 max_stack = rmb->ilgen->max_stack;
4829 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
4830 if (rmb->ilgen->ex_handlers)
4831 num_clauses = method_count_clauses (rmb->ilgen);
4834 code = mono_array_addr (rmb->code, guint8, 0);
4835 code_size = mono_array_length (rmb->code);
4836 /* we probably need to run a verifier on the code... */
4846 header = g_malloc0 (sizeof (MonoMethodHeader) +
4847 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
4848 header->code_size = code_size;
4849 header->code = g_malloc (code_size);
4850 memcpy ((char*)header->code, code, code_size);
4851 header->max_stack = max_stack;
4852 header->init_locals = rmb->init_locals;
4853 header->num_locals = num_locals;
4855 for (i = 0; i < num_locals; ++i) {
4856 MonoReflectionLocalBuilder *lb =
4857 mono_array_get (rmb->ilgen->locals,
4858 MonoReflectionLocalBuilder*, i);
4860 header->locals [i] = g_new0 (MonoType, 1);
4861 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
4864 header->num_clauses = num_clauses;
4866 header->clauses = method_encode_clauses (klass->image->assembly->dynamic,
4871 pm->header = header;
4878 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
4880 ReflectionMethodBuilder rmb;
4882 MonoMethodSignature *sig;
4884 name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
4886 sig = ctor_builder_to_signature (mb);
4888 rmb.ilgen = mb->ilgen;
4889 rmb.parameters = mb->parameters;
4890 rmb.pinfo = mb->pinfo;
4891 rmb.attrs = mb->attrs;
4892 rmb.iattrs = mb->iattrs;
4893 rmb.call_conv = mb->call_conv;
4894 rmb.type = mb->type;
4895 rmb.name = mono_string_new (mono_domain_get (), name);
4896 rmb.table_idx = &mb->table_idx;
4897 rmb.init_locals = mb->init_locals;
4900 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
4905 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
4907 ReflectionMethodBuilder rmb;
4908 MonoMethodSignature *sig;
4910 sig = method_builder_to_signature (mb);
4912 rmb.ilgen = mb->ilgen;
4913 rmb.parameters = mb->parameters;
4914 rmb.pinfo = mb->pinfo;
4915 rmb.attrs = mb->attrs;
4916 rmb.iattrs = mb->iattrs;
4917 rmb.call_conv = mb->call_conv;
4918 rmb.type = mb->type;
4919 rmb.name = mb->name;
4920 rmb.table_idx = &mb->table_idx;
4921 rmb.init_locals = mb->init_locals;
4922 rmb.code = mb->code;
4924 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
4929 ensure_runtime_vtable (MonoClass *klass)
4931 MonoReflectionTypeBuilder *tb = klass->reflection_info;
4932 int i, num, j, onum;
4933 MonoMethod **overrides;
4935 if (!tb || klass->wastypebuilder)
4938 ensure_runtime_vtable (klass->parent);
4940 num = tb->ctors? mono_array_length (tb->ctors): 0;
4941 num += tb->methods? mono_array_length (tb->methods): 0;
4942 klass->method.count = num;
4943 klass->methods = g_new (MonoMethod*, num);
4944 num = tb->ctors? mono_array_length (tb->ctors): 0;
4945 for (i = 0; i < num; ++i)
4946 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
4947 num = tb->methods? mono_array_length (tb->methods): 0;
4949 for (i = 0; i < num; ++i)
4950 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
4952 klass->wastypebuilder = TRUE;
4953 if (tb->interfaces) {
4954 klass->interface_count = mono_array_length (tb->interfaces);
4955 klass->interfaces = g_new (MonoClass*, klass->interface_count);
4956 for (i = 0; i < klass->interface_count; ++i) {
4957 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
4958 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
4965 for (i = 0; i < mono_array_length (tb->methods); ++i) {
4966 MonoReflectionMethodBuilder *mb =
4967 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4968 if (mb->override_method)
4973 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
4977 for (i = 0; i < mono_array_length (tb->methods); ++i) {
4978 MonoReflectionMethodBuilder *mb =
4979 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4980 if (mb->override_method) {
4981 /* FIXME: What if 'override_method' is a MethodBuilder ? */
4982 overrides [onum * 2] =
4983 mb->override_method->method;
4984 overrides [onum * 2 + 1] =
4987 g_assert (mb->mhandle);
4994 mono_class_setup_vtable (klass, overrides, onum);
4998 typebuilder_setup_fields (MonoClass *klass)
5000 MonoReflectionTypeBuilder *tb = klass->reflection_info;
5001 MonoReflectionFieldBuilder *fb;
5002 MonoClassField *field;
5005 klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
5007 if (!klass->field.count)
5010 klass->fields = g_new0 (MonoClassField, klass->field.count);
5012 for (i = 0; i < klass->field.count; ++i) {
5013 fb = mono_array_get (tb->fields, gpointer, i);
5014 field = &klass->fields [i];
5015 field->name = mono_string_to_utf8 (fb->name);
5017 /* FIXME: handle type modifiers */
5018 field->type = g_memdup (fb->type->type, sizeof (MonoType));
5019 field->type->attrs = fb->attrs;
5021 field->type = fb->type->type;
5023 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
5024 field->data = mono_array_addr (fb->rva_data, char, 0);
5025 if (fb->offset != -1)
5026 field->offset = fb->offset;
5027 field->parent = klass;
5030 mono_class_layout_fields (klass);
5034 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
5037 MonoReflectionType* res;
5039 MONO_ARCH_SAVE_REGS;
5041 klass = my_mono_class_from_mono_type (tb->type.type);
5044 * Fields to set in klass:
5045 * the various flags: delegate/unicode/contextbound etc.
5051 klass->flags = tb->attrs;
5052 klass->element_class = klass;
5054 /* enums are done right away */
5055 if (!klass->enumtype)
5056 ensure_runtime_vtable (klass);
5058 /* fields and object layout */
5059 if (klass->parent) {
5060 if (!klass->parent->size_inited)
5061 mono_class_init (klass->parent);
5062 klass->instance_size += klass->parent->instance_size;
5063 klass->class_size += klass->parent->class_size;
5064 klass->min_align = klass->parent->min_align;
5066 klass->instance_size = sizeof (MonoObject);
5067 klass->min_align = 1;
5069 /* FIXME: handle packing_size and instance_size */
5070 typebuilder_setup_fields (klass);
5072 /* FIXME: properties */
5074 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5075 /* with enums res == tb: need to fix that. */
5076 if (!klass->enumtype)
5077 g_assert (res != (MonoReflectionType*)tb);
5082 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
5084 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5085 guint32 na = mono_array_length (sig->arguments);
5090 MONO_ARCH_SAVE_REGS;
5092 p = buf = g_malloc (10 + na * 10);
5094 mono_metadata_encode_value (0x07, p, &p);
5095 mono_metadata_encode_value (na, p, &p);
5096 for (i = 0; i < na; ++i) {
5097 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5098 encode_reflection_type (assembly, type, p, &p);
5102 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5103 p = mono_array_addr (result, char, 0);
5104 memcpy (p, buf, buflen);
5111 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
5113 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5114 guint32 na = mono_array_length (sig->arguments);
5119 MONO_ARCH_SAVE_REGS;
5121 p = buf = g_malloc (10 + na * 10);
5123 mono_metadata_encode_value (0x06, p, &p);
5124 for (i = 0; i < na; ++i) {
5125 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5126 encode_reflection_type (assembly, type, p, &p);
5130 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5131 p = mono_array_addr (result, char, 0);
5132 memcpy (p, buf, buflen);
5139 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
5141 MonoDynamicAssembly *assembly = image->assembly->dynamic;
5145 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5148 if (strcmp (obj->vtable->klass->name, "String") == 0) {
5152 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
5153 MonoReflectionType *tb = (MonoReflectionType*)obj;
5154 result = mono_class_from_mono_type (tb->type);
5157 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
5158 result = ((MonoReflectionMethod*)obj)->method;
5161 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
5162 result = ((MonoReflectionMethod*)obj)->method;
5165 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
5166 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
5167 result = mb->mhandle;
5169 /* Type is not yet created */
5170 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5172 mono_domain_try_type_resolve (mono_domain_get (), (MonoObject*)tb);
5175 * Hopefully this has been filled in by calling CreateType() on the
5179 * TODO: This won't work if the application finishes another
5180 * TypeBuilder instance instead of this one.
5182 result = mb->mhandle;
5185 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
5186 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
5188 result = cb->mhandle;
5190 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
5192 mono_domain_try_type_resolve (mono_domain_get (), (MonoObject*)tb);
5193 result = cb->mhandle;
5196 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
5197 result = ((MonoReflectionField*)obj)->field;
5200 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
5201 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
5202 result = fb->handle;
5205 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
5207 mono_domain_try_type_resolve (mono_domain_get (), (MonoObject*)tb);
5208 result = fb->handle;
5211 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
5212 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
5215 klass = tb->type.type->data.klass;
5216 if (klass->wastypebuilder) {
5217 /* Already created */
5221 mono_domain_try_type_resolve (mono_domain_get (), (MonoObject*)tb);
5222 result = tb->type.type->data.klass;
5226 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
5227 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
5228 MonoMethodSignature *sig;
5231 if (helper->arguments)
5232 nargs = mono_array_length (helper->arguments);
5236 sig = mono_metadata_signature_alloc (image, nargs);
5237 sig->explicit_this = helper->call_conv & 64;
5238 sig->hasthis = helper->call_conv & 32;
5240 if (helper->call_conv == 0) /* unmanaged */
5241 sig->call_convention = helper->unmanaged_call_conv - 1;
5243 if (helper->call_conv & 0x02)
5244 sig->call_convention = MONO_CALL_VARARG;
5246 sig->call_convention = MONO_CALL_DEFAULT;
5248 sig->param_count = nargs;
5249 /* TODO: Copy type ? */
5250 sig->ret = helper->return_type->type;
5251 for (i = 0; i < nargs; ++i) {
5252 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
5253 sig->params [i] = rt->type;
5259 g_print (obj->vtable->klass->name);
5260 g_assert_not_reached ();