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"
26 #include "rawbuffer.h"
27 #include "mono-endian.h"
29 #include <mono/os/gc_wrapper.h>
31 #define TEXT_OFFSET 512
32 #define CLI_H_SIZE 136
33 #define FILE_ALIGN 512
34 #define VIRT_ALIGN 8192
35 #define START_TEXT_RVA 0x00002000
38 MonoReflectionILGen *ilgen;
39 MonoReflectionType *rtype;
40 MonoArray *parameters;
45 guint32 *table_idx; /* note: it's a pointer */
49 MonoBoolean init_locals;
50 } ReflectionMethodBuilder;
52 const unsigned char table_sizes [64] = {
62 MONO_INTERFACEIMPL_SIZE,
63 MONO_MEMBERREF_SIZE, /* 0x0A */
65 MONO_CUSTOM_ATTR_SIZE,
66 MONO_FIELD_MARSHAL_SIZE,
67 MONO_DECL_SECURITY_SIZE,
68 MONO_CLASS_LAYOUT_SIZE,
69 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
70 MONO_STAND_ALONE_SIGNATURE_SIZE,
74 MONO_PROPERTY_MAP_SIZE,
77 MONO_METHOD_SEMA_SIZE,
79 MONO_MODULEREF_SIZE, /* 0x1A */
85 MONO_ASSEMBLY_SIZE, /* 0x20 */
86 MONO_ASSEMBLY_PROCESSOR_SIZE,
88 MONO_ASSEMBLYREF_SIZE,
89 MONO_ASSEMBLYREFPROC_SIZE,
90 MONO_ASSEMBLYREFOS_SIZE,
94 MONO_NESTED_CLASS_SIZE,
98 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
99 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
100 static guint32 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo);
103 alloc_table (MonoDynamicTable *table, guint nrows)
106 g_assert (table->columns);
107 table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
111 string_heap_insert (MonoDynamicStream *sh, const char *str)
115 gpointer oldkey, oldval;
117 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
118 return GPOINTER_TO_UINT (oldval);
120 len = strlen (str) + 1;
122 if (idx + len > sh->alloc_size) {
123 sh->alloc_size += len + 4096;
124 sh->data = g_realloc (sh->data, sh->alloc_size);
127 * We strdup the string even if we already copy them in sh->data
128 * so that the string pointers in the hash remain valid even if
129 * we need to realloc sh->data. We may want to avoid that later.
131 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
132 memcpy (sh->data + idx, str, len);
138 string_heap_init (MonoDynamicStream *sh)
141 sh->alloc_size = 4096;
142 sh->data = g_malloc (4096);
143 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
144 string_heap_insert (sh, "");
147 #if 0 /* never used */
149 string_heap_free (MonoDynamicStream *sh)
152 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
153 g_hash_table_destroy (sh->hash);
158 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
161 if (stream->alloc_size < stream->index + len) {
162 stream->alloc_size += len + 4096;
163 stream->data = g_realloc (stream->data, stream->alloc_size);
165 memcpy (stream->data + stream->index, data, len);
167 stream->index += len;
169 * align index? Not without adding an additional param that controls it since
170 * we may store a blob value in pieces.
176 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
179 if (stream->alloc_size < stream->index + len) {
180 stream->alloc_size += len + 4096;
181 stream->data = g_realloc (stream->data, stream->alloc_size);
183 memset (stream->data + stream->index, 0, len);
185 stream->index += len;
190 stream_data_align (MonoDynamicStream *stream)
193 guint32 count = stream->index % 4;
195 /* we assume the stream data will be aligned */
197 mono_image_add_stream_data (stream, buf, 4 - count);
200 /* modified version needed to handle building corlib */
202 my_mono_class_from_mono_type (MonoType *type) {
203 switch (type->type) {
204 case MONO_TYPE_ARRAY:
206 case MONO_TYPE_SZARRAY:
207 return mono_class_from_mono_type (type);
209 /* should be always valid when we reach this case... */
210 return type->data.klass;
215 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
218 g_assert_not_reached ();
223 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
227 case MONO_TYPE_BOOLEAN:
241 case MONO_TYPE_STRING:
242 case MONO_TYPE_OBJECT:
243 case MONO_TYPE_TYPEDBYREF:
244 mono_metadata_encode_value (type->type, p, &p);
247 case MONO_TYPE_SZARRAY:
248 mono_metadata_encode_value (type->type, p, &p);
249 encode_type (assembly, type->data.type, p, &p);
251 case MONO_TYPE_VALUETYPE:
252 case MONO_TYPE_CLASS:
253 mono_metadata_encode_value (type->type, p, &p);
254 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
257 case MONO_TYPE_VALUETYPE:
258 case MONO_TYPE_CLASS: {
259 MonoClass *k = mono_class_from_mono_type (type);
260 mono_metadata_encode_value (type->type, p, &p);
261 /* ensure only non-byref gets passed to mono_image_typedef_or_ref() */
262 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
266 case MONO_TYPE_ARRAY:
267 mono_metadata_encode_value (type->type, p, &p);
268 encode_type (assembly, type->data.array->type, p, &p);
269 mono_metadata_encode_value (type->data.array->rank, p, &p);
270 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
271 mono_metadata_encode_value (0, p, &p);
274 g_error ("need to encode type %x", type->type);
280 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
283 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
287 encode_type (assembly, type->type, p, endbuf);
291 g_assert_not_reached ();
296 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
301 guint32 nparams = sig->param_count;
302 guint32 size = 10 + nparams * 10;
307 p = buf = g_malloc (size);
309 * FIXME: vararg, explicit_this, differenc call_conv values...
311 *p = sig->call_convention;
313 *p |= 0x20; /* hasthis */
315 mono_metadata_encode_value (nparams, p, &p);
316 encode_type (assembly, sig->ret, p, &p);
317 for (i = 0; i < nparams; ++i)
318 encode_type (assembly, sig->params [i], p, &p);
320 g_assert (p - buf < size);
321 mono_metadata_encode_value (p-buf, b, &b);
322 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
323 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
329 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
332 * FIXME: reuse code from method_encode_signature().
337 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
338 guint32 size = 10 + nparams * 10;
343 p = buf = g_malloc (size);
344 /* LAMESPEC: all the call conv spec is foobared */
345 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
346 if (mb->call_conv & 2)
347 *p |= 0x5; /* vararg */
348 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
349 *p |= 0x20; /* hasthis */
351 mono_metadata_encode_value (nparams, p, &p);
352 encode_reflection_type (assembly, mb->rtype, p, &p);
353 for (i = 0; i < nparams; ++i) {
354 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
355 encode_reflection_type (assembly, pt, p, &p);
358 g_assert (p - buf < size);
359 mono_metadata_encode_value (p-buf, b, &b);
360 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
361 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
367 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
369 MonoDynamicTable *table;
372 guint32 idx, sig_idx, size;
373 guint nl = mono_array_length (ilgen->locals);
380 p = buf = g_malloc (size);
381 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
382 idx = table->next_idx ++;
384 alloc_table (table, table->rows);
385 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
387 mono_metadata_encode_value (0x07, p, &p);
388 mono_metadata_encode_value (nl, p, &p);
389 for (i = 0; i < nl; ++i) {
390 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
391 encode_reflection_type (assembly, lb->type, p, &p);
393 g_assert (p - buf < size);
394 mono_metadata_encode_value (p-buf, b, &b);
395 sig_idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
396 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
399 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
405 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
411 gint32 num_locals = 0;
412 gint32 num_exception = 0;
415 char fat_header [12];
418 guint32 local_sig = 0;
419 guint32 header_size = 12;
422 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
423 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
424 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
425 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
429 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
431 code = mb->ilgen->code;
432 code_size = mb->ilgen->code_len;
433 max_stack = mb->ilgen->max_stack;
434 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
435 if (mb->ilgen->ex_handlers) {
436 MonoILExceptionInfo *ex_info;
437 for (i = 0; i < mono_array_length (mb->ilgen->ex_handlers); ++i) {
438 ex_info = (MonoILExceptionInfo*)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
439 if (ex_info->handlers)
440 num_exception += mono_array_length (ex_info->handlers);
447 code_size = mono_array_length (code);
448 max_stack = 8; /* we probably need to run a verifier on the code... */
451 /* check for exceptions, maxstack, locals */
452 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
454 if (code_size < 64 && !(code_size & 1)) {
455 flags = (code_size << 2) | 0x2;
456 } else if (code_size < 32 && (code_size & 1)) {
457 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
461 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
462 /* add to the fixup todo list */
463 if (mb->ilgen && mb->ilgen->num_token_fixups)
464 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
465 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
466 return assembly->text_rva + idx;
470 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
472 * FIXME: need to set also the header size in fat_flags.
473 * (and more sects and init locals flags)
477 fat_flags |= METHOD_HEADER_MORE_SECTS;
479 fat_flags |= METHOD_HEADER_INIT_LOCALS;
480 fat_header [0] = fat_flags;
481 fat_header [1] = (header_size / 4 ) << 4;
482 shortp = (guint16*)(fat_header + 2);
483 *shortp = GUINT16_TO_LE (max_stack);
484 intp = (guint32*)(fat_header + 4);
485 *intp = GUINT32_TO_LE (code_size);
486 intp = (guint32*)(fat_header + 8);
487 *intp = GUINT32_TO_LE (local_sig);
488 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
489 /* add to the fixup todo list */
490 if (mb->ilgen && mb->ilgen->num_token_fixups)
491 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
493 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
495 unsigned char sheader [4];
496 MonoExceptionClause clause;
497 MonoILExceptionInfo * ex_info;
498 MonoILExceptionBlock * ex_block;
501 stream_data_align (&assembly->code);
502 /* always use fat format for now */
503 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
504 num_exception *= sizeof (MonoExceptionClause);
505 num_exception += 4; /* include the size of the header */
506 sheader [1] = num_exception & 0xff;
507 sheader [2] = (num_exception >> 8) & 0xff;
508 sheader [3] = (num_exception >> 16) & 0xff;
509 mono_image_add_stream_data (&assembly->code, sheader, 4);
510 /* fat header, so we are already aligned */
512 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
513 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
514 if (ex_info->handlers) {
515 int finally_start = ex_info->start + ex_info->len;
516 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
517 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
518 clause.flags = GUINT32_TO_LE (ex_block->type);
519 clause.try_offset = GUINT32_TO_LE (ex_info->start);
520 /* need fault, too, probably */
521 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
522 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
524 clause.try_len = GUINT32_TO_LE (ex_info->len);
525 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
526 clause.handler_len = GUINT32_TO_LE (ex_block->len);
527 finally_start = ex_block->start + ex_block->len;
528 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
529 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
530 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
531 /*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",
532 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);*/
533 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
536 g_error ("No clauses for ex info block %d", i);
540 return assembly->text_rva + idx;
544 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 token)
547 MonoDynamicTable *table;
550 table = &assembly->tables [table_idx];
552 g_assert (col < table->columns);
554 values = table->values + table->columns;
555 for (i = 1; i <= table->rows; ++i) {
556 if (values [col] == token)
558 values += table->columns;
564 * idx is the table index of the object
565 * type is one of CUSTOM_ATTR_*
568 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
570 MonoDynamicTable *table;
571 MonoReflectionCustomAttr *cattr;
573 guint32 count, i, token;
577 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
580 count = mono_array_length (cattrs);
581 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
582 table->rows += count;
583 alloc_table (table, table->rows);
584 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
585 idx <<= CUSTOM_ATTR_BITS;
587 for (i = 0; i < count; ++i) {
588 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
589 values [MONO_CUSTOM_ATTR_PARENT] = idx;
590 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
591 type = mono_metadata_token_index (token);
592 type <<= CUSTOM_ATTR_TYPE_BITS;
593 switch (mono_metadata_token_table (token)) {
594 case MONO_TABLE_METHOD:
595 type |= CUSTOM_ATTR_TYPE_METHODDEF;
597 case MONO_TABLE_MEMBERREF:
598 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
601 g_warning ("got wrong token in custom attr");
604 values [MONO_CUSTOM_ATTR_TYPE] = type;
606 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
607 values [MONO_CUSTOM_ATTR_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, p - blob_size);
608 mono_image_add_stream_data (&assembly->blob,
609 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
610 values += MONO_CUSTOM_ATTR_SIZE;
617 * Fill in the MethodDef and ParamDef tables for a method.
618 * This is used for both normal methods and constructors.
621 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
623 MonoDynamicTable *table;
628 /* room in this table is already allocated */
629 table = &assembly->tables [MONO_TABLE_METHOD];
630 *mb->table_idx = table->next_idx ++;
631 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
633 name = mono_string_to_utf8 (mb->name);
634 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
636 } else { /* a constructor */
637 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
639 values [MONO_METHOD_FLAGS] = mb->attrs;
640 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
641 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
642 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
644 table = &assembly->tables [MONO_TABLE_PARAM];
645 values [MONO_METHOD_PARAMLIST] = table->next_idx;
648 MonoDynamicTable *mtable;
651 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
652 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
655 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
656 if (mono_array_get (mb->pinfo, gpointer, i))
659 table->rows += count;
660 alloc_table (table, table->rows);
661 values = table->values + table->next_idx * MONO_PARAM_SIZE;
662 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
663 MonoReflectionParamBuilder *pb;
664 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
665 values [MONO_PARAM_FLAGS] = pb->attrs;
666 values [MONO_PARAM_SEQUENCE] = i;
667 name = mono_string_to_utf8 (pb->name);
668 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
670 values += MONO_PARAM_SIZE;
671 if (pb->marshal_info) {
673 alloc_table (mtable, mtable->rows);
674 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
675 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
676 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
678 pb->table_idx = table->next_idx++;
685 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
687 MonoDynamicTable *table;
690 ReflectionMethodBuilder rmb;
692 rmb.ilgen = mb->ilgen;
693 rmb.rtype = mb->rtype;
694 rmb.parameters = mb->parameters;
695 rmb.pinfo = mb->pinfo;
696 rmb.attrs = mb->attrs;
697 rmb.iattrs = mb->iattrs;
698 rmb.call_conv = mb->call_conv;
702 rmb.table_idx = &mb->table_idx;
703 rmb.init_locals = mb->init_locals;
705 mono_image_basic_method (&rmb, assembly);
707 if (mb->dll) { /* It's a P/Invoke method */
709 table = &assembly->tables [MONO_TABLE_IMPLMAP];
711 alloc_table (table, table->rows);
712 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
713 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
714 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
715 name = mono_string_to_utf8 (mb->dllentry);
716 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
718 name = mono_string_to_utf8 (mb->dll);
719 moduleref = string_heap_insert (&assembly->sheap, name);
721 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
722 table = &assembly->tables [MONO_TABLE_MODULEREF];
724 alloc_table (table, table->rows);
725 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
726 values [MONO_IMPLMAP_SCOPE] = table->rows;
729 if (mb->override_method) {
730 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
732 table = &assembly->tables [MONO_TABLE_METHODIMPL];
734 alloc_table (table, table->rows);
735 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
736 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
737 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
738 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
739 switch (mono_metadata_token_table (tok)) {
740 case MONO_TABLE_MEMBERREF:
741 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
743 case MONO_TABLE_METHOD:
744 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
747 g_assert_not_reached ();
749 values [MONO_METHODIMPL_DECLARATION] = tok;
754 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
756 ReflectionMethodBuilder rmb;
758 rmb.ilgen = mb->ilgen;
759 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
760 rmb.parameters = mb->parameters;
761 rmb.pinfo = mb->pinfo;
762 rmb.attrs = mb->attrs;
763 rmb.iattrs = mb->iattrs;
764 rmb.call_conv = mb->call_conv;
768 rmb.table_idx = &mb->table_idx;
769 rmb.init_locals = mb->init_locals;
771 mono_image_basic_method (&rmb, assembly);
776 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
784 p = buf = g_malloc (64);
786 mono_metadata_encode_value (0x06, p, &p);
787 /* encode custom attributes before the type */
788 encode_type (assembly, field->type, p, &p);
789 g_assert (p-buf < 64);
790 mono_metadata_encode_value (p-buf, b, &b);
791 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
792 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
798 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
806 p = buf = g_malloc (64);
808 mono_metadata_encode_value (0x06, p, &p);
809 /* encode custom attributes before the type */
810 encode_reflection_type (assembly, fb->type, p, &p);
811 g_assert (p-buf < 64);
812 mono_metadata_encode_value (p-buf, b, &b);
813 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
814 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
820 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
821 * dest may be misaligned.
824 swap_with_size (char *dest, const char* val, int len, int nelem) {
825 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
828 for (elem = 0; elem < nelem; ++elem) {
854 g_assert_not_reached ();
860 memcpy (dest, val, len * nelem);
865 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
872 p = buf = g_malloc (64);
874 box_val = ((char*)val) + sizeof (MonoObject);
875 *ret_type = val->vtable->klass->byval_arg.type;
878 case MONO_TYPE_BOOLEAN:
898 case MONO_TYPE_VALUETYPE:
899 if (val->vtable->klass->enumtype) {
900 *ret_type = val->vtable->klass->enum_basetype->type;
903 g_error ("we can't encode valuetypes");
904 case MONO_TYPE_STRING: {
905 MonoString *str = (MonoString*)val;
906 /* there is no signature */
907 len = str->length * 2;
908 mono_metadata_encode_value (len, b, &b);
909 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
910 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
912 char *swapped = g_malloc (2 * mono_string_length (str));
913 const char *p = (const char*)mono_string_chars (str);
915 swap_with_size (swapped, p, 2, mono_string_length (str));
916 mono_image_add_stream_data (&assembly->blob, swapped, len);
920 mono_image_add_stream_data (&assembly->blob, (const char*)mono_string_chars (str), len);
927 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
930 /* there is no signature */
931 mono_metadata_encode_value (len, b, &b);
932 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
933 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
934 swap_with_size (blob_size, box_val, len, 1);
935 mono_image_add_stream_data (&assembly->blob, blob_size, len);
937 mono_image_add_stream_data (&assembly->blob, box_val, len);
945 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo) {
951 p = buf = g_malloc (256);
953 switch (minfo->type) {
954 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
956 mono_metadata_encode_value (minfo->type, p, &p);
960 mono_metadata_encode_value (len, b, &b);
961 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
962 mono_image_add_stream_data (&assembly->blob, buf, len);
968 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
970 MonoDynamicTable *table;
974 /* maybe this fixup should be done in the C# code */
975 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
976 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
977 table = &assembly->tables [MONO_TABLE_FIELD];
978 fb->table_idx = table->next_idx ++;
979 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
980 name = mono_string_to_utf8 (fb->name);
981 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
983 values [MONO_FIELD_FLAGS] = fb->attrs;
984 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
986 if (fb->offset != -1) {
987 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
989 alloc_table (table, table->rows);
990 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
991 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
992 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
994 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
995 guint32 field_type = 0;
996 table = &assembly->tables [MONO_TABLE_CONSTANT];
998 alloc_table (table, table->rows);
999 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1000 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1001 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1002 values [MONO_CONSTANT_TYPE] = field_type;
1003 values [MONO_CONSTANT_PADDING] = 0;
1007 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1009 alloc_table (table, table->rows);
1010 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1011 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1013 * We store it in the code section because it's simpler for now.
1015 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1016 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1018 if (fb->marshal_info) {
1019 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1021 alloc_table (table, table->rows);
1022 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1023 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1024 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1029 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
1033 char *b = blob_size;
1034 guint32 nparams = 0;
1035 MonoReflectionMethodBuilder *mb = fb->get_method;
1036 MonoReflectionMethodBuilder *smb = fb->set_method;
1037 guint32 idx, i, size;
1039 if (mb && mb->parameters)
1040 nparams = mono_array_length (mb->parameters);
1041 if (!mb && smb && smb->parameters)
1042 nparams = mono_array_length (smb->parameters) - 1;
1043 size = 24 + nparams * 10;
1044 buf = p = g_malloc (size);
1047 mono_metadata_encode_value (nparams, p, &p);
1049 encode_reflection_type (assembly, mb->rtype, p, &p);
1050 for (i = 0; i < nparams; ++i) {
1051 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1052 encode_reflection_type (assembly, pt, p, &p);
1055 /* the property type is the last param */
1056 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1057 for (i = 0; i < nparams; ++i) {
1058 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1059 encode_reflection_type (assembly, pt, p, &p);
1063 g_assert (p - buf < size);
1064 mono_metadata_encode_value (p-buf, b, &b);
1065 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1066 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
1072 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
1074 MonoDynamicTable *table;
1077 guint num_methods = 0;
1081 * we need to set things in the following tables:
1082 * PROPERTYMAP (info already filled in _get_type_info ())
1083 * PROPERTY (rows already preallocated in _get_type_info ())
1084 * METHOD (method info already done with the generic method code)
1087 table = &assembly->tables [MONO_TABLE_PROPERTY];
1088 pb->table_idx = table->next_idx ++;
1089 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1090 name = mono_string_to_utf8 (pb->name);
1091 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1093 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1094 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1096 /* FIXME: we still don't handle 'other' methods */
1097 if (pb->get_method) num_methods ++;
1098 if (pb->set_method) num_methods ++;
1100 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1101 table->rows += num_methods;
1102 alloc_table (table, table->rows);
1104 if (pb->get_method) {
1105 semaidx = table->next_idx ++;
1106 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1107 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1108 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1109 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1111 if (pb->set_method) {
1112 semaidx = table->next_idx ++;
1113 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1114 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1115 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1116 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1121 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
1123 MonoDynamicTable *table;
1126 guint num_methods = 0;
1130 * we need to set things in the following tables:
1131 * EVENTMAP (info already filled in _get_type_info ())
1132 * EVENT (rows already preallocated in _get_type_info ())
1133 * METHOD (method info already done with the generic method code)
1136 table = &assembly->tables [MONO_TABLE_EVENT];
1137 eb->table_idx = table->next_idx ++;
1138 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1139 name = mono_string_to_utf8 (eb->name);
1140 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1142 values [MONO_EVENT_FLAGS] = eb->attrs;
1143 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1146 * FIXME: we still don't handle 'other' methods
1148 if (eb->add_method) num_methods ++;
1149 if (eb->remove_method) num_methods ++;
1150 if (eb->raise_method) num_methods ++;
1152 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1153 table->rows += num_methods;
1154 alloc_table (table, table->rows);
1156 if (eb->add_method) {
1157 semaidx = table->next_idx ++;
1158 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1159 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1160 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1161 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1163 if (eb->remove_method) {
1164 semaidx = table->next_idx ++;
1165 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1166 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1167 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1168 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1170 if (eb->raise_method) {
1171 semaidx = table->next_idx ++;
1172 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1173 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1174 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1175 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1180 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
1182 MonoDynamicTable *table;
1185 guint32 cols [MONO_ASSEMBLY_SIZE];
1189 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1192 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1194 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1195 token = table->next_idx ++;
1197 alloc_table (table, table->rows);
1198 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1199 if (strcmp ("corlib", image->assembly_name) == 0)
1200 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1202 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1203 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1204 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1205 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1206 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1207 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1208 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1209 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1211 if ((pubkey = mono_image_get_public_key (image, &publen))) {
1212 guchar pubtoken [9];
1214 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
1215 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
1217 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1219 token <<= RESOLTION_SCOPE_BITS;
1220 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1221 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1226 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1228 MonoDynamicTable *table;
1234 char *b = blob_size;
1236 switch (type->type) {
1237 case MONO_TYPE_FNPTR:
1239 case MONO_TYPE_SZARRAY:
1240 case MONO_TYPE_ARRAY:
1241 encode_type (assembly, type, p, &p);
1247 g_assert (p-sig < 128);
1248 mono_metadata_encode_value (p-sig, b, &b);
1249 token = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1250 mono_image_add_stream_data (&assembly->blob, sig, p-sig);
1252 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1253 alloc_table (table, table->rows + 1);
1254 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1255 values [MONO_TYPESPEC_SIGNATURE] = token;
1257 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1258 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1264 * Despite the name, we handle also TypeSpec (with the above helper).
1267 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1269 MonoDynamicTable *table;
1271 guint32 token, scope, enclosing;
1274 #define COMPILE_CORLIB 0
1276 /* nasty hack, need to find the proper solution */
1277 if (type->type == MONO_TYPE_OBJECT)
1278 return TYPEDEFORREF_TYPEDEF | (2 << TYPEDEFORREF_BITS);
1280 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1283 token = create_typespec (assembly, type);
1286 klass = my_mono_class_from_mono_type (type);
1288 klass = mono_class_from_mono_type (type);
1290 * If it's in the same module:
1292 if (klass->image == assembly->assembly.image) {
1293 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1294 return TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1297 if (klass->nested_in) {
1298 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1299 /* get the typeref idx of the enclosing type */
1300 enclosing >>= TYPEDEFORREF_BITS;
1301 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1303 scope = resolution_scope_from_image (assembly, klass->image);
1305 table = &assembly->tables [MONO_TABLE_TYPEREF];
1306 alloc_table (table, table->rows + 1);
1307 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1308 values [MONO_TYPEREF_SCOPE] = scope;
1309 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1310 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1311 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1312 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1318 * Insert a memberef row into the metadata: the token that point to the memberref
1319 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1320 * mono_image_get_fieldref_token()).
1321 * The sig param is an index to an already built signature.
1324 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1326 MonoDynamicTable *table;
1328 guint32 token, pclass;
1331 parent = mono_image_typedef_or_ref (assembly, type);
1332 switch (parent & TYPEDEFORREF_MASK) {
1333 case TYPEDEFORREF_TYPEREF:
1334 pclass = MEMBERREF_PARENT_TYPEREF;
1336 case TYPEDEFORREF_TYPESPEC:
1337 pclass = MEMBERREF_PARENT_TYPESPEC;
1339 case TYPEDEFORREF_TYPEDEF:
1340 /* should never get here */
1342 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
1345 /* extract the index */
1346 parent >>= TYPEDEFORREF_BITS;
1348 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1349 alloc_table (table, table->rows + 1);
1350 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1351 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1352 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1353 values [MONO_MEMBERREF_SIGNATURE] = sig;
1354 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1361 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1365 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1368 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1369 method->name, method_encode_signature (assembly, method->signature));
1370 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1375 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1379 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1382 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
1383 field->name, fieldref_encode_signature (assembly, field));
1384 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1389 reflection_cc_to_file (int call_conv) {
1390 switch (call_conv & 0x3) {
1392 case 1: return MONO_CALL_DEFAULT;
1393 case 2: return MONO_CALL_VARARG;
1395 g_assert_not_reached ();
1402 MonoMethodSignature *sig;
1408 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1413 MonoMethodSignature *sig;
1416 name = mono_string_to_utf8 (m->name);
1417 nparams = mono_array_length (m->parameters);
1418 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1420 sig->call_convention = reflection_cc_to_file (m->call_conv);
1421 sig->param_count = nparams;
1422 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1423 for (i = 0; i < nparams; ++i) {
1424 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1425 sig->params [i] = t->type;
1428 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1430 if (strcmp (name, am->name) == 0 &&
1431 mono_metadata_type_equal (am->parent, m->parent->type) &&
1432 mono_metadata_signature_equal (am->sig, sig)) {
1438 am = g_new0 (ArrayMethod, 1);
1441 am->parent = m->parent->type;
1442 am->token = mono_image_get_memberref_token (assembly, am->parent,
1443 name, method_encode_signature (assembly, sig));
1444 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1445 m->table_idx = am->token & 0xffffff;
1450 * Insert into the metadata tables all the info about the TypeBuilder tb.
1451 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1454 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1456 MonoDynamicTable *table;
1458 int i, is_object = 0, is_system = 0;
1461 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1462 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1463 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1464 n = mono_string_to_utf8 (tb->name);
1465 if (strcmp (n, "Object") == 0)
1467 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1469 n = mono_string_to_utf8 (tb->nspace);
1470 if (strcmp (n, "System") == 0)
1472 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1474 if (tb->parent && !(is_system && is_object)) { /* interfaces don't have a parent */
1475 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1477 values [MONO_TYPEDEF_EXTENDS] = 0;
1478 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1479 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1482 * if we have explicitlayout or sequentiallayouts, output data in the
1483 * ClassLayout table.
1485 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1486 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1488 alloc_table (table, table->rows);
1489 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1490 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1491 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1492 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1495 /* handle interfaces */
1496 if (tb->interfaces) {
1497 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1499 table->rows += mono_array_length (tb->interfaces);
1500 alloc_table (table, table->rows);
1501 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1502 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1503 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1504 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1505 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1506 values += MONO_INTERFACEIMPL_SIZE;
1512 table = &assembly->tables [MONO_TABLE_FIELD];
1513 table->rows += mono_array_length (tb->fields);
1514 alloc_table (table, table->rows);
1515 for (i = 0; i < mono_array_length (tb->fields); ++i)
1516 mono_image_get_field_info (
1517 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1520 /* handle constructors */
1522 table = &assembly->tables [MONO_TABLE_METHOD];
1523 table->rows += mono_array_length (tb->ctors);
1524 alloc_table (table, table->rows);
1525 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1526 mono_image_get_ctor_info (domain,
1527 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1530 /* handle methods */
1532 table = &assembly->tables [MONO_TABLE_METHOD];
1533 table->rows += mono_array_length (tb->methods);
1534 alloc_table (table, table->rows);
1535 for (i = 0; i < mono_array_length (tb->methods); ++i)
1536 mono_image_get_method_info (
1537 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1540 /* Do the same with properties etc.. */
1541 if (tb->events && mono_array_length (tb->events)) {
1542 table = &assembly->tables [MONO_TABLE_EVENT];
1543 table->rows += mono_array_length (tb->events);
1544 alloc_table (table, table->rows);
1545 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1547 alloc_table (table, table->rows);
1548 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1549 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1550 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1551 for (i = 0; i < mono_array_length (tb->events); ++i)
1552 mono_image_get_event_info (
1553 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1555 if (tb->properties && mono_array_length (tb->properties)) {
1556 table = &assembly->tables [MONO_TABLE_PROPERTY];
1557 table->rows += mono_array_length (tb->properties);
1558 alloc_table (table, table->rows);
1559 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1561 alloc_table (table, table->rows);
1562 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1563 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1564 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1565 for (i = 0; i < mono_array_length (tb->properties); ++i)
1566 mono_image_get_property_info (
1567 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1570 MonoDynamicTable *ntable;
1572 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1573 table->rows += mono_array_length (tb->subtypes);
1574 alloc_table (table, table->rows);
1576 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1577 ntable->rows += mono_array_length (tb->subtypes);
1578 alloc_table (ntable, ntable->rows);
1579 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1581 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1582 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1584 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1585 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1586 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1587 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1588 mono_string_to_utf8 (tb->name), tb->table_idx,
1589 ntable->next_idx, ntable->rows);*/
1590 values += MONO_NESTED_CLASS_SIZE;
1593 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1594 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1596 mono_image_get_type_info (domain, subtype, assembly);
1602 assign_type_idx (MonoReflectionTypeBuilder *type, MonoDynamicTable *table)
1606 type->table_idx = table->next_idx ++;
1607 if (!type->subtypes)
1609 for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1610 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1611 assign_type_idx (subtype, table);
1616 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
1621 for (i = 0; i < mono_array_length (pinfo); ++i) {
1622 MonoReflectionParamBuilder *pb;
1623 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
1626 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
1631 type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
1634 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1636 for (i = 0; i < mono_array_length (tb->fields); ++i) {
1637 MonoReflectionFieldBuilder* fb;
1638 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
1639 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
1643 for (i = 0; i < mono_array_length (tb->events); ++i) {
1644 MonoReflectionEventBuilder* eb;
1645 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
1646 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1649 if (tb->properties) {
1650 for (i = 0; i < mono_array_length (tb->properties); ++i) {
1651 MonoReflectionPropertyBuilder* pb;
1652 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
1653 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
1657 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
1658 MonoReflectionCtorBuilder* cb;
1659 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
1660 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
1661 params_add_cattrs (assembly, cb->pinfo);
1666 for (i = 0; i < mono_array_length (tb->methods); ++i) {
1667 MonoReflectionMethodBuilder* mb;
1668 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
1669 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
1670 params_add_cattrs (assembly, mb->pinfo);
1675 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
1676 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
1681 module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
1684 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1686 for (i = 0; i < mono_array_length (mb->types); ++i)
1687 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
1691 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1693 MonoDynamicTable *table;
1697 table = &assembly->tables [MONO_TABLE_MODULE];
1698 mb->table_idx = table->next_idx ++;
1699 name = mono_string_to_utf8 (mb->module.name);
1700 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1702 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1705 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1706 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1707 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1710 * fill-in info in other tables as well.
1712 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1713 table->rows += mono_array_length (mb->types);
1714 alloc_table (table, table->rows);
1716 * We assign here the typedef indexes to avoid mismatches if a type that
1717 * has not yet been stored in the tables is referenced by another type.
1719 for (i = 0; i < mono_array_length (mb->types); ++i) {
1720 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1721 assign_type_idx (type, table);
1723 for (i = 0; i < mono_array_length (mb->types); ++i)
1724 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1727 #define align_pointer(base,p)\
1729 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1731 (p) += 4 - (__diff & 3);\
1735 compare_semantics (const void *a, const void *b)
1737 const guint32 *a_values = a;
1738 const guint32 *b_values = b;
1739 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
1742 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
1746 compare_custom_attrs (const void *a, const void *b)
1748 const guint32 *a_values = a;
1749 const guint32 *b_values = b;
1751 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
1755 compare_field_marshal (const void *a, const void *b)
1757 const guint32 *a_values = a;
1758 const guint32 *b_values = b;
1760 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
1764 compare_nested (const void *a, const void *b)
1766 const guint32 *a_values = a;
1767 const guint32 *b_values = b;
1769 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
1773 * build_compressed_metadata() fills in the blob of data that represents the
1774 * raw metadata as it will be saved in the PE file. The five streams are output
1775 * and the metadata tables are comnpressed from the guint32 array representation,
1776 * to the compressed on-disk format.
1779 build_compressed_metadata (MonoDynamicAssembly *assembly)
1781 MonoDynamicTable *table;
1783 guint64 valid_mask = 0;
1784 guint64 sorted_mask;
1785 guint32 heapt_size = 0;
1786 guint32 meta_size = 256; /* allow for header and other stuff */
1787 guint32 table_offset;
1788 guint32 ntables = 0;
1795 * We need to use the current ms version or the ms runtime it won't find
1796 * the support dlls. D'oh!
1797 * const char *version = "mono-" VERSION;
1799 const char *version = "v1.0.3705";
1802 MonoDynamicStream *stream;
1803 } stream_desc [] = {
1804 {"#~", &assembly->tstream},
1805 {"#Strings", &assembly->sheap},
1806 {"#US", &assembly->us},
1807 {"#Blob", &assembly->blob},
1808 {"#GUID", &assembly->guid}
1811 /* tables that are sorted */
1812 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
1813 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
1814 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
1815 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
1816 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
1817 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
1819 /* Compute table sizes */
1820 /* the MonoImage has already been created in mono_image_basic_init() */
1821 meta = assembly->assembly.image;
1823 /* Setup the info used by compute_sizes () */
1824 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1825 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1826 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1828 meta_size += assembly->blob.index;
1829 meta_size += assembly->guid.index;
1830 meta_size += assembly->sheap.index;
1831 meta_size += assembly->us.index;
1833 for (i=0; i < 64; ++i)
1834 meta->tables [i].rows = assembly->tables [i].rows;
1836 for (i = 0; i < 64; i++){
1837 if (meta->tables [i].rows == 0)
1839 valid_mask |= (guint64)1 << i;
1841 meta->tables [i].row_size = mono_metadata_compute_size (
1842 meta, i, &meta->tables [i].size_bitfield);
1843 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1845 heapt_size += 24; /* #~ header size */
1846 heapt_size += ntables * 4;
1847 meta_size += heapt_size;
1848 meta->raw_metadata = g_malloc0 (meta_size);
1849 p = meta->raw_metadata;
1850 /* the metadata signature */
1851 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1852 /* version numbers and 4 bytes reserved */
1853 int16val = (guint16*)p;
1854 *int16val++ = GUINT16_TO_LE (1);
1855 *int16val = GUINT16_TO_LE (1);
1857 /* version string */
1858 int32val = (guint32*)p;
1859 *int32val = GUINT32_TO_LE ((strlen (version) + 3) & (~3)); /* needs to be multiple of 4 */
1861 memcpy (p, version, GUINT32_FROM_LE (*int32val));
1862 p += GUINT32_FROM_LE (*int32val);
1863 align_pointer (meta->raw_metadata, p);
1864 int16val = (guint16*)p;
1865 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
1866 *int16val = GUINT16_TO_LE (5); /* number of streams */
1870 * write the stream info.
1872 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1873 table_offset += 3; table_offset &= ~3;
1875 assembly->tstream.index = heapt_size;
1876 for (i = 0; i < 5; ++i) {
1877 int32val = (guint32*)p;
1878 stream_desc [i].stream->offset = table_offset;
1879 *int32val++ = GUINT32_TO_LE (table_offset);
1880 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
1881 table_offset += GUINT32_FROM_LE (*int32val);
1882 table_offset += 3; table_offset &= ~3;
1884 strcpy (p, stream_desc [i].name);
1885 p += strlen (stream_desc [i].name) + 1;
1886 align_pointer (meta->raw_metadata, p);
1889 * now copy the data, the table stream header and contents goes first.
1891 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1892 p = meta->raw_metadata + assembly->tstream.offset;
1893 int32val = (guint32*)p;
1894 *int32val = GUINT32_TO_LE (0); /* reserved */
1896 *p++ = 1; /* version */
1898 if (meta->idx_string_wide)
1900 if (meta->idx_guid_wide)
1902 if (meta->idx_blob_wide)
1905 *p++ = 0; /* reserved */
1906 int64val = (guint64*)p;
1907 *int64val++ = GUINT64_TO_LE (valid_mask);
1908 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
1910 int32val = (guint32*)p;
1911 for (i = 0; i < 64; i++){
1912 if (meta->tables [i].rows == 0)
1914 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
1916 p = (unsigned char*)int32val;
1918 /* sort the tables that still need sorting */
1919 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1921 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
1922 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1924 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
1925 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1927 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
1928 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1930 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
1932 /* compress the tables */
1933 for (i = 0; i < 64; i++){
1936 guint32 bitfield = meta->tables [i].size_bitfield;
1937 if (!meta->tables [i].rows)
1939 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1940 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1941 meta->tables [i].base = p;
1942 for (row = 1; row <= meta->tables [i].rows; ++row) {
1943 values = assembly->tables [i].values + row * assembly->tables [i].columns;
1944 for (col = 0; col < assembly->tables [i].columns; ++col) {
1945 switch (mono_metadata_table_size (bitfield, col)) {
1947 *p++ = values [col];
1950 *p++ = values [col] & 0xff;
1951 *p++ = (values [col] >> 8) & 0xff;
1954 *p++ = values [col] & 0xff;
1955 *p++ = (values [col] >> 8) & 0xff;
1956 *p++ = (values [col] >> 16) & 0xff;
1957 *p++ = (values [col] >> 24) & 0xff;
1960 g_assert_not_reached ();
1964 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1967 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1968 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1969 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1970 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1971 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1973 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1977 * Some tables in metadata need to be sorted according to some criteria, but
1978 * when methods and fields are first created with reflection, they may be assigned a token
1979 * that doesn't correspond to the final token they will get assigned after the sorting.
1980 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
1981 * with the reflection objects that represent them. Once all the tables are set up, the
1982 * reflection objects will contains the correct table index. fixup_method() will fixup the
1983 * tokens for the method with ILGenerator @ilgen.
1986 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
1987 guint32 code_idx = GPOINTER_TO_UINT (value);
1988 MonoReflectionILTokenInfo *iltoken;
1989 MonoReflectionFieldBuilder *field;
1990 MonoReflectionCtorBuilder *ctor;
1991 MonoReflectionMethodBuilder *method;
1992 MonoReflectionTypeBuilder *tb;
1994 unsigned char *target;
1996 for (i = 0; i < ilgen->num_token_fixups; ++i) {
1997 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
1998 target = assembly->code.data + code_idx + iltoken->code_pos;
1999 switch (target [3]) {
2000 case MONO_TABLE_FIELD:
2001 if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
2002 g_assert_not_reached ();
2003 field = (MonoReflectionFieldBuilder *)iltoken->member;
2004 idx = field->table_idx;
2006 case MONO_TABLE_METHOD:
2007 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
2008 method = (MonoReflectionMethodBuilder *)iltoken->member;
2009 idx = method->table_idx;
2010 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
2011 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
2012 idx = ctor->table_idx;
2014 g_assert_not_reached ();
2017 case MONO_TABLE_TYPEDEF:
2018 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
2019 g_assert_not_reached ();
2020 tb = (MonoReflectionTypeBuilder *)iltoken->member;
2021 idx = tb->table_idx;
2024 g_error ("got unexpected table 0x%02x in fixup", target [3]);
2026 target [0] = idx & 0xff;
2027 target [1] = (idx >> 8) & 0xff;
2028 target [2] = (idx >> 16) & 0xff;
2033 assembly_add_resource (MonoDynamicAssembly *assembly, MonoReflectionResource *rsrc)
2035 MonoDynamicTable *table;
2039 char *b = blob_size;
2041 guint32 idx, offset;
2043 if (rsrc->filename) {
2044 name = mono_string_to_utf8 (rsrc->filename);
2045 sname = g_path_get_basename (name);
2047 table = &assembly->tables [MONO_TABLE_FILE];
2049 alloc_table (table, table->rows);
2050 values = table->values + table->next_idx * MONO_FILE_SIZE;
2051 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
2052 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
2055 mono_sha1_get_digest_from_file (name, hash);
2056 mono_metadata_encode_value (20, b, &b);
2057 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2058 mono_image_add_stream_data (&assembly->blob, hash, 20);
2060 idx = table->next_idx++;
2061 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
2065 offset = mono_array_length (rsrc->data);
2066 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
2067 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
2068 offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
2069 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
2073 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
2075 alloc_table (table, table->rows);
2076 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
2077 values [MONO_MANIFEST_OFFSET] = offset;
2078 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
2079 name = mono_string_to_utf8 (rsrc->name);
2080 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
2082 values [MONO_MANIFEST_IMPLEMENTATION] = idx;
2087 set_version_from_string (MonoString *version, guint32 *values)
2089 gchar *ver, *p, *str;
2092 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
2093 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
2094 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
2095 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
2098 ver = str = mono_string_to_utf8 (version);
2099 for (i = 0; i < 4; ++i) {
2100 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
2106 /* handle Revision and Build */
2116 load_public_key (MonoString *fname, MonoDynamicAssembly *assembly) {
2117 char *name, *content;
2123 name = mono_string_to_utf8 (fname);
2124 if (g_file_get_contents (name, &content, &len, NULL)) {
2126 char *b = blob_size;
2127 /* check it's a public key or keypair */
2128 mono_metadata_encode_value (len, b, &b);
2129 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
2130 mono_image_add_stream_data (&assembly->blob, content, len);
2132 /* need to get the actual value from the key type... */
2133 assembly->strong_name_size = 128;
2134 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
2136 /* FIXME: how do we tell mcs if loading fails? */
2142 * mono_image_build_metadata() will fill the info in all the needed metadata tables
2143 * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
2144 * and recursively outputs the info for a module. Each module will output all the info
2145 * about it's types etc.
2146 * At the end of the process, method and field tokens are fixed up and the on-disk
2147 * compressed metadata representation is created.
2150 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
2152 MonoDynamicTable *table;
2153 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
2154 MonoDomain *domain = mono_object_domain (assemblyb);
2160 assembly->text_rva = START_TEXT_RVA;
2162 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2163 alloc_table (table, 1);
2164 values = table->values + MONO_ASSEMBLY_SIZE;
2165 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2166 name = mono_string_to_utf8 (assemblyb->name);
2167 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
2169 if (assemblyb->culture) {
2170 name = mono_string_to_utf8 (assemblyb->culture);
2171 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
2174 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2176 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->keyfile, assembly);
2177 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2178 set_version_from_string (assemblyb->version, values);
2180 assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
2181 assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
2183 if (assemblyb->modules) {
2184 len = mono_array_length (assemblyb->modules);
2185 table = &assembly->tables [MONO_TABLE_MODULE];
2186 alloc_table (table, len);
2187 for (i = 0; i < len; ++i)
2188 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
2190 table = &assembly->tables [MONO_TABLE_MODULE];
2192 alloc_table (table, table->rows);
2193 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
2197 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2199 * table->rows is already set above and in mono_image_fill_module_table.
2201 alloc_table (table, table->rows);
2203 * Set the first entry.
2205 values = table->values + table->columns;
2206 values [MONO_TYPEDEF_FLAGS] = 0;
2207 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2208 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2209 values [MONO_TYPEDEF_EXTENDS] = 0;
2210 values [MONO_TYPEDEF_FIELD_LIST] = 1;
2211 values [MONO_TYPEDEF_METHOD_LIST] = 1;
2213 /* add all the custom attributes at the end, once all the indexes are stable */
2214 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
2216 if (assemblyb->modules) {
2217 len = mono_array_length (assemblyb->modules);
2218 for (i = 0; i < len; ++i)
2219 module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
2222 if (assemblyb->resources) {
2223 len = mono_array_length (assemblyb->resources);
2224 for (i = 0; i < len; ++i)
2225 assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
2229 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2231 build_compressed_metadata (assembly);
2235 * mono_image_insert_string:
2236 * @assembly: assembly builder object
2239 * Insert @str into the user string stream of @assembly.
2242 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
2248 if (!assembly->dynamic_assembly)
2249 mono_image_basic_init (assembly);
2250 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
2251 idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
2252 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2254 char *swapped = g_malloc (2 * mono_string_length (str));
2255 const char *p = (const char*)mono_string_chars (str);
2257 swap_with_size (swapped, p, 2, mono_string_length (str));
2258 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2262 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2264 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2265 return MONO_TOKEN_STRING | idx;
2269 * mono_image_create_token:
2270 * @assembly: a dynamic assembly
2273 * Get a token to insert in the IL code stream for the given MemberInfo.
2274 * @obj can be one of:
2275 * ConstructorBuilder
2285 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2291 g_error ("System.Array methods not yet supported");
2293 klass = obj->vtable->klass;
2294 if (strcmp (klass->name, "MethodBuilder") == 0) {
2295 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2296 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2297 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2300 if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2301 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2302 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2303 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2306 if (strcmp (klass->name, "FieldBuilder") == 0) {
2307 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2308 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
2310 if (strcmp (klass->name, "TypeBuilder") == 0) {
2311 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2312 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
2314 if (strcmp (klass->name, "MonoType") == 0) {
2315 MonoReflectionType *tb = (MonoReflectionType *)obj;
2316 return mono_metadata_token_from_dor (
2317 mono_image_typedef_or_ref (assembly, tb->type));
2319 if (strcmp (klass->name, "MonoCMethod") == 0 ||
2320 strcmp (klass->name, "MonoMethod") == 0) {
2321 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2322 token = mono_image_get_methodref_token (assembly, m->method);
2323 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2326 if (strcmp (klass->name, "MonoField") == 0) {
2327 MonoReflectionField *f = (MonoReflectionField *)obj;
2328 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2329 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2332 if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2333 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2334 token = mono_image_get_array_token (assembly, m);
2337 g_print ("requested token for %s\n", klass->name);
2342 guint32 import_lookup_table;
2346 guint32 import_address_table_rva;
2355 * mono_image_basic_ini:
2356 * @assembly: an assembly builder object
2358 * Create the MonoImage that represents the assembly builder and setup some
2359 * of the helper hash table and the basic metadata streams.
2362 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2364 static const guchar entrycode [16] = {0xff, 0x25, 0};
2365 MonoDynamicAssembly *assembly;
2369 if (assemblyb->dynamic_assembly)
2373 assembly = assemblyb->dynamic_assembly = GC_malloc (sizeof (MonoDynamicAssembly));
2375 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2378 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
2379 assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2380 assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2381 assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2383 string_heap_init (&assembly->sheap);
2384 mono_image_add_stream_data (&assembly->us, "", 1);
2385 mono_image_add_stream_data (&assembly->blob, "", 1);
2386 /* import tables... */
2387 mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2388 assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2389 assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2390 mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2391 assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2392 mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2393 assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2394 stream_data_align (&assembly->code);
2396 assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2398 for (i=0; i < 64; ++i) {
2399 assembly->tables [i].next_idx = 1;
2400 assembly->tables [i].columns = table_sizes [i];
2403 image = g_new0 (MonoImage, 1);
2405 /* keep in sync with image.c */
2406 assembly->assembly.aname.name = image->name = mono_string_to_utf8 (assemblyb->name);
2407 image->assembly_name = image->name; /* they may be different */
2409 image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2410 image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2411 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2412 image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2414 image->delegate_begin_invoke_cache =
2415 g_hash_table_new ((GHashFunc)mono_signature_hash,
2416 (GCompareFunc)mono_metadata_signature_equal);
2417 image->delegate_end_invoke_cache =
2418 g_hash_table_new ((GHashFunc)mono_signature_hash,
2419 (GCompareFunc)mono_metadata_signature_equal);
2420 image->delegate_invoke_cache =
2421 g_hash_table_new ((GHashFunc)mono_signature_hash,
2422 (GCompareFunc)mono_metadata_signature_equal);
2424 image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2425 image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2426 image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2427 image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2428 assembly->assembly.image = image;
2433 calc_section_size (MonoDynamicAssembly *assembly)
2437 /* alignment constraints */
2438 assembly->code.index += 3;
2439 assembly->code.index &= ~3;
2440 assembly->meta_size += 3;
2441 assembly->meta_size &= ~3;
2442 assembly->resources.index += 3;
2443 assembly->resources.index &= ~3;
2445 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2446 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2449 assembly->sections [MONO_SECTION_RELOC].size = 12;
2450 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2457 * mono_image_create_pefile:
2458 * @assemblyb: an assembly builder object
2460 * When we need to save an assembly, we first call this function that ensures the metadata
2461 * tables are built for all the modules in the assembly. This function creates the PE-COFF
2462 * header, the image sections, the CLI header etc. all the data is written in
2463 * assembly->pefile where it can be easily retrieved later in chunks.
2466 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
2467 MonoMSDOSHeader *msdos;
2468 MonoDotNetHeader *header;
2469 MonoSectionTable *section;
2470 MonoCLIHeader *cli_header;
2471 guint32 size, image_size, virtual_base, text_offset;
2472 guint32 header_start, section_start, file_offset, virtual_offset;
2473 MonoDynamicAssembly *assembly;
2474 MonoDynamicStream *pefile;
2476 guint32 *rva, value;
2479 static const unsigned char msheader[] = {
2480 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2481 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2484 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2485 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2486 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2487 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2490 mono_image_basic_init (assemblyb);
2491 assembly = assemblyb->dynamic_assembly;
2493 /* already created */
2494 if (assembly->pefile.index)
2497 mono_image_build_metadata (assemblyb);
2498 nsections = calc_section_size (assembly);
2500 pefile = &assembly->pefile;
2502 /* The DOS header and stub */
2503 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2504 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
2506 /* the dotnet header */
2507 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2509 /* the section tables */
2510 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2512 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2513 virtual_offset = VIRT_ALIGN;
2516 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2517 if (!assembly->sections [i].size)
2520 file_offset += FILE_ALIGN - 1;
2521 file_offset &= ~(FILE_ALIGN - 1);
2522 virtual_offset += VIRT_ALIGN - 1;
2523 virtual_offset &= ~(VIRT_ALIGN - 1);
2525 assembly->sections [i].offset = file_offset;
2526 assembly->sections [i].rva = virtual_offset;
2528 file_offset += assembly->sections [i].size;
2529 virtual_offset += assembly->sections [i].size;
2530 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2533 file_offset += FILE_ALIGN - 1;
2534 file_offset &= ~(FILE_ALIGN - 1);
2535 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
2537 image_size += section_start + sizeof (MonoSectionTable) * nsections;
2539 /* back-patch info */
2540 msdos = (MonoMSDOSHeader*)pefile->data;
2541 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
2542 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
2543 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2545 header = (MonoDotNetHeader*)(pefile->data + header_start);
2546 header->pesig [0] = 'P';
2547 header->pesig [1] = 'E';
2549 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
2550 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2551 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2552 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2553 if (assemblyb->pekind == 1) {
2555 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
2558 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2561 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2563 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2564 header->pe.pe_major = 6;
2565 header->pe.pe_minor = 0;
2566 size = assembly->sections [MONO_SECTION_TEXT].size;
2567 size += FILE_ALIGN - 1;
2568 size &= ~(FILE_ALIGN - 1);
2569 header->pe.pe_code_size = size;
2570 size = assembly->sections [MONO_SECTION_RSRC].size;
2571 size += FILE_ALIGN - 1;
2572 size &= ~(FILE_ALIGN - 1);
2573 header->pe.pe_data_size = size;
2574 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2575 header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
2576 header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
2577 /* pe_rva_entry_point always at the beginning of the text section */
2578 header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
2580 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2581 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2582 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2583 header->nt.pe_os_major = GUINT16_FROM_LE (4);
2584 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2585 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2586 size = section_start;
2587 size += FILE_ALIGN - 1;
2588 size &= ~(FILE_ALIGN - 1);
2589 header->nt.pe_header_size = GUINT32_FROM_LE (size);
2591 size += VIRT_ALIGN - 1;
2592 size &= ~(VIRT_ALIGN - 1);
2593 header->nt.pe_image_size = GUINT32_FROM_LE (size);
2594 header->nt.pe_subsys_required = GUINT16_FROM_LE (assemblyb->pekind); /* 3 -> cmdline app, 2 -> GUI app */
2595 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2596 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2597 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2598 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2599 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2600 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2602 /* fill data directory entries */
2604 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2605 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2607 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2608 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2610 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2611 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2612 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2613 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2614 /* patch imported function RVA name */
2615 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2616 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2618 /* the import table */
2619 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2620 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2621 /* patch imported dll RVA name and other entries in the dir */
2622 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2623 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
2624 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2625 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2626 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2627 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2629 p = (assembly->code.data + assembly->ilt_offset);
2630 value = (assembly->text_rva + assembly->imp_names_offset - 2);
2631 *p++ = (value) & 0xff;
2632 *p++ = (value >> 8) & (0xff);
2633 *p++ = (value >> 16) & (0xff);
2634 *p++ = (value >> 24) & (0xff);
2636 /* the CLI header info */
2637 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2638 cli_header->ch_size = GUINT32_FROM_LE (72);
2639 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
2640 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
2641 if (assemblyb->entry_point)
2642 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
2644 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
2645 /* The embedded managed resources */
2646 text_offset = assembly->text_rva + assembly->code.index;
2647 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
2648 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
2649 text_offset += assembly->resources.index;
2650 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
2651 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
2652 text_offset += assembly->meta_size;
2653 if (assembly->strong_name_size) {
2654 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
2655 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
2656 text_offset += assembly->strong_name_size;
2659 /* write the section tables and section content */
2660 section = (MonoSectionTable*)(pefile->data + section_start);
2661 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2662 static const char *section_names [] = {
2663 ".text", ".rsrc", ".reloc"
2665 if (!assembly->sections [i].size)
2667 strcpy (section->st_name, section_names [i]);
2668 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
2669 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
2670 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
2671 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
2672 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
2673 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
2674 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
2676 case MONO_SECTION_TEXT:
2677 /* patch entry point */
2678 p = (assembly->code.data + 2);
2679 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
2680 *p++ = (value) & 0xff;
2681 *p++ = (value >> 8) & 0xff;
2682 *p++ = (value >> 16) & 0xff;
2683 *p++ = (value >> 24) & 0xff;
2685 text_offset = assembly->sections [i].offset;
2686 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
2687 text_offset += assembly->code.index;
2688 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
2689 text_offset += assembly->resources.index;
2690 memcpy (pefile->data + text_offset, assembly->assembly.image->raw_metadata, assembly->meta_size);
2691 text_offset += assembly->meta_size;
2692 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
2694 case MONO_SECTION_RELOC:
2695 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
2696 *rva = GUINT32_FROM_LE (assembly->text_rva);
2698 *rva = GUINT32_FROM_LE (12);
2700 data16 = (guint16*)rva;
2702 * the entrypoint is always at the start of the text section
2703 * 3 is IMAGE_REL_BASED_HIGHLOW
2704 * 2 is patch_size_rva - text_rva
2706 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
2708 *data16 = 0; /* terminate */
2710 case MONO_SECTION_RSRC:
2712 g_assert_not_reached ();
2717 /* check that the file is properly padded */
2720 FILE *f = fopen ("mypetest.exe", "w");
2721 fwrite (pefile->data, pefile->index, 1, f);
2728 * We need to return always the same object for MethodInfo, FieldInfo etc..
2729 * but we need to consider the reflected type.
2730 * type uses a different hash, since it uses custom hash/equal functions.
2735 MonoClass *refclass;
2739 reflected_equal (gconstpointer a, gconstpointer b) {
2740 const ReflectedEntry *ea = a;
2741 const ReflectedEntry *eb = b;
2743 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
2747 reflected_hash (gconstpointer a) {
2748 const ReflectedEntry *ea = a;
2749 return GPOINTER_TO_UINT (ea->item);
2752 #define CHECK_OBJECT(t,p,k) \
2758 mono_domain_lock (domain); \
2759 if (!domain->refobject_hash) \
2760 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
2761 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
2762 mono_domain_unlock (domain); \
2767 #define CACHE_OBJECT(p,o,k) \
2769 ReflectedEntry *e = mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry)); \
2771 e->refclass = (k); \
2772 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
2773 mono_domain_unlock (domain); \
2777 * mono_assembly_get_object:
2778 * @domain: an app domain
2779 * @assembly: an assembly
2781 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
2783 MonoReflectionAssembly*
2784 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
2786 static MonoClass *System_Reflection_Assembly;
2787 MonoReflectionAssembly *res;
2789 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
2790 if (!System_Reflection_Assembly)
2791 System_Reflection_Assembly = mono_class_from_name (
2792 mono_defaults.corlib, "System.Reflection", "Assembly");
2793 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
2794 res->assembly = assembly;
2795 CACHE_OBJECT (assembly, res, NULL);
2800 MonoReflectionModule*
2801 mono_module_get_object (MonoDomain *domain, MonoImage *image)
2803 static MonoClass *System_Reflection_Module;
2804 MonoReflectionModule *res;
2806 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
2807 if (!System_Reflection_Module)
2808 System_Reflection_Module = mono_class_from_name (
2809 mono_defaults.corlib, "System.Reflection", "Module");
2810 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
2813 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
2815 res->fqname = mono_string_new (domain, image->name);
2816 res->name = mono_string_new (domain, image->name);
2817 res->scopename = mono_string_new (domain, image->module_name);
2819 CACHE_OBJECT (image, res, NULL);
2825 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
2827 if ((t1->type != t2->type) ||
2828 (t1->byref != t2->byref))
2832 case MONO_TYPE_VOID:
2833 case MONO_TYPE_BOOLEAN:
2834 case MONO_TYPE_CHAR:
2845 case MONO_TYPE_STRING:
2848 case MONO_TYPE_OBJECT:
2850 case MONO_TYPE_VALUETYPE:
2851 case MONO_TYPE_CLASS:
2852 return t1->data.klass == t2->data.klass;
2854 case MONO_TYPE_SZARRAY:
2855 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
2856 case MONO_TYPE_ARRAY:
2857 if (t1->data.array->rank != t2->data.array->rank)
2859 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
2861 g_error ("implement type compare for %0x!", t1->type);
2869 mymono_metadata_type_hash (MonoType *t1)
2875 hash |= t1->byref << 6; /* do not collide with t1->type values */
2877 case MONO_TYPE_VALUETYPE:
2878 case MONO_TYPE_CLASS:
2879 /* check if the distribution is good enough */
2880 return hash << 7 | g_str_hash (t1->data.klass->name);
2882 case MONO_TYPE_SZARRAY:
2883 return hash << 7 | mymono_metadata_type_hash (t1->data.type);
2889 * mono_type_get_object:
2890 * @domain: an app domain
2893 * Return an System.MonoType object representing the type @type.
2896 mono_type_get_object (MonoDomain *domain, MonoType *type)
2898 MonoReflectionType *res;
2899 MonoClass *klass = mono_class_from_mono_type (type);
2901 mono_domain_lock (domain);
2902 if (!domain->type_hash)
2903 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
2904 (GCompareFunc)mymono_metadata_type_equal);
2905 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
2906 mono_domain_unlock (domain);
2909 if (klass->reflection_info && !klass->wastypebuilder) {
2910 //g_assert_not_reached ();
2911 /* should this be considered an error condition? */
2913 mono_domain_unlock (domain);
2914 return klass->reflection_info;
2917 mono_class_init (klass);
2918 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
2920 mono_g_hash_table_insert (domain->type_hash, type, res);
2921 mono_domain_unlock (domain);
2926 * mono_method_get_object:
2927 * @domain: an app domain
2929 * @refclass: the reflected type (can be NULL)
2931 * Return an System.Reflection.MonoMethod object representing the method @method.
2933 MonoReflectionMethod*
2934 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
2937 * We use the same C representation for methods and constructors, but the type
2938 * name in C# is different.
2942 MonoReflectionMethod *ret;
2945 refclass = method->klass;
2947 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
2948 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
2949 cname = "MonoCMethod";
2951 cname = "MonoMethod";
2952 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
2954 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
2955 ret->method = method;
2956 ret->name = mono_string_new (domain, method->name);
2957 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
2958 CACHE_OBJECT (method, ret, refclass);
2963 * mono_field_get_object:
2964 * @domain: an app domain
2968 * Return an System.Reflection.MonoField object representing the field @field
2971 MonoReflectionField*
2972 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
2974 MonoReflectionField *res;
2977 CHECK_OBJECT (MonoReflectionField *, field, klass);
2978 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
2979 res = (MonoReflectionField *)mono_object_new (domain, oklass);
2982 CACHE_OBJECT (field, res, klass);
2987 * mono_property_get_object:
2988 * @domain: an app domain
2990 * @property: a property
2992 * Return an System.Reflection.MonoProperty object representing the property @property
2995 MonoReflectionProperty*
2996 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
2998 MonoReflectionProperty *res;
3001 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
3002 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
3003 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
3005 res->property = property;
3006 CACHE_OBJECT (property, res, klass);
3011 * mono_event_get_object:
3012 * @domain: an app domain
3016 * Return an System.Reflection.MonoEvent object representing the event @event
3019 MonoReflectionEvent*
3020 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
3022 MonoReflectionEvent *res;
3025 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
3026 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
3027 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
3030 CACHE_OBJECT (event, res, klass);
3035 * mono_param_get_objects:
3036 * @domain: an app domain
3039 * Return an System.Reflection.ParameterInfo array object representing the parameters
3040 * in the method @method.
3042 MonoReflectionParameter**
3043 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
3045 MonoReflectionParameter **res;
3046 MonoReflectionMethod *member;
3051 if (!method->signature->param_count)
3054 member = mono_method_get_object (domain, method, NULL);
3055 names = g_new (char *, method->signature->param_count);
3056 mono_method_get_param_names (method, (const char **) names);
3058 /* Note: the cache is based on the address of the signature into the method
3059 * since we already cache MethodInfos with the method as keys.
3061 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature), NULL);
3062 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
3064 res = GC_malloc (sizeof (MonoReflectionParameter*) * method->signature->param_count);
3066 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
3068 for (i = 0; i < method->signature->param_count; ++i) {
3069 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
3070 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
3071 res [i]->DefaultValueImpl = NULL; /* FIXME */
3072 res [i]->MemberImpl = (MonoObject*)member;
3073 res [i]->NameImpl = mono_string_new (domain, names [i]);
3074 res [i]->PositionImpl = i + 1;
3075 res [i]->AttrsImpl = method->signature->params [i]->attrs;
3078 CACHE_OBJECT (&(method->signature), res, NULL);
3083 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
3087 memset (assembly, 0, sizeof (MonoAssemblyName));
3089 assembly->culture = "";
3091 while (*p && (isalnum (*p) || *p == '.'))
3094 while (*p == ' ' || *p == ',') {
3103 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
3105 assembly->major = strtoul (p, &s, 10);
3106 if (s == p || *s != '.')
3109 assembly->minor = strtoul (p, &s, 10);
3110 if (s == p || *s != '.')
3113 assembly->build = strtoul (p, &s, 10);
3114 if (s == p || *s != '.')
3117 assembly->revision = strtoul (p, &s, 10);
3120 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
3122 if (strncmp (p, "neutral", 7) == 0) {
3123 assembly->culture = "";
3126 assembly->culture = p;
3127 while (*p && *p != ',') {
3131 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
3134 while (*s && isxdigit (*s)) {
3138 assembly->hash_len = s - p;
3139 if (!(s-p) || ((s-p) & 1))
3141 assembly->hash_value = s = p;
3142 while (*s && isxdigit (*s)) {
3144 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3147 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3155 while (*p == ' ' || *p == ',') {
3169 * mono_reflection_parse_type:
3172 * Parse a type name as accepted by the GetType () method and output the info
3173 * extracted in the info structure.
3174 * the name param will be mangled, so, make a copy before passing it to this function.
3175 * The fields in info will be valid until the memory pointed to by name is valid.
3176 * Returns 0 on parse error.
3177 * See also mono_type_get_name () below.
3180 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
3182 char *start, *p, *w, *last_point, *startn;
3183 int in_modifiers = 0;
3184 int isbyref = 0, rank;
3186 start = p = w = name;
3188 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
3189 info->name = info->name_space = NULL;
3190 info->nested = NULL;
3191 info->modifiers = NULL;
3193 /* last_point separates the namespace from the name */
3199 *p = 0; /* NULL terminate the name */
3201 /* we have parsed the nesting namespace + name */
3203 info->nested = g_list_append (info->nested, startn);
3207 info->name_space = start;
3209 info->name = last_point + 1;
3211 info->name_space = (char *)"";
3236 info->nested = g_list_append (info->nested, startn);
3239 info->name_space = start;
3241 info->name = last_point + 1;
3243 info->name_space = (char *)"";
3250 if (isbyref) /* only one level allowed by the spec */
3253 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
3257 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
3268 else if (*p != '*') /* '*' means unknown lower bound */
3274 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
3286 return 0; /* missing assembly name */
3287 if (!assembly_name_to_aname (&info->assembly, p))
3293 if (info->assembly.name)
3296 *w = 0; /* terminate class name */
3297 if (!info->name || !*info->name)
3299 /* add other consistency checks */
3304 mono_type_get_name_recurse (MonoType *type, GString *str)
3308 switch (type->type) {
3309 case MONO_TYPE_ARRAY: {
3310 int i, rank = type->data.array->rank;
3312 mono_type_get_name_recurse (type->data.array->type, str);
3313 g_string_append_c (str, '[');
3314 for (i = 1; i < rank; i++)
3315 g_string_append_c (str, ',');
3316 g_string_append_c (str, ']');
3319 case MONO_TYPE_SZARRAY:
3320 mono_type_get_name_recurse (type->data.type, str);
3321 g_string_append (str, "[]");
3324 mono_type_get_name_recurse (type->data.type, str);
3325 g_string_append_c (str, '*');
3328 klass = mono_class_from_mono_type (type);
3329 if (klass->nested_in) {
3330 mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
3331 g_string_append_c (str, '+');
3333 if (*klass->name_space) {
3334 g_string_append (str, klass->name_space);
3335 g_string_append_c (str, '.');
3337 g_string_append (str, klass->name);
3343 * mono_type_get_name:
3346 * Returns the string representation for type as required by System.Reflection.
3347 * The inverse of mono_reflection_parse_type ().
3350 mono_type_get_name (MonoType *type)
3352 GString* result = g_string_new ("");
3353 mono_type_get_name_recurse (type, result);
3356 g_string_append_c (result, '&');
3358 return g_string_free (result, FALSE);
3362 * mono_reflection_get_type:
3363 * @image: a metadata context
3364 * @info: type description structure
3365 * @ignorecase: flag for case-insensitive string compares
3367 * Build a MonoType from the type description in @info.
3371 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3378 image = mono_defaults.corlib;
3381 klass = mono_class_from_name_case (image, info->name_space, info->name);
3383 klass = mono_class_from_name (image, info->name_space, info->name);
3386 for (mod = info->nested; mod; mod = mod->next) {
3389 mono_class_init (klass);
3390 nested = klass->nested_classes;
3393 klass = nested->data;
3395 if (g_strcasecmp (klass->name, mod->data) == 0)
3398 if (strcmp (klass->name, mod->data) == 0)
3402 nested = nested->next;
3409 mono_class_init (klass);
3410 for (mod = info->modifiers; mod; mod = mod->next) {
3411 modval = GPOINTER_TO_UINT (mod->data);
3412 if (!modval) { /* byref: must be last modifier */
3413 return &klass->this_arg;
3414 } else if (modval == -1) {
3415 klass = mono_ptr_class_get (&klass->byval_arg);
3416 } else { /* array rank */
3417 klass = mono_array_class_get (&klass->byval_arg, modval);
3419 mono_class_init (klass);
3421 return &klass->byval_arg;
3425 * mono_reflection_type_from_name:
3427 * @image: a metadata context (can be NULL).
3429 * Retrieves a MonoType from its @name. If the name is not fully qualified,
3430 * it defaults to get the type from @image or, if @image is NULL or loading
3431 * from it fails, uses corlib.
3435 mono_reflection_type_from_name (char *name, MonoImage *image)
3438 MonoTypeNameParse info;
3440 /*g_print ("requested type %s\n", str);*/
3441 if (!mono_reflection_parse_type (name, &info)) {
3442 g_list_free (info.modifiers);
3443 g_list_free (info.nested);
3447 if (info.assembly.name) {
3448 image = mono_image_loaded (info.assembly.name);
3449 /* do we need to load if it's not already loaded? */
3451 g_list_free (info.modifiers);
3452 g_list_free (info.nested);
3455 } else if (image == NULL) {
3456 image = mono_defaults.corlib;
3459 type = mono_reflection_get_type (image, &info, FALSE);
3460 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
3461 image = mono_defaults.corlib;
3462 type = mono_reflection_get_type (image, &info, FALSE);
3465 g_list_free (info.modifiers);
3466 g_list_free (info.nested);
3471 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
3473 int slen, type = t->type;
3478 case MONO_TYPE_BOOLEAN: {
3479 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
3484 case MONO_TYPE_CHAR:
3486 case MONO_TYPE_I2: {
3487 guint16 *val = g_malloc (sizeof (guint16));
3492 #if SIZEOF_VOID_P == 4
3498 case MONO_TYPE_I4: {
3499 guint32 *val = g_malloc (sizeof (guint32));
3504 #if SIZEOF_VOID_P == 8
3505 case MONO_TYPE_U: /* error out instead? this should probably not happen */
3510 case MONO_TYPE_I8: {
3511 guint64 *val = g_malloc (sizeof (guint64));
3516 case MONO_TYPE_VALUETYPE:
3517 if (t->data.klass->enumtype) {
3518 type = t->data.klass->enum_basetype->type;
3521 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
3524 case MONO_TYPE_STRING:
3525 if (*p == (char)0xFF) {
3529 slen = mono_metadata_decode_value (p, &p);
3531 return mono_string_new_len (mono_domain_get (), p, slen);
3532 case MONO_TYPE_CLASS: {
3536 slen = mono_metadata_decode_value (p, &p);
3537 n = g_memdup (p, slen + 1);
3539 t = mono_reflection_type_from_name (n, image);
3541 g_warning ("Cannot load type '%s'", n);
3544 return mono_type_get_object (mono_domain_get (), t);
3546 case MONO_TYPE_OBJECT: {
3554 } else if (subt == 0x55) {
3557 slen = mono_metadata_decode_value (p, &p);
3558 n = g_memdup (p, slen + 1);
3560 t = mono_reflection_type_from_name (n, image);
3562 g_warning ("Cannot load type '%s'", n);
3565 subc = mono_class_from_mono_type (t);
3566 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
3567 MonoType simple_type = {{0}};
3568 simple_type.type = subt;
3569 subc = mono_class_from_mono_type (&simple_type);
3571 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
3573 val = load_cattr_value (image, &subc->byval_arg, p, end);
3574 obj = mono_object_new (mono_domain_get (), subc);
3575 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
3580 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
3586 * Optimization we could avoid mallocing() an little-endian archs that
3587 * don't crash with unaligned accesses.
3590 fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
3592 const char *p = mono_metadata_blob_heap (image, blobidx);
3594 len = mono_metadata_decode_value (p, &p);
3595 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
3600 for (i = 0; i < sig->param_count; ++i) {
3601 params [i] = load_cattr_value (image, sig->params [i], p, &p);
3607 type_is_reference (MonoType *type)
3609 switch (type->type) {
3610 case MONO_TYPE_BOOLEAN:
3611 case MONO_TYPE_CHAR:
3624 case MONO_TYPE_VALUETYPE:
3632 free_param_data (MonoMethodSignature *sig, void **params) {
3634 for (i = 0; i < sig->param_count; ++i) {
3635 if (!type_is_reference (sig->params [i]))
3636 g_free (params [i]);
3641 * Find the method index in the metadata methodDef table.
3642 * Later put these three helper methods in metadata and export them.
3645 find_method_index (MonoMethod *method) {
3646 MonoClass *klass = method->klass;
3649 for (i = 0; i < klass->method.count; ++i) {
3650 if (method == klass->methods [i])
3651 return klass->method.first + 1 + i;
3657 * Find the field index in the metadata FieldDef table.
3660 find_field_index (MonoClass *klass, MonoClassField *field) {
3663 for (i = 0; i < klass->field.count; ++i) {
3664 if (field == &klass->fields [i])
3665 return klass->field.first + 1 + i;
3671 * Find the property index in the metadata Property table.
3674 find_property_index (MonoClass *klass, MonoProperty *property) {
3677 for (i = 0; i < klass->property.count; ++i) {
3678 if (property == &klass->properties [i])
3679 return klass->property.first + 1 + i;
3685 * Find the event index in the metadata Event table.
3688 find_event_index (MonoClass *klass, MonoEvent *event) {
3691 for (i = 0; i < klass->event.count; ++i) {
3692 if (event == &klass->events [i])
3693 return klass->event.first + 1 + i;
3699 * mono_reflection_get_custom_attrs:
3700 * @obj: a reflection object handle
3702 * Return an array with all the custom attributes defined of the
3703 * reflection handle @obj. The objects are fully build.
3706 mono_reflection_get_custom_attrs (MonoObject *obj)
3708 guint32 idx, mtoken, i, len;
3709 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
3719 klass = obj->vtable->klass;
3720 /* FIXME: need to handle: Module */
3721 if (klass == mono_defaults.monotype_class) {
3722 MonoReflectionType *rtype = (MonoReflectionType*)obj;
3723 klass = mono_class_from_mono_type (rtype->type);
3724 idx = mono_metadata_token_index (klass->type_token);
3725 idx <<= CUSTOM_ATTR_BITS;
3726 idx |= CUSTOM_ATTR_TYPEDEF;
3727 image = klass->image;
3728 } else if (strcmp ("Assembly", klass->name) == 0) {
3729 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
3730 idx = 1; /* there is only one assembly */
3731 idx <<= CUSTOM_ATTR_BITS;
3732 idx |= CUSTOM_ATTR_ASSEMBLY;
3733 image = rassembly->assembly->image;
3734 } else if (strcmp ("MonoProperty", klass->name) == 0) {
3735 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
3736 idx = find_property_index (rprop->klass, rprop->property);
3737 idx <<= CUSTOM_ATTR_BITS;
3738 idx |= CUSTOM_ATTR_PROPERTY;
3739 image = rprop->klass->image;
3740 } else if (strcmp ("MonoEvent", klass->name) == 0) {
3741 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
3742 idx = find_event_index (revent->klass, revent->event);
3743 idx <<= CUSTOM_ATTR_BITS;
3744 idx |= CUSTOM_ATTR_EVENT;
3745 image = revent->klass->image;
3746 } else if (strcmp ("MonoField", klass->name) == 0) {
3747 MonoReflectionField *rfield = (MonoReflectionField*)obj;
3748 idx = find_field_index (rfield->klass, rfield->field);
3749 idx <<= CUSTOM_ATTR_BITS;
3750 idx |= CUSTOM_ATTR_FIELDDEF;
3751 image = rfield->klass->image;
3752 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
3753 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
3754 idx = find_method_index (rmethod->method);
3755 idx <<= CUSTOM_ATTR_BITS;
3756 idx |= CUSTOM_ATTR_METHODDEF;
3757 image = rmethod->method->klass->image;
3758 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
3759 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
3760 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
3761 guint32 method_index = find_method_index (rmethod->method);
3762 guint32 param_list, param_last, param_pos, found;
3764 image = rmethod->method->klass->image;
3765 ca = &image->tables [MONO_TABLE_METHOD];
3767 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
3768 if (method_index == ca->rows) {
3769 ca = &image->tables [MONO_TABLE_PARAM];
3770 param_last = ca->rows + 1;
3772 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
3773 ca = &image->tables [MONO_TABLE_PARAM];
3776 for (i = param_list; i < param_last; ++i) {
3777 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
3778 if (param_pos == param->PositionImpl) {
3784 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
3786 idx <<= CUSTOM_ATTR_BITS;
3787 idx |= CUSTOM_ATTR_PARAMDEF;
3788 } else { /* handle other types here... */
3789 g_error ("get custom attrs not yet supported for %s", klass->name);
3792 /* at this point image and index are set correctly for searching the custom attr */
3793 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3794 /* the table is not sorted */
3795 for (i = 0; i < ca->rows; ++i) {
3798 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
3799 if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
3801 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
3802 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
3803 case CUSTOM_ATTR_TYPE_METHODDEF:
3804 mtoken |= MONO_TOKEN_METHOD_DEF;
3806 case CUSTOM_ATTR_TYPE_MEMBERREF:
3807 mtoken |= MONO_TOKEN_MEMBER_REF;
3810 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
3813 method = mono_get_method (image, mtoken, NULL);
3815 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
3816 mono_class_init (method->klass);
3817 /*g_print ("got attr %s\n", method->klass->name);*/
3818 params = g_new (void*, method->signature->param_count);
3819 named = fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
3820 attr = mono_object_new (mono_domain_get (), method->klass);
3821 mono_runtime_invoke (method, attr, params, NULL);
3822 free_param_data (method->signature, params);
3824 num_named = read16 (named);
3826 for (j = 0; j < num_named; j++) {
3828 char *name, named_type;
3829 named_type = *named++;
3830 named++; /* type of data */
3831 name_len = mono_metadata_decode_blob_size (named, &named);
3832 name = g_malloc (name_len + 1);
3833 memcpy (name, named, name_len);
3834 name [name_len] = 0;
3836 if (named_type == 0x53) {
3837 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
3838 void *val = load_cattr_value (image, field->type, named, &named);
3839 mono_field_set_value (attr, field, val);
3840 if (!type_is_reference (field->type))
3842 } else if (named_type == 0x54) {
3843 MonoProperty *prop = mono_class_get_property_from_name (mono_object_class (attr), name);
3845 MonoType *prop_type;
3846 /* can we have more that 1 arg in a custom attr named property? */
3847 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
3848 pparams [0] = load_cattr_value (image, prop_type, named, &named);
3849 mono_property_set_value (prop, attr, pparams, NULL);
3850 if (!type_is_reference (prop_type))
3851 g_free (pparams [0]);
3855 list = g_list_prepend (list, attr);
3858 len = g_list_length (list);
3860 * The return type is really object[], but System/Attribute.cs does a cast
3861 * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
3862 * probably fix that.
3864 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
3865 result = mono_array_new (mono_domain_get (), klass, len);
3866 for (i = 0; i < len; ++i) {
3867 mono_array_set (result, gpointer, i, list->data);
3870 g_list_free (g_list_first (list));
3875 static MonoMethodSignature*
3876 parameters_to_signature (MonoArray *parameters) {
3877 MonoMethodSignature *sig;
3880 count = parameters? mono_array_length (parameters): 0;
3882 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
3883 sig->param_count = count;
3884 sig->sentinelpos = -1; /* FIXME */
3885 for (i = 0; i < count; ++i) {
3886 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
3887 sig->params [i] = pt->type;
3892 static MonoMethodSignature*
3893 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
3894 MonoMethodSignature *sig;
3896 sig = parameters_to_signature (ctor->parameters);
3897 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
3898 sig->ret = &mono_defaults.void_class->byval_arg;
3902 static MonoMethodSignature*
3903 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
3904 MonoMethodSignature *sig;
3906 sig = parameters_to_signature (method->parameters);
3907 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
3908 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
3913 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
3915 MonoClass *klass = mono_object_class (prop);
3916 if (strcmp (klass->name, "PropertyBuilder") == 0) {
3917 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
3918 *name = mono_string_to_utf8 (pb->name);
3919 *type = pb->type->type;
3921 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
3922 *name = g_strdup (p->property->name);
3923 if (p->property->get)
3924 *type = p->property->get->signature->ret;
3926 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
3931 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
3933 MonoClass *klass = mono_object_class (field);
3934 if (strcmp (klass->name, "FieldBuilder") == 0) {
3935 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
3936 *name = mono_string_to_utf8 (fb->name);
3937 *type = fb->type->type;
3939 MonoReflectionField *f = (MonoReflectionField *)field;
3940 *name = g_strdup (f->field->name);
3941 *type = f->field->type;
3946 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
3947 char *name, *result;
3951 name = mono_type_get_name (type);
3952 klass = my_mono_class_from_mono_type (type);
3953 ta = klass->image->assembly;
3954 if (ta == ass || klass->image == mono_defaults.corlib)
3957 /* missing public key */
3958 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
3959 name, ta->aname.name,
3960 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
3961 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
3967 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
3970 MonoTypeEnum simple_type;
3972 if ((p-buffer) + 10 >= *buflen) {
3975 newbuf = g_realloc (buffer, *buflen);
3976 p = newbuf + (p-buffer);
3979 argval = ((char*)arg + sizeof (MonoObject));
3980 simple_type = type->type;
3982 switch (simple_type) {
3983 case MONO_TYPE_BOOLEAN:
3988 case MONO_TYPE_CHAR:
3991 swap_with_size (p, argval, 2, 1);
3997 swap_with_size (p, argval, 4, 1);
4003 swap_with_size (p, argval, 8, 1);
4006 case MONO_TYPE_VALUETYPE:
4007 if (type->data.klass->enumtype) {
4008 simple_type = type->data.klass->enum_basetype->type;
4011 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
4014 case MONO_TYPE_STRING: {
4021 str = mono_string_to_utf8 ((MonoString*)arg);
4022 slen = strlen (str);
4023 if ((p-buffer) + 10 + slen >= *buflen) {
4027 newbuf = g_realloc (buffer, *buflen);
4028 p = newbuf + (p-buffer);
4031 mono_metadata_encode_value (slen, p, &p);
4032 memcpy (p, str, slen);
4037 case MONO_TYPE_CLASS: {
4040 MonoClass *k = mono_object_class (arg);
4041 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
4042 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
4043 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
4045 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
4046 slen = strlen (str);
4047 if ((p-buffer) + 10 + slen >= *buflen) {
4051 newbuf = g_realloc (buffer, *buflen);
4052 p = newbuf + (p-buffer);
4055 mono_metadata_encode_value (slen, p, &p);
4056 memcpy (p, str, slen);
4061 /* it may be a boxed value or a Type */
4062 case MONO_TYPE_OBJECT: {
4063 MonoClass *klass = mono_object_class (arg);
4067 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
4070 } else if (klass->enumtype) {
4072 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
4073 *p++ = simple_type = klass->byval_arg.type;
4076 g_error ("unhandled type in custom attr");
4078 str = type_get_qualified_name (klass->enum_basetype, NULL);
4079 slen = strlen (str);
4080 if ((p-buffer) + 10 + slen >= *buflen) {
4084 newbuf = g_realloc (buffer, *buflen);
4085 p = newbuf + (p-buffer);
4088 mono_metadata_encode_value (slen, p, &p);
4089 memcpy (p, str, slen);
4092 simple_type = klass->enum_basetype->type;
4096 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
4099 *retbuffer = buffer;
4103 * mono_reflection_get_custom_attrs_blob:
4104 * @ctor: custom attribute constructor
4105 * @ctorArgs: arguments o the constructor
4111 * Creates the blob of data that needs to be saved in the metadata and that represents
4112 * the custom attributed described by @ctor, @ctorArgs etc.
4113 * Returns: a Byte array representing the blob of data.
4116 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) {
4118 MonoMethodSignature *sig;
4123 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4124 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
4126 sig = ((MonoReflectionMethod*)ctor)->method->signature;
4129 p = buffer = g_malloc (buflen);
4130 /* write the prolog */
4133 for (i = 0; i < sig->param_count; ++i) {
4134 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
4135 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
4139 i += mono_array_length (properties);
4141 i += mono_array_length (fields);
4143 *p++ = (i >> 8) & 0xff;
4146 for (i = 0; i < mono_array_length (properties); ++i) {
4151 prop = mono_array_get (properties, gpointer, i);
4152 get_prop_name_and_type (prop, &pname, &ptype);
4153 *p++ = 0x54; /* PROPERTY signature */
4154 mono_metadata_encode_value (ptype->type, p, &p);
4155 len = strlen (pname);
4156 mono_metadata_encode_value (len, p, &p);
4157 memcpy (p, pname, len);
4159 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
4166 for (i = 0; i < mono_array_length (fields); ++i) {
4171 field = mono_array_get (fields, gpointer, i);
4172 get_field_name_and_type (field, &fname, &ftype);
4173 *p++ = 0x53; /* FIELD signature */
4174 mono_metadata_encode_value (ftype->type, p, &p);
4175 len = strlen (fname);
4176 mono_metadata_encode_value (len, p, &p);
4177 memcpy (p, fname, len);
4179 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
4184 g_assert (p - buffer <= buflen);
4185 buflen = p - buffer;
4186 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
4187 p = mono_array_addr (result, char, 0);
4188 memcpy (p, buffer, buflen);
4190 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
4196 * mono_reflection_setup_internal_class:
4197 * @tb: a TypeBuilder object
4199 * Creates a MonoClass that represents the TypeBuilder.
4200 * This is a trick that lets us simplify a lot of reflection code
4201 * (and will allow us to support Build and Run assemblies easier).
4204 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
4206 MonoClass *klass, *parent;
4208 klass = g_new0 (MonoClass, 1);
4210 klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
4213 /* check so we can compile corlib correctly */
4214 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
4215 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
4216 parent = tb->parent->type->data.klass;
4218 parent = my_mono_class_from_mono_type (tb->parent->type);
4222 klass->inited = 1; /* we lie to the runtime */
4223 klass->name = mono_string_to_utf8 (tb->name);
4224 klass->name_space = mono_string_to_utf8 (tb->nspace);
4225 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
4226 klass->flags = tb->attrs;
4228 klass->element_class = klass;
4229 klass->reflection_info = tb; /* need to pin. */
4232 mono_class_setup_parent (klass, parent);
4233 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
4234 const char *old_n = klass->name;
4235 /* trick to get relative numbering right when compiling corlib */
4236 klass->name = "BuildingObject";
4237 mono_class_setup_parent (klass, mono_defaults.object_class);
4238 klass->name = old_n;
4240 mono_class_setup_mono_type (klass);
4243 * FIXME: handle interfaces.
4246 tb->type.type = &klass->byval_arg;
4248 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
4252 * mono_reflection_create_internal_class:
4253 * @tb: a TypeBuilder object
4255 * Actually create the MonoClass that is associated with the TypeBuilder.
4258 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
4262 klass = my_mono_class_from_mono_type (tb->type.type);
4264 if (klass->enumtype && klass->enum_basetype == NULL) {
4265 MonoReflectionFieldBuilder *fb;
4267 g_assert (tb->fields != NULL);
4268 g_assert (mono_array_length (tb->fields) >= 1);
4270 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
4272 klass->enum_basetype = fb->type->type;
4273 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
4274 if (!klass->element_class)
4275 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
4276 klass->instance_size = klass->element_class->instance_size;
4277 klass->size_inited = 1;
4279 * this is almost safe to do with enums and it's needed to be able
4280 * to create objects of the enum type (for use in SetConstant).
4282 mono_class_setup_vtable (klass);
4287 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb) {
4289 MonoMethodNormal *pm;
4290 pm = g_new0 (MonoMethodNormal, 1);
4291 m = (MonoMethod*)pm;
4293 m->flags = mb->attrs;
4294 m->iflags = mb->iattrs;
4295 m->name = mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor";
4297 m->signature = ctor_builder_to_signature (mb);
4298 /* FIXME: create header */
4304 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb) {
4308 MonoMethodPInvoke *pm;
4309 pm = g_new0 (MonoMethodPInvoke, 1);
4310 m = (MonoMethod*)pm;
4312 MonoMethodNormal *pm;
4313 pm = g_new0 (MonoMethodNormal, 1);
4314 m = (MonoMethod*)pm;
4316 m->flags = mb->attrs;
4317 m->iflags = mb->iattrs;
4318 m->name = mono_string_to_utf8 (mb->name);
4320 m->signature = method_builder_to_signature (mb);
4321 /* FIXME: create header */
4327 ensure_runtime_vtable (MonoClass *klass)
4329 MonoReflectionTypeBuilder *tb = klass->reflection_info;
4332 if (!tb || klass->wastypebuilder)
4335 ensure_runtime_vtable (klass->parent);
4337 num = tb->ctors? mono_array_length (tb->ctors): 0;
4338 num += tb->methods? mono_array_length (tb->methods): 0;
4339 klass->method.count = num;
4340 klass->methods = g_new (MonoMethod*, num);
4341 num = tb->ctors? mono_array_length (tb->ctors): 0;
4342 for (i = 0; i < num; ++i)
4343 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
4344 num = tb->methods? mono_array_length (tb->methods): 0;
4346 for (i = 0; i < num; ++i)
4347 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
4349 klass->wastypebuilder = TRUE;
4350 if (tb->interfaces) {
4351 klass->interface_count = mono_array_length (tb->interfaces);
4352 klass->interfaces = g_new (MonoClass*, klass->interface_count);
4353 for (i = 0; i < klass->interface_count; ++i) {
4354 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
4355 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
4358 mono_class_setup_vtable (klass);
4362 typebuilder_setup_fields (MonoClass *klass)
4364 MonoReflectionTypeBuilder *tb = klass->reflection_info;
4365 MonoReflectionFieldBuilder *fb;
4366 MonoClassField *field;
4369 klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
4371 if (klass->field.count || klass->fields)
4374 klass->fields = g_new0 (MonoClassField, klass->field.count);
4376 for (i = 0; i < klass->field.count; ++i) {
4377 fb = mono_array_get (tb->fields, gpointer, i);
4378 field = &klass->fields [i];
4379 field->name = mono_string_to_utf8 (fb->name);
4381 /* FIXME: handle type modifiers */
4382 field->type = g_memdup (fb->type->type, sizeof (MonoType));
4383 field->type->attrs = fb->attrs;
4385 field->type = fb->type->type;
4387 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
4388 field->data = mono_array_addr (fb->rva_data, char, 0);
4389 if (fb->offset != -1)
4390 field->offset = fb->offset;
4392 mono_class_layout_fields (klass);
4396 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
4399 MonoReflectionType* res;
4401 klass = my_mono_class_from_mono_type (tb->type.type);
4404 * Fields to set in klass:
4405 * the various flags: delegate/unicode/contextbound etc.
4411 klass->flags = tb->attrs;
4412 klass->element_class = klass;
4414 /* enums are done right away */
4415 if (!klass->enumtype)
4416 ensure_runtime_vtable (klass);
4418 /* fields and object layout */
4419 if (klass->parent) {
4420 if (!klass->parent->size_inited)
4421 mono_class_init (klass->parent);
4422 klass->instance_size += klass->parent->instance_size;
4423 klass->class_size += klass->parent->class_size;
4424 klass->min_align = klass->parent->min_align;
4426 klass->instance_size = sizeof (MonoObject);
4427 klass->min_align = 1;
4429 /* FIXME: handle packing_size and instance_size */
4430 typebuilder_setup_fields (klass);
4432 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
4433 /* with enums res == tb: need to fix that. */
4434 if (!klass->enumtype)
4435 g_assert (res != tb);
4440 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
4442 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
4443 guint32 na = mono_array_length (sig->arguments);
4448 p = buf = g_malloc (10 + na * 10);
4450 mono_metadata_encode_value (0x07, p, &p);
4451 mono_metadata_encode_value (na, p, &p);
4452 for (i = 0; i < na; ++i) {
4453 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
4454 encode_reflection_type (assembly, type, p, &p);
4458 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
4459 p = mono_array_addr (result, char, 0);
4460 memcpy (p, buf, buflen);
4467 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
4469 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
4470 guint32 na = mono_array_length (sig->arguments);
4475 p = buf = g_malloc (10 + na * 10);
4477 mono_metadata_encode_value (0x06, p, &p);
4478 for (i = 0; i < na; ++i) {
4479 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
4480 encode_reflection_type (assembly, type, p, &p);
4484 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
4485 p = mono_array_addr (result, char, 0);
4486 memcpy (p, buf, buflen);