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);
1218 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
1219 * This is currently only a problem with references to System.Xml (see bug#27706),
1220 * but there may be other cases that makes this necessary. Note, we need to set
1221 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
1222 * recognized by ms, yuck!
1223 * FIXME: need to add more assembly names, as needed.
1225 if (strcmp (image->assembly_name, "corlib") == 0 ||
1226 strcmp (image->assembly_name, "mscorlib") == 0 ||
1227 strcmp (image->assembly_name, "System") == 0 ||
1228 strcmp (image->assembly_name, "System.Xml") == 0 ||
1229 strcmp (image->assembly_name, "System.Data") == 0 ||
1230 strcmp (image->assembly_name, "System.Drawing") == 0 ||
1231 strcmp (image->assembly_name, "System.Web") == 0) {
1232 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
1233 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1234 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1235 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1237 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1240 token <<= RESOLTION_SCOPE_BITS;
1241 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1242 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1247 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1249 MonoDynamicTable *table;
1255 char *b = blob_size;
1257 switch (type->type) {
1258 case MONO_TYPE_FNPTR:
1260 case MONO_TYPE_SZARRAY:
1261 case MONO_TYPE_ARRAY:
1262 encode_type (assembly, type, p, &p);
1268 g_assert (p-sig < 128);
1269 mono_metadata_encode_value (p-sig, b, &b);
1270 token = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1271 mono_image_add_stream_data (&assembly->blob, sig, p-sig);
1273 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1274 alloc_table (table, table->rows + 1);
1275 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1276 values [MONO_TYPESPEC_SIGNATURE] = token;
1278 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1279 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1285 * Despite the name, we handle also TypeSpec (with the above helper).
1288 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1290 MonoDynamicTable *table;
1292 guint32 token, scope, enclosing;
1295 #define COMPILE_CORLIB 0
1297 /* nasty hack, need to find the proper solution */
1298 if (type->type == MONO_TYPE_OBJECT)
1299 return TYPEDEFORREF_TYPEDEF | (2 << TYPEDEFORREF_BITS);
1301 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1304 token = create_typespec (assembly, type);
1307 klass = my_mono_class_from_mono_type (type);
1309 klass = mono_class_from_mono_type (type);
1311 * If it's in the same module:
1313 if (klass->image == assembly->assembly.image) {
1314 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1315 return TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1318 if (klass->nested_in) {
1319 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1320 /* get the typeref idx of the enclosing type */
1321 enclosing >>= TYPEDEFORREF_BITS;
1322 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1324 scope = resolution_scope_from_image (assembly, klass->image);
1326 table = &assembly->tables [MONO_TABLE_TYPEREF];
1327 alloc_table (table, table->rows + 1);
1328 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1329 values [MONO_TYPEREF_SCOPE] = scope;
1330 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1331 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1332 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1333 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1339 * Insert a memberef row into the metadata: the token that point to the memberref
1340 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1341 * mono_image_get_fieldref_token()).
1342 * The sig param is an index to an already built signature.
1345 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1347 MonoDynamicTable *table;
1349 guint32 token, pclass;
1352 parent = mono_image_typedef_or_ref (assembly, type);
1353 switch (parent & TYPEDEFORREF_MASK) {
1354 case TYPEDEFORREF_TYPEREF:
1355 pclass = MEMBERREF_PARENT_TYPEREF;
1357 case TYPEDEFORREF_TYPESPEC:
1358 pclass = MEMBERREF_PARENT_TYPESPEC;
1360 case TYPEDEFORREF_TYPEDEF:
1361 /* should never get here */
1363 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
1366 /* extract the index */
1367 parent >>= TYPEDEFORREF_BITS;
1369 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1370 alloc_table (table, table->rows + 1);
1371 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1372 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1373 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1374 values [MONO_MEMBERREF_SIGNATURE] = sig;
1375 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1382 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1386 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1389 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1390 method->name, method_encode_signature (assembly, method->signature));
1391 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1396 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1400 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1403 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
1404 field->name, fieldref_encode_signature (assembly, field));
1405 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1410 reflection_cc_to_file (int call_conv) {
1411 switch (call_conv & 0x3) {
1413 case 1: return MONO_CALL_DEFAULT;
1414 case 2: return MONO_CALL_VARARG;
1416 g_assert_not_reached ();
1423 MonoMethodSignature *sig;
1429 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1434 MonoMethodSignature *sig;
1437 name = mono_string_to_utf8 (m->name);
1438 nparams = mono_array_length (m->parameters);
1439 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1441 sig->call_convention = reflection_cc_to_file (m->call_conv);
1442 sig->param_count = nparams;
1443 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1444 for (i = 0; i < nparams; ++i) {
1445 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1446 sig->params [i] = t->type;
1449 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1451 if (strcmp (name, am->name) == 0 &&
1452 mono_metadata_type_equal (am->parent, m->parent->type) &&
1453 mono_metadata_signature_equal (am->sig, sig)) {
1459 am = g_new0 (ArrayMethod, 1);
1462 am->parent = m->parent->type;
1463 am->token = mono_image_get_memberref_token (assembly, am->parent,
1464 name, method_encode_signature (assembly, sig));
1465 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1466 m->table_idx = am->token & 0xffffff;
1471 * Insert into the metadata tables all the info about the TypeBuilder tb.
1472 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1475 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1477 MonoDynamicTable *table;
1479 int i, is_object = 0, is_system = 0;
1482 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1483 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1484 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1485 n = mono_string_to_utf8 (tb->name);
1486 if (strcmp (n, "Object") == 0)
1488 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1490 n = mono_string_to_utf8 (tb->nspace);
1491 if (strcmp (n, "System") == 0)
1493 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1495 if (tb->parent && !(is_system && is_object)) { /* interfaces don't have a parent */
1496 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1498 values [MONO_TYPEDEF_EXTENDS] = 0;
1499 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1500 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1503 * if we have explicitlayout or sequentiallayouts, output data in the
1504 * ClassLayout table.
1506 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1507 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1509 alloc_table (table, table->rows);
1510 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1511 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1512 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1513 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1516 /* handle interfaces */
1517 if (tb->interfaces) {
1518 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1520 table->rows += mono_array_length (tb->interfaces);
1521 alloc_table (table, table->rows);
1522 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1523 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1524 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1525 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1526 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1527 values += MONO_INTERFACEIMPL_SIZE;
1533 table = &assembly->tables [MONO_TABLE_FIELD];
1534 table->rows += mono_array_length (tb->fields);
1535 alloc_table (table, table->rows);
1536 for (i = 0; i < mono_array_length (tb->fields); ++i)
1537 mono_image_get_field_info (
1538 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1541 /* handle constructors */
1543 table = &assembly->tables [MONO_TABLE_METHOD];
1544 table->rows += mono_array_length (tb->ctors);
1545 alloc_table (table, table->rows);
1546 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1547 mono_image_get_ctor_info (domain,
1548 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1551 /* handle methods */
1553 table = &assembly->tables [MONO_TABLE_METHOD];
1554 table->rows += mono_array_length (tb->methods);
1555 alloc_table (table, table->rows);
1556 for (i = 0; i < mono_array_length (tb->methods); ++i)
1557 mono_image_get_method_info (
1558 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1561 /* Do the same with properties etc.. */
1562 if (tb->events && mono_array_length (tb->events)) {
1563 table = &assembly->tables [MONO_TABLE_EVENT];
1564 table->rows += mono_array_length (tb->events);
1565 alloc_table (table, table->rows);
1566 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1568 alloc_table (table, table->rows);
1569 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1570 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1571 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1572 for (i = 0; i < mono_array_length (tb->events); ++i)
1573 mono_image_get_event_info (
1574 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1576 if (tb->properties && mono_array_length (tb->properties)) {
1577 table = &assembly->tables [MONO_TABLE_PROPERTY];
1578 table->rows += mono_array_length (tb->properties);
1579 alloc_table (table, table->rows);
1580 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1582 alloc_table (table, table->rows);
1583 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1584 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1585 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1586 for (i = 0; i < mono_array_length (tb->properties); ++i)
1587 mono_image_get_property_info (
1588 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1591 MonoDynamicTable *ntable;
1593 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1594 table->rows += mono_array_length (tb->subtypes);
1595 alloc_table (table, table->rows);
1597 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1598 ntable->rows += mono_array_length (tb->subtypes);
1599 alloc_table (ntable, ntable->rows);
1600 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1602 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1603 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1605 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1606 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1607 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1608 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1609 mono_string_to_utf8 (tb->name), tb->table_idx,
1610 ntable->next_idx, ntable->rows);*/
1611 values += MONO_NESTED_CLASS_SIZE;
1614 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1615 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1617 mono_image_get_type_info (domain, subtype, assembly);
1623 assign_type_idx (MonoReflectionTypeBuilder *type, MonoDynamicTable *table)
1627 type->table_idx = table->next_idx ++;
1628 if (!type->subtypes)
1630 for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1631 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1632 assign_type_idx (subtype, table);
1637 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
1642 for (i = 0; i < mono_array_length (pinfo); ++i) {
1643 MonoReflectionParamBuilder *pb;
1644 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
1647 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
1652 type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
1655 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1657 for (i = 0; i < mono_array_length (tb->fields); ++i) {
1658 MonoReflectionFieldBuilder* fb;
1659 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
1660 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
1664 for (i = 0; i < mono_array_length (tb->events); ++i) {
1665 MonoReflectionEventBuilder* eb;
1666 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
1667 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1670 if (tb->properties) {
1671 for (i = 0; i < mono_array_length (tb->properties); ++i) {
1672 MonoReflectionPropertyBuilder* pb;
1673 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
1674 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
1678 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
1679 MonoReflectionCtorBuilder* cb;
1680 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
1681 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
1682 params_add_cattrs (assembly, cb->pinfo);
1687 for (i = 0; i < mono_array_length (tb->methods); ++i) {
1688 MonoReflectionMethodBuilder* mb;
1689 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
1690 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
1691 params_add_cattrs (assembly, mb->pinfo);
1696 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
1697 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
1702 module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
1705 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1707 for (i = 0; i < mono_array_length (mb->types); ++i)
1708 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
1712 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1714 MonoDynamicTable *table;
1718 table = &assembly->tables [MONO_TABLE_MODULE];
1719 mb->table_idx = table->next_idx ++;
1720 name = mono_string_to_utf8 (mb->module.name);
1721 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1723 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1726 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1727 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1728 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1731 * fill-in info in other tables as well.
1733 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1734 table->rows += mono_array_length (mb->types);
1735 alloc_table (table, table->rows);
1737 * We assign here the typedef indexes to avoid mismatches if a type that
1738 * has not yet been stored in the tables is referenced by another type.
1740 for (i = 0; i < mono_array_length (mb->types); ++i) {
1741 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1742 assign_type_idx (type, table);
1744 for (i = 0; i < mono_array_length (mb->types); ++i)
1745 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1748 #define align_pointer(base,p)\
1750 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1752 (p) += 4 - (__diff & 3);\
1756 compare_semantics (const void *a, const void *b)
1758 const guint32 *a_values = a;
1759 const guint32 *b_values = b;
1760 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
1763 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
1767 compare_custom_attrs (const void *a, const void *b)
1769 const guint32 *a_values = a;
1770 const guint32 *b_values = b;
1772 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
1776 compare_field_marshal (const void *a, const void *b)
1778 const guint32 *a_values = a;
1779 const guint32 *b_values = b;
1781 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
1785 compare_nested (const void *a, const void *b)
1787 const guint32 *a_values = a;
1788 const guint32 *b_values = b;
1790 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
1794 * build_compressed_metadata() fills in the blob of data that represents the
1795 * raw metadata as it will be saved in the PE file. The five streams are output
1796 * and the metadata tables are comnpressed from the guint32 array representation,
1797 * to the compressed on-disk format.
1800 build_compressed_metadata (MonoDynamicAssembly *assembly)
1802 MonoDynamicTable *table;
1804 guint64 valid_mask = 0;
1805 guint64 sorted_mask;
1806 guint32 heapt_size = 0;
1807 guint32 meta_size = 256; /* allow for header and other stuff */
1808 guint32 table_offset;
1809 guint32 ntables = 0;
1816 * We need to use the current ms version or the ms runtime it won't find
1817 * the support dlls. D'oh!
1818 * const char *version = "mono-" VERSION;
1820 const char *version = "v1.0.3705";
1823 MonoDynamicStream *stream;
1824 } stream_desc [] = {
1825 {"#~", &assembly->tstream},
1826 {"#Strings", &assembly->sheap},
1827 {"#US", &assembly->us},
1828 {"#Blob", &assembly->blob},
1829 {"#GUID", &assembly->guid}
1832 /* tables that are sorted */
1833 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
1834 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
1835 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
1836 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
1837 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
1838 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
1840 /* Compute table sizes */
1841 /* the MonoImage has already been created in mono_image_basic_init() */
1842 meta = assembly->assembly.image;
1844 /* Setup the info used by compute_sizes () */
1845 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1846 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1847 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1849 meta_size += assembly->blob.index;
1850 meta_size += assembly->guid.index;
1851 meta_size += assembly->sheap.index;
1852 meta_size += assembly->us.index;
1854 for (i=0; i < 64; ++i)
1855 meta->tables [i].rows = assembly->tables [i].rows;
1857 for (i = 0; i < 64; i++){
1858 if (meta->tables [i].rows == 0)
1860 valid_mask |= (guint64)1 << i;
1862 meta->tables [i].row_size = mono_metadata_compute_size (
1863 meta, i, &meta->tables [i].size_bitfield);
1864 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1866 heapt_size += 24; /* #~ header size */
1867 heapt_size += ntables * 4;
1868 meta_size += heapt_size;
1869 meta->raw_metadata = g_malloc0 (meta_size);
1870 p = meta->raw_metadata;
1871 /* the metadata signature */
1872 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1873 /* version numbers and 4 bytes reserved */
1874 int16val = (guint16*)p;
1875 *int16val++ = GUINT16_TO_LE (1);
1876 *int16val = GUINT16_TO_LE (1);
1878 /* version string */
1879 int32val = (guint32*)p;
1880 *int32val = GUINT32_TO_LE ((strlen (version) + 3) & (~3)); /* needs to be multiple of 4 */
1882 memcpy (p, version, GUINT32_FROM_LE (*int32val));
1883 p += GUINT32_FROM_LE (*int32val);
1884 align_pointer (meta->raw_metadata, p);
1885 int16val = (guint16*)p;
1886 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
1887 *int16val = GUINT16_TO_LE (5); /* number of streams */
1891 * write the stream info.
1893 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1894 table_offset += 3; table_offset &= ~3;
1896 assembly->tstream.index = heapt_size;
1897 for (i = 0; i < 5; ++i) {
1898 int32val = (guint32*)p;
1899 stream_desc [i].stream->offset = table_offset;
1900 *int32val++ = GUINT32_TO_LE (table_offset);
1901 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
1902 table_offset += GUINT32_FROM_LE (*int32val);
1903 table_offset += 3; table_offset &= ~3;
1905 strcpy (p, stream_desc [i].name);
1906 p += strlen (stream_desc [i].name) + 1;
1907 align_pointer (meta->raw_metadata, p);
1910 * now copy the data, the table stream header and contents goes first.
1912 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1913 p = meta->raw_metadata + assembly->tstream.offset;
1914 int32val = (guint32*)p;
1915 *int32val = GUINT32_TO_LE (0); /* reserved */
1917 *p++ = 1; /* version */
1919 if (meta->idx_string_wide)
1921 if (meta->idx_guid_wide)
1923 if (meta->idx_blob_wide)
1926 *p++ = 0; /* reserved */
1927 int64val = (guint64*)p;
1928 *int64val++ = GUINT64_TO_LE (valid_mask);
1929 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
1931 int32val = (guint32*)p;
1932 for (i = 0; i < 64; i++){
1933 if (meta->tables [i].rows == 0)
1935 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
1937 p = (unsigned char*)int32val;
1939 /* sort the tables that still need sorting */
1940 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1942 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
1943 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1945 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
1946 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1948 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
1949 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1951 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
1953 /* compress the tables */
1954 for (i = 0; i < 64; i++){
1957 guint32 bitfield = meta->tables [i].size_bitfield;
1958 if (!meta->tables [i].rows)
1960 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1961 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1962 meta->tables [i].base = p;
1963 for (row = 1; row <= meta->tables [i].rows; ++row) {
1964 values = assembly->tables [i].values + row * assembly->tables [i].columns;
1965 for (col = 0; col < assembly->tables [i].columns; ++col) {
1966 switch (mono_metadata_table_size (bitfield, col)) {
1968 *p++ = values [col];
1971 *p++ = values [col] & 0xff;
1972 *p++ = (values [col] >> 8) & 0xff;
1975 *p++ = values [col] & 0xff;
1976 *p++ = (values [col] >> 8) & 0xff;
1977 *p++ = (values [col] >> 16) & 0xff;
1978 *p++ = (values [col] >> 24) & 0xff;
1981 g_assert_not_reached ();
1985 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1988 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1989 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1990 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1991 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1992 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1994 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1998 * Some tables in metadata need to be sorted according to some criteria, but
1999 * when methods and fields are first created with reflection, they may be assigned a token
2000 * that doesn't correspond to the final token they will get assigned after the sorting.
2001 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
2002 * with the reflection objects that represent them. Once all the tables are set up, the
2003 * reflection objects will contains the correct table index. fixup_method() will fixup the
2004 * tokens for the method with ILGenerator @ilgen.
2007 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
2008 guint32 code_idx = GPOINTER_TO_UINT (value);
2009 MonoReflectionILTokenInfo *iltoken;
2010 MonoReflectionFieldBuilder *field;
2011 MonoReflectionCtorBuilder *ctor;
2012 MonoReflectionMethodBuilder *method;
2013 MonoReflectionTypeBuilder *tb;
2015 unsigned char *target;
2017 for (i = 0; i < ilgen->num_token_fixups; ++i) {
2018 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
2019 target = assembly->code.data + code_idx + iltoken->code_pos;
2020 switch (target [3]) {
2021 case MONO_TABLE_FIELD:
2022 if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
2023 g_assert_not_reached ();
2024 field = (MonoReflectionFieldBuilder *)iltoken->member;
2025 idx = field->table_idx;
2027 case MONO_TABLE_METHOD:
2028 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
2029 method = (MonoReflectionMethodBuilder *)iltoken->member;
2030 idx = method->table_idx;
2031 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
2032 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
2033 idx = ctor->table_idx;
2035 g_assert_not_reached ();
2038 case MONO_TABLE_TYPEDEF:
2039 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
2040 g_assert_not_reached ();
2041 tb = (MonoReflectionTypeBuilder *)iltoken->member;
2042 idx = tb->table_idx;
2045 g_error ("got unexpected table 0x%02x in fixup", target [3]);
2047 target [0] = idx & 0xff;
2048 target [1] = (idx >> 8) & 0xff;
2049 target [2] = (idx >> 16) & 0xff;
2054 assembly_add_resource (MonoDynamicAssembly *assembly, MonoReflectionResource *rsrc)
2056 MonoDynamicTable *table;
2060 char *b = blob_size;
2062 guint32 idx, offset;
2064 if (rsrc->filename) {
2065 name = mono_string_to_utf8 (rsrc->filename);
2066 sname = g_path_get_basename (name);
2068 table = &assembly->tables [MONO_TABLE_FILE];
2070 alloc_table (table, table->rows);
2071 values = table->values + table->next_idx * MONO_FILE_SIZE;
2072 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
2073 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
2076 mono_sha1_get_digest_from_file (name, hash);
2077 mono_metadata_encode_value (20, b, &b);
2078 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2079 mono_image_add_stream_data (&assembly->blob, hash, 20);
2081 idx = table->next_idx++;
2082 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
2086 offset = mono_array_length (rsrc->data);
2087 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
2088 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
2089 offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
2090 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
2094 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
2096 alloc_table (table, table->rows);
2097 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
2098 values [MONO_MANIFEST_OFFSET] = offset;
2099 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
2100 name = mono_string_to_utf8 (rsrc->name);
2101 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
2103 values [MONO_MANIFEST_IMPLEMENTATION] = idx;
2108 set_version_from_string (MonoString *version, guint32 *values)
2110 gchar *ver, *p, *str;
2113 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
2114 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
2115 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
2116 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
2119 ver = str = mono_string_to_utf8 (version);
2120 for (i = 0; i < 4; ++i) {
2121 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
2127 /* handle Revision and Build */
2137 load_public_key (MonoString *fname, MonoDynamicAssembly *assembly) {
2138 char *name, *content;
2144 name = mono_string_to_utf8 (fname);
2145 if (g_file_get_contents (name, &content, &len, NULL)) {
2147 char *b = blob_size;
2148 /* check it's a public key or keypair */
2149 mono_metadata_encode_value (len, b, &b);
2150 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
2151 mono_image_add_stream_data (&assembly->blob, content, len);
2153 /* need to get the actual value from the key type... */
2154 assembly->strong_name_size = 128;
2155 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
2157 /* FIXME: how do we tell mcs if loading fails? */
2163 * mono_image_build_metadata() will fill the info in all the needed metadata tables
2164 * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
2165 * and recursively outputs the info for a module. Each module will output all the info
2166 * about it's types etc.
2167 * At the end of the process, method and field tokens are fixed up and the on-disk
2168 * compressed metadata representation is created.
2171 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
2173 MonoDynamicTable *table;
2174 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
2175 MonoDomain *domain = mono_object_domain (assemblyb);
2181 assembly->text_rva = START_TEXT_RVA;
2183 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2184 alloc_table (table, 1);
2185 values = table->values + MONO_ASSEMBLY_SIZE;
2186 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2187 name = mono_string_to_utf8 (assemblyb->name);
2188 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
2190 if (assemblyb->culture) {
2191 name = mono_string_to_utf8 (assemblyb->culture);
2192 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
2195 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2197 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->keyfile, assembly);
2198 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2199 set_version_from_string (assemblyb->version, values);
2201 assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
2202 assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
2204 if (assemblyb->modules) {
2205 len = mono_array_length (assemblyb->modules);
2206 table = &assembly->tables [MONO_TABLE_MODULE];
2207 alloc_table (table, len);
2208 for (i = 0; i < len; ++i)
2209 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
2211 table = &assembly->tables [MONO_TABLE_MODULE];
2213 alloc_table (table, table->rows);
2214 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
2218 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2220 * table->rows is already set above and in mono_image_fill_module_table.
2222 alloc_table (table, table->rows);
2224 * Set the first entry.
2226 values = table->values + table->columns;
2227 values [MONO_TYPEDEF_FLAGS] = 0;
2228 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2229 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2230 values [MONO_TYPEDEF_EXTENDS] = 0;
2231 values [MONO_TYPEDEF_FIELD_LIST] = 1;
2232 values [MONO_TYPEDEF_METHOD_LIST] = 1;
2234 /* add all the custom attributes at the end, once all the indexes are stable */
2235 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
2237 if (assemblyb->modules) {
2238 len = mono_array_length (assemblyb->modules);
2239 for (i = 0; i < len; ++i)
2240 module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
2243 if (assemblyb->resources) {
2244 len = mono_array_length (assemblyb->resources);
2245 for (i = 0; i < len; ++i)
2246 assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
2250 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2252 build_compressed_metadata (assembly);
2256 * mono_image_insert_string:
2257 * @assembly: assembly builder object
2260 * Insert @str into the user string stream of @assembly.
2263 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
2269 if (!assembly->dynamic_assembly)
2270 mono_image_basic_init (assembly);
2271 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
2272 idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
2273 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2275 char *swapped = g_malloc (2 * mono_string_length (str));
2276 const char *p = (const char*)mono_string_chars (str);
2278 swap_with_size (swapped, p, 2, mono_string_length (str));
2279 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2283 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2285 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2286 return MONO_TOKEN_STRING | idx;
2290 * mono_image_create_token:
2291 * @assembly: a dynamic assembly
2294 * Get a token to insert in the IL code stream for the given MemberInfo.
2295 * @obj can be one of:
2296 * ConstructorBuilder
2306 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2312 g_error ("System.Array methods not yet supported");
2314 klass = obj->vtable->klass;
2315 if (strcmp (klass->name, "MethodBuilder") == 0) {
2316 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2317 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2318 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2321 if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2322 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2323 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2324 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2327 if (strcmp (klass->name, "FieldBuilder") == 0) {
2328 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2329 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
2331 if (strcmp (klass->name, "TypeBuilder") == 0) {
2332 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2333 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
2335 if (strcmp (klass->name, "MonoType") == 0) {
2336 MonoReflectionType *tb = (MonoReflectionType *)obj;
2337 return mono_metadata_token_from_dor (
2338 mono_image_typedef_or_ref (assembly, tb->type));
2340 if (strcmp (klass->name, "MonoCMethod") == 0 ||
2341 strcmp (klass->name, "MonoMethod") == 0) {
2342 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2343 token = mono_image_get_methodref_token (assembly, m->method);
2344 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2347 if (strcmp (klass->name, "MonoField") == 0) {
2348 MonoReflectionField *f = (MonoReflectionField *)obj;
2349 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2350 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2353 if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2354 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2355 token = mono_image_get_array_token (assembly, m);
2358 g_print ("requested token for %s\n", klass->name);
2363 guint32 import_lookup_table;
2367 guint32 import_address_table_rva;
2376 * mono_image_basic_ini:
2377 * @assembly: an assembly builder object
2379 * Create the MonoImage that represents the assembly builder and setup some
2380 * of the helper hash table and the basic metadata streams.
2383 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2385 static const guchar entrycode [16] = {0xff, 0x25, 0};
2386 MonoDynamicAssembly *assembly;
2390 if (assemblyb->dynamic_assembly)
2394 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
2396 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2399 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
2400 assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2401 assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2402 assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2404 string_heap_init (&assembly->sheap);
2405 mono_image_add_stream_data (&assembly->us, "", 1);
2406 mono_image_add_stream_data (&assembly->blob, "", 1);
2407 /* import tables... */
2408 mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2409 assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2410 assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2411 mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2412 assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2413 mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2414 assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2415 stream_data_align (&assembly->code);
2417 assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2419 for (i=0; i < 64; ++i) {
2420 assembly->tables [i].next_idx = 1;
2421 assembly->tables [i].columns = table_sizes [i];
2424 image = g_new0 (MonoImage, 1);
2426 /* keep in sync with image.c */
2427 assembly->assembly.aname.name = image->name = mono_string_to_utf8 (assemblyb->name);
2428 image->assembly_name = image->name; /* they may be different */
2430 image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2431 image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2432 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2433 image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2435 image->delegate_begin_invoke_cache =
2436 g_hash_table_new ((GHashFunc)mono_signature_hash,
2437 (GCompareFunc)mono_metadata_signature_equal);
2438 image->delegate_end_invoke_cache =
2439 g_hash_table_new ((GHashFunc)mono_signature_hash,
2440 (GCompareFunc)mono_metadata_signature_equal);
2441 image->delegate_invoke_cache =
2442 g_hash_table_new ((GHashFunc)mono_signature_hash,
2443 (GCompareFunc)mono_metadata_signature_equal);
2445 image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2446 image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2447 image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2448 image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2449 assembly->assembly.image = image;
2454 calc_section_size (MonoDynamicAssembly *assembly)
2458 /* alignment constraints */
2459 assembly->code.index += 3;
2460 assembly->code.index &= ~3;
2461 assembly->meta_size += 3;
2462 assembly->meta_size &= ~3;
2463 assembly->resources.index += 3;
2464 assembly->resources.index &= ~3;
2466 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2467 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2470 assembly->sections [MONO_SECTION_RELOC].size = 12;
2471 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2478 * mono_image_create_pefile:
2479 * @assemblyb: an assembly builder object
2481 * When we need to save an assembly, we first call this function that ensures the metadata
2482 * tables are built for all the modules in the assembly. This function creates the PE-COFF
2483 * header, the image sections, the CLI header etc. all the data is written in
2484 * assembly->pefile where it can be easily retrieved later in chunks.
2487 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
2488 MonoMSDOSHeader *msdos;
2489 MonoDotNetHeader *header;
2490 MonoSectionTable *section;
2491 MonoCLIHeader *cli_header;
2492 guint32 size, image_size, virtual_base, text_offset;
2493 guint32 header_start, section_start, file_offset, virtual_offset;
2494 MonoDynamicAssembly *assembly;
2495 MonoDynamicStream *pefile;
2497 guint32 *rva, value;
2500 static const unsigned char msheader[] = {
2501 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2502 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2505 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2506 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2507 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2508 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2511 mono_image_basic_init (assemblyb);
2512 assembly = assemblyb->dynamic_assembly;
2514 /* already created */
2515 if (assembly->pefile.index)
2518 mono_image_build_metadata (assemblyb);
2519 nsections = calc_section_size (assembly);
2521 pefile = &assembly->pefile;
2523 /* The DOS header and stub */
2524 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2525 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
2527 /* the dotnet header */
2528 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2530 /* the section tables */
2531 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2533 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2534 virtual_offset = VIRT_ALIGN;
2537 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2538 if (!assembly->sections [i].size)
2541 file_offset += FILE_ALIGN - 1;
2542 file_offset &= ~(FILE_ALIGN - 1);
2543 virtual_offset += VIRT_ALIGN - 1;
2544 virtual_offset &= ~(VIRT_ALIGN - 1);
2546 assembly->sections [i].offset = file_offset;
2547 assembly->sections [i].rva = virtual_offset;
2549 file_offset += assembly->sections [i].size;
2550 virtual_offset += assembly->sections [i].size;
2551 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2554 file_offset += FILE_ALIGN - 1;
2555 file_offset &= ~(FILE_ALIGN - 1);
2556 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
2558 image_size += section_start + sizeof (MonoSectionTable) * nsections;
2560 /* back-patch info */
2561 msdos = (MonoMSDOSHeader*)pefile->data;
2562 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
2563 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
2564 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2566 header = (MonoDotNetHeader*)(pefile->data + header_start);
2567 header->pesig [0] = 'P';
2568 header->pesig [1] = 'E';
2570 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
2571 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2572 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2573 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2574 if (assemblyb->pekind == 1) {
2576 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
2579 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2582 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2584 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2585 header->pe.pe_major = 6;
2586 header->pe.pe_minor = 0;
2587 size = assembly->sections [MONO_SECTION_TEXT].size;
2588 size += FILE_ALIGN - 1;
2589 size &= ~(FILE_ALIGN - 1);
2590 header->pe.pe_code_size = size;
2591 size = assembly->sections [MONO_SECTION_RSRC].size;
2592 size += FILE_ALIGN - 1;
2593 size &= ~(FILE_ALIGN - 1);
2594 header->pe.pe_data_size = size;
2595 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2596 header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
2597 header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
2598 /* pe_rva_entry_point always at the beginning of the text section */
2599 header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
2601 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2602 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2603 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2604 header->nt.pe_os_major = GUINT16_FROM_LE (4);
2605 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2606 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2607 size = section_start;
2608 size += FILE_ALIGN - 1;
2609 size &= ~(FILE_ALIGN - 1);
2610 header->nt.pe_header_size = GUINT32_FROM_LE (size);
2612 size += VIRT_ALIGN - 1;
2613 size &= ~(VIRT_ALIGN - 1);
2614 header->nt.pe_image_size = GUINT32_FROM_LE (size);
2617 // Translate the PEFileKind value to the value expected by the Windows loader
2620 short kind = assemblyb->pekind;
2623 // PEFileKinds.ConsoleApplication == 2
2624 // PEFileKinds.WindowApplication == 3
2627 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
2628 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
2634 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
2636 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2637 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2638 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2639 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2640 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2641 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2643 /* fill data directory entries */
2645 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2646 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2648 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2649 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2651 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2652 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2653 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2654 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2655 /* patch imported function RVA name */
2656 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2657 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2659 /* the import table */
2660 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2661 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2662 /* patch imported dll RVA name and other entries in the dir */
2663 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2664 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
2665 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2666 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2667 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2668 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2670 p = (assembly->code.data + assembly->ilt_offset);
2671 value = (assembly->text_rva + assembly->imp_names_offset - 2);
2672 *p++ = (value) & 0xff;
2673 *p++ = (value >> 8) & (0xff);
2674 *p++ = (value >> 16) & (0xff);
2675 *p++ = (value >> 24) & (0xff);
2677 /* the CLI header info */
2678 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2679 cli_header->ch_size = GUINT32_FROM_LE (72);
2680 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
2681 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
2682 if (assemblyb->entry_point)
2683 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
2685 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
2686 /* The embedded managed resources */
2687 text_offset = assembly->text_rva + assembly->code.index;
2688 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
2689 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
2690 text_offset += assembly->resources.index;
2691 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
2692 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
2693 text_offset += assembly->meta_size;
2694 if (assembly->strong_name_size) {
2695 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
2696 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
2697 text_offset += assembly->strong_name_size;
2700 /* write the section tables and section content */
2701 section = (MonoSectionTable*)(pefile->data + section_start);
2702 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2703 static const char *section_names [] = {
2704 ".text", ".rsrc", ".reloc"
2706 if (!assembly->sections [i].size)
2708 strcpy (section->st_name, section_names [i]);
2709 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
2710 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
2711 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
2712 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
2713 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
2714 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
2715 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
2717 case MONO_SECTION_TEXT:
2718 /* patch entry point */
2719 p = (assembly->code.data + 2);
2720 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
2721 *p++ = (value) & 0xff;
2722 *p++ = (value >> 8) & 0xff;
2723 *p++ = (value >> 16) & 0xff;
2724 *p++ = (value >> 24) & 0xff;
2726 text_offset = assembly->sections [i].offset;
2727 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
2728 text_offset += assembly->code.index;
2729 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
2730 text_offset += assembly->resources.index;
2731 memcpy (pefile->data + text_offset, assembly->assembly.image->raw_metadata, assembly->meta_size);
2732 text_offset += assembly->meta_size;
2733 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
2735 case MONO_SECTION_RELOC:
2736 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
2737 *rva = GUINT32_FROM_LE (assembly->text_rva);
2739 *rva = GUINT32_FROM_LE (12);
2741 data16 = (guint16*)rva;
2743 * the entrypoint is always at the start of the text section
2744 * 3 is IMAGE_REL_BASED_HIGHLOW
2745 * 2 is patch_size_rva - text_rva
2747 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
2749 *data16 = 0; /* terminate */
2751 case MONO_SECTION_RSRC:
2753 g_assert_not_reached ();
2758 /* check that the file is properly padded */
2761 FILE *f = fopen ("mypetest.exe", "w");
2762 fwrite (pefile->data, pefile->index, 1, f);
2769 * We need to return always the same object for MethodInfo, FieldInfo etc..
2770 * but we need to consider the reflected type.
2771 * type uses a different hash, since it uses custom hash/equal functions.
2776 MonoClass *refclass;
2780 reflected_equal (gconstpointer a, gconstpointer b) {
2781 const ReflectedEntry *ea = a;
2782 const ReflectedEntry *eb = b;
2784 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
2788 reflected_hash (gconstpointer a) {
2789 const ReflectedEntry *ea = a;
2790 return GPOINTER_TO_UINT (ea->item);
2793 #define CHECK_OBJECT(t,p,k) \
2799 mono_domain_lock (domain); \
2800 if (!domain->refobject_hash) \
2801 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
2802 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
2803 mono_domain_unlock (domain); \
2808 #define CACHE_OBJECT(p,o,k) \
2810 ReflectedEntry *e = mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry)); \
2812 e->refclass = (k); \
2813 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
2814 mono_domain_unlock (domain); \
2818 * mono_assembly_get_object:
2819 * @domain: an app domain
2820 * @assembly: an assembly
2822 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
2824 MonoReflectionAssembly*
2825 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
2827 static MonoClass *System_Reflection_Assembly;
2828 MonoReflectionAssembly *res;
2830 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
2831 if (!System_Reflection_Assembly)
2832 System_Reflection_Assembly = mono_class_from_name (
2833 mono_defaults.corlib, "System.Reflection", "Assembly");
2834 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
2835 res->assembly = assembly;
2836 CACHE_OBJECT (assembly, res, NULL);
2841 MonoReflectionModule*
2842 mono_module_get_object (MonoDomain *domain, MonoImage *image)
2844 static MonoClass *System_Reflection_Module;
2845 MonoReflectionModule *res;
2847 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
2848 if (!System_Reflection_Module)
2849 System_Reflection_Module = mono_class_from_name (
2850 mono_defaults.corlib, "System.Reflection", "Module");
2851 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
2854 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
2856 res->fqname = mono_string_new (domain, image->name);
2857 res->name = mono_string_new (domain, image->name);
2858 res->scopename = mono_string_new (domain, image->module_name);
2860 CACHE_OBJECT (image, res, NULL);
2866 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
2868 if ((t1->type != t2->type) ||
2869 (t1->byref != t2->byref))
2873 case MONO_TYPE_VOID:
2874 case MONO_TYPE_BOOLEAN:
2875 case MONO_TYPE_CHAR:
2886 case MONO_TYPE_STRING:
2889 case MONO_TYPE_OBJECT:
2891 case MONO_TYPE_VALUETYPE:
2892 case MONO_TYPE_CLASS:
2893 return t1->data.klass == t2->data.klass;
2895 case MONO_TYPE_SZARRAY:
2896 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
2897 case MONO_TYPE_ARRAY:
2898 if (t1->data.array->rank != t2->data.array->rank)
2900 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
2902 g_error ("implement type compare for %0x!", t1->type);
2910 mymono_metadata_type_hash (MonoType *t1)
2916 hash |= t1->byref << 6; /* do not collide with t1->type values */
2918 case MONO_TYPE_VALUETYPE:
2919 case MONO_TYPE_CLASS:
2920 /* check if the distribution is good enough */
2921 return hash << 7 | g_str_hash (t1->data.klass->name);
2923 case MONO_TYPE_SZARRAY:
2924 return hash << 7 | mymono_metadata_type_hash (t1->data.type);
2930 * mono_type_get_object:
2931 * @domain: an app domain
2934 * Return an System.MonoType object representing the type @type.
2937 mono_type_get_object (MonoDomain *domain, MonoType *type)
2939 MonoReflectionType *res;
2940 MonoClass *klass = mono_class_from_mono_type (type);
2942 mono_domain_lock (domain);
2943 if (!domain->type_hash)
2944 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
2945 (GCompareFunc)mymono_metadata_type_equal);
2946 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
2947 mono_domain_unlock (domain);
2950 if (klass->reflection_info && !klass->wastypebuilder) {
2951 //g_assert_not_reached ();
2952 /* should this be considered an error condition? */
2954 mono_domain_unlock (domain);
2955 return klass->reflection_info;
2958 mono_class_init (klass);
2959 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
2961 mono_g_hash_table_insert (domain->type_hash, type, res);
2962 mono_domain_unlock (domain);
2967 * mono_method_get_object:
2968 * @domain: an app domain
2970 * @refclass: the reflected type (can be NULL)
2972 * Return an System.Reflection.MonoMethod object representing the method @method.
2974 MonoReflectionMethod*
2975 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
2978 * We use the same C representation for methods and constructors, but the type
2979 * name in C# is different.
2983 MonoReflectionMethod *ret;
2986 refclass = method->klass;
2988 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
2989 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
2990 cname = "MonoCMethod";
2992 cname = "MonoMethod";
2993 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
2995 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
2996 ret->method = method;
2997 ret->name = mono_string_new (domain, method->name);
2998 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
2999 CACHE_OBJECT (method, ret, refclass);
3004 * mono_field_get_object:
3005 * @domain: an app domain
3009 * Return an System.Reflection.MonoField object representing the field @field
3012 MonoReflectionField*
3013 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
3015 MonoReflectionField *res;
3018 CHECK_OBJECT (MonoReflectionField *, field, klass);
3019 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
3020 res = (MonoReflectionField *)mono_object_new (domain, oklass);
3023 CACHE_OBJECT (field, res, klass);
3028 * mono_property_get_object:
3029 * @domain: an app domain
3031 * @property: a property
3033 * Return an System.Reflection.MonoProperty object representing the property @property
3036 MonoReflectionProperty*
3037 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
3039 MonoReflectionProperty *res;
3042 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
3043 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
3044 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
3046 res->property = property;
3047 CACHE_OBJECT (property, res, klass);
3052 * mono_event_get_object:
3053 * @domain: an app domain
3057 * Return an System.Reflection.MonoEvent object representing the event @event
3060 MonoReflectionEvent*
3061 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
3063 MonoReflectionEvent *res;
3066 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
3067 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
3068 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
3071 CACHE_OBJECT (event, res, klass);
3076 * mono_param_get_objects:
3077 * @domain: an app domain
3080 * Return an System.Reflection.ParameterInfo array object representing the parameters
3081 * in the method @method.
3083 MonoReflectionParameter**
3084 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
3086 MonoReflectionParameter **res;
3087 MonoReflectionMethod *member;
3092 if (!method->signature->param_count)
3095 member = mono_method_get_object (domain, method, NULL);
3096 names = g_new (char *, method->signature->param_count);
3097 mono_method_get_param_names (method, (const char **) names);
3099 /* Note: the cache is based on the address of the signature into the method
3100 * since we already cache MethodInfos with the method as keys.
3102 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature), NULL);
3103 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
3105 res = GC_MALLOC (sizeof (MonoReflectionParameter*) * method->signature->param_count);
3107 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
3109 for (i = 0; i < method->signature->param_count; ++i) {
3110 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
3111 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
3112 res [i]->DefaultValueImpl = NULL; /* FIXME */
3113 res [i]->MemberImpl = (MonoObject*)member;
3114 res [i]->NameImpl = mono_string_new (domain, names [i]);
3115 res [i]->PositionImpl = i + 1;
3116 res [i]->AttrsImpl = method->signature->params [i]->attrs;
3119 CACHE_OBJECT (&(method->signature), res, NULL);
3124 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
3128 memset (assembly, 0, sizeof (MonoAssemblyName));
3130 assembly->culture = "";
3132 while (*p && (isalnum (*p) || *p == '.'))
3135 while (*p == ' ' || *p == ',') {
3144 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
3146 assembly->major = strtoul (p, &s, 10);
3147 if (s == p || *s != '.')
3150 assembly->minor = strtoul (p, &s, 10);
3151 if (s == p || *s != '.')
3154 assembly->build = strtoul (p, &s, 10);
3155 if (s == p || *s != '.')
3158 assembly->revision = strtoul (p, &s, 10);
3161 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
3163 if (strncmp (p, "neutral", 7) == 0) {
3164 assembly->culture = "";
3167 assembly->culture = p;
3168 while (*p && *p != ',') {
3172 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
3175 while (*s && isxdigit (*s)) {
3179 assembly->hash_len = s - p;
3180 if (!(s-p) || ((s-p) & 1))
3182 assembly->hash_value = s = p;
3183 while (*s && isxdigit (*s)) {
3185 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3188 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3196 while (*p == ' ' || *p == ',') {
3210 * mono_reflection_parse_type:
3213 * Parse a type name as accepted by the GetType () method and output the info
3214 * extracted in the info structure.
3215 * the name param will be mangled, so, make a copy before passing it to this function.
3216 * The fields in info will be valid until the memory pointed to by name is valid.
3217 * Returns 0 on parse error.
3218 * See also mono_type_get_name () below.
3221 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
3223 char *start, *p, *w, *last_point, *startn;
3224 int in_modifiers = 0;
3225 int isbyref = 0, rank;
3227 start = p = w = name;
3229 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
3230 info->name = info->name_space = NULL;
3231 info->nested = NULL;
3232 info->modifiers = NULL;
3234 /* last_point separates the namespace from the name */
3240 *p = 0; /* NULL terminate the name */
3242 /* we have parsed the nesting namespace + name */
3244 info->nested = g_list_append (info->nested, startn);
3248 info->name_space = start;
3250 info->name = last_point + 1;
3252 info->name_space = (char *)"";
3277 info->nested = g_list_append (info->nested, startn);
3280 info->name_space = start;
3282 info->name = last_point + 1;
3284 info->name_space = (char *)"";
3291 if (isbyref) /* only one level allowed by the spec */
3294 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
3298 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
3309 else if (*p != '*') /* '*' means unknown lower bound */
3315 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
3327 return 0; /* missing assembly name */
3328 if (!assembly_name_to_aname (&info->assembly, p))
3334 if (info->assembly.name)
3337 *w = 0; /* terminate class name */
3338 if (!info->name || !*info->name)
3340 /* add other consistency checks */
3345 mono_type_get_name_recurse (MonoType *type, GString *str)
3349 switch (type->type) {
3350 case MONO_TYPE_ARRAY: {
3351 int i, rank = type->data.array->rank;
3353 mono_type_get_name_recurse (type->data.array->type, str);
3354 g_string_append_c (str, '[');
3355 for (i = 1; i < rank; i++)
3356 g_string_append_c (str, ',');
3357 g_string_append_c (str, ']');
3360 case MONO_TYPE_SZARRAY:
3361 mono_type_get_name_recurse (type->data.type, str);
3362 g_string_append (str, "[]");
3365 mono_type_get_name_recurse (type->data.type, str);
3366 g_string_append_c (str, '*');
3369 klass = mono_class_from_mono_type (type);
3370 if (klass->nested_in) {
3371 mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
3372 g_string_append_c (str, '+');
3374 if (*klass->name_space) {
3375 g_string_append (str, klass->name_space);
3376 g_string_append_c (str, '.');
3378 g_string_append (str, klass->name);
3384 * mono_type_get_name:
3387 * Returns the string representation for type as required by System.Reflection.
3388 * The inverse of mono_reflection_parse_type ().
3391 mono_type_get_name (MonoType *type)
3393 GString* result = g_string_new ("");
3394 mono_type_get_name_recurse (type, result);
3397 g_string_append_c (result, '&');
3399 return g_string_free (result, FALSE);
3403 * mono_reflection_get_type:
3404 * @image: a metadata context
3405 * @info: type description structure
3406 * @ignorecase: flag for case-insensitive string compares
3408 * Build a MonoType from the type description in @info.
3412 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3419 image = mono_defaults.corlib;
3422 klass = mono_class_from_name_case (image, info->name_space, info->name);
3424 klass = mono_class_from_name (image, info->name_space, info->name);
3427 for (mod = info->nested; mod; mod = mod->next) {
3430 mono_class_init (klass);
3431 nested = klass->nested_classes;
3434 klass = nested->data;
3436 if (g_strcasecmp (klass->name, mod->data) == 0)
3439 if (strcmp (klass->name, mod->data) == 0)
3443 nested = nested->next;
3450 mono_class_init (klass);
3451 for (mod = info->modifiers; mod; mod = mod->next) {
3452 modval = GPOINTER_TO_UINT (mod->data);
3453 if (!modval) { /* byref: must be last modifier */
3454 return &klass->this_arg;
3455 } else if (modval == -1) {
3456 klass = mono_ptr_class_get (&klass->byval_arg);
3457 } else { /* array rank */
3458 klass = mono_array_class_get (&klass->byval_arg, modval);
3460 mono_class_init (klass);
3462 return &klass->byval_arg;
3466 * mono_reflection_type_from_name:
3468 * @image: a metadata context (can be NULL).
3470 * Retrieves a MonoType from its @name. If the name is not fully qualified,
3471 * it defaults to get the type from @image or, if @image is NULL or loading
3472 * from it fails, uses corlib.
3476 mono_reflection_type_from_name (char *name, MonoImage *image)
3479 MonoTypeNameParse info;
3481 /*g_print ("requested type %s\n", str);*/
3482 if (!mono_reflection_parse_type (name, &info)) {
3483 g_list_free (info.modifiers);
3484 g_list_free (info.nested);
3488 if (info.assembly.name) {
3489 image = mono_image_loaded (info.assembly.name);
3490 /* do we need to load if it's not already loaded? */
3492 g_list_free (info.modifiers);
3493 g_list_free (info.nested);
3496 } else if (image == NULL) {
3497 image = mono_defaults.corlib;
3500 type = mono_reflection_get_type (image, &info, FALSE);
3501 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
3502 image = mono_defaults.corlib;
3503 type = mono_reflection_get_type (image, &info, FALSE);
3506 g_list_free (info.modifiers);
3507 g_list_free (info.nested);
3512 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
3514 int slen, type = t->type;
3519 case MONO_TYPE_BOOLEAN: {
3520 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
3525 case MONO_TYPE_CHAR:
3527 case MONO_TYPE_I2: {
3528 guint16 *val = g_malloc (sizeof (guint16));
3533 #if SIZEOF_VOID_P == 4
3539 case MONO_TYPE_I4: {
3540 guint32 *val = g_malloc (sizeof (guint32));
3545 #if SIZEOF_VOID_P == 8
3546 case MONO_TYPE_U: /* error out instead? this should probably not happen */
3551 case MONO_TYPE_I8: {
3552 guint64 *val = g_malloc (sizeof (guint64));
3557 case MONO_TYPE_VALUETYPE:
3558 if (t->data.klass->enumtype) {
3559 type = t->data.klass->enum_basetype->type;
3562 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
3565 case MONO_TYPE_STRING:
3566 if (*p == (char)0xFF) {
3570 slen = mono_metadata_decode_value (p, &p);
3572 return mono_string_new_len (mono_domain_get (), p, slen);
3573 case MONO_TYPE_CLASS: {
3577 slen = mono_metadata_decode_value (p, &p);
3578 n = g_memdup (p, slen + 1);
3580 t = mono_reflection_type_from_name (n, image);
3582 g_warning ("Cannot load type '%s'", n);
3585 return mono_type_get_object (mono_domain_get (), t);
3587 case MONO_TYPE_OBJECT: {
3595 } else if (subt == 0x55) {
3598 slen = mono_metadata_decode_value (p, &p);
3599 n = g_memdup (p, slen + 1);
3601 t = mono_reflection_type_from_name (n, image);
3603 g_warning ("Cannot load type '%s'", n);
3606 subc = mono_class_from_mono_type (t);
3607 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
3608 MonoType simple_type = {{0}};
3609 simple_type.type = subt;
3610 subc = mono_class_from_mono_type (&simple_type);
3612 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
3614 val = load_cattr_value (image, &subc->byval_arg, p, end);
3615 obj = mono_object_new (mono_domain_get (), subc);
3616 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
3621 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
3627 * Optimization we could avoid mallocing() an little-endian archs that
3628 * don't crash with unaligned accesses.
3631 fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
3633 const char *p = mono_metadata_blob_heap (image, blobidx);
3635 len = mono_metadata_decode_value (p, &p);
3636 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
3641 for (i = 0; i < sig->param_count; ++i) {
3642 params [i] = load_cattr_value (image, sig->params [i], p, &p);
3648 type_is_reference (MonoType *type)
3650 switch (type->type) {
3651 case MONO_TYPE_BOOLEAN:
3652 case MONO_TYPE_CHAR:
3665 case MONO_TYPE_VALUETYPE:
3673 free_param_data (MonoMethodSignature *sig, void **params) {
3675 for (i = 0; i < sig->param_count; ++i) {
3676 if (!type_is_reference (sig->params [i]))
3677 g_free (params [i]);
3682 * Find the method index in the metadata methodDef table.
3683 * Later put these three helper methods in metadata and export them.
3686 find_method_index (MonoMethod *method) {
3687 MonoClass *klass = method->klass;
3690 for (i = 0; i < klass->method.count; ++i) {
3691 if (method == klass->methods [i])
3692 return klass->method.first + 1 + i;
3698 * Find the field index in the metadata FieldDef table.
3701 find_field_index (MonoClass *klass, MonoClassField *field) {
3704 for (i = 0; i < klass->field.count; ++i) {
3705 if (field == &klass->fields [i])
3706 return klass->field.first + 1 + i;
3712 * Find the property index in the metadata Property table.
3715 find_property_index (MonoClass *klass, MonoProperty *property) {
3718 for (i = 0; i < klass->property.count; ++i) {
3719 if (property == &klass->properties [i])
3720 return klass->property.first + 1 + i;
3726 * Find the event index in the metadata Event table.
3729 find_event_index (MonoClass *klass, MonoEvent *event) {
3732 for (i = 0; i < klass->event.count; ++i) {
3733 if (event == &klass->events [i])
3734 return klass->event.first + 1 + i;
3740 * mono_reflection_get_custom_attrs:
3741 * @obj: a reflection object handle
3743 * Return an array with all the custom attributes defined of the
3744 * reflection handle @obj. The objects are fully build.
3747 mono_reflection_get_custom_attrs (MonoObject *obj)
3749 guint32 idx, mtoken, i, len;
3750 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
3760 klass = obj->vtable->klass;
3761 /* FIXME: need to handle: Module */
3762 if (klass == mono_defaults.monotype_class) {
3763 MonoReflectionType *rtype = (MonoReflectionType*)obj;
3764 klass = mono_class_from_mono_type (rtype->type);
3765 idx = mono_metadata_token_index (klass->type_token);
3766 idx <<= CUSTOM_ATTR_BITS;
3767 idx |= CUSTOM_ATTR_TYPEDEF;
3768 image = klass->image;
3769 } else if (strcmp ("Assembly", klass->name) == 0) {
3770 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
3771 idx = 1; /* there is only one assembly */
3772 idx <<= CUSTOM_ATTR_BITS;
3773 idx |= CUSTOM_ATTR_ASSEMBLY;
3774 image = rassembly->assembly->image;
3775 } else if (strcmp ("MonoProperty", klass->name) == 0) {
3776 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
3777 idx = find_property_index (rprop->klass, rprop->property);
3778 idx <<= CUSTOM_ATTR_BITS;
3779 idx |= CUSTOM_ATTR_PROPERTY;
3780 image = rprop->klass->image;
3781 } else if (strcmp ("MonoEvent", klass->name) == 0) {
3782 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
3783 idx = find_event_index (revent->klass, revent->event);
3784 idx <<= CUSTOM_ATTR_BITS;
3785 idx |= CUSTOM_ATTR_EVENT;
3786 image = revent->klass->image;
3787 } else if (strcmp ("MonoField", klass->name) == 0) {
3788 MonoReflectionField *rfield = (MonoReflectionField*)obj;
3789 idx = find_field_index (rfield->klass, rfield->field);
3790 idx <<= CUSTOM_ATTR_BITS;
3791 idx |= CUSTOM_ATTR_FIELDDEF;
3792 image = rfield->klass->image;
3793 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
3794 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
3795 idx = find_method_index (rmethod->method);
3796 idx <<= CUSTOM_ATTR_BITS;
3797 idx |= CUSTOM_ATTR_METHODDEF;
3798 image = rmethod->method->klass->image;
3799 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
3800 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
3801 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
3802 guint32 method_index = find_method_index (rmethod->method);
3803 guint32 param_list, param_last, param_pos, found;
3805 image = rmethod->method->klass->image;
3806 ca = &image->tables [MONO_TABLE_METHOD];
3808 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
3809 if (method_index == ca->rows) {
3810 ca = &image->tables [MONO_TABLE_PARAM];
3811 param_last = ca->rows + 1;
3813 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
3814 ca = &image->tables [MONO_TABLE_PARAM];
3817 for (i = param_list; i < param_last; ++i) {
3818 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
3819 if (param_pos == param->PositionImpl) {
3825 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
3827 idx <<= CUSTOM_ATTR_BITS;
3828 idx |= CUSTOM_ATTR_PARAMDEF;
3829 } else { /* handle other types here... */
3830 g_error ("get custom attrs not yet supported for %s", klass->name);
3833 /* at this point image and index are set correctly for searching the custom attr */
3834 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3835 /* the table is not sorted */
3836 for (i = 0; i < ca->rows; ++i) {
3839 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
3840 if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
3842 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
3843 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
3844 case CUSTOM_ATTR_TYPE_METHODDEF:
3845 mtoken |= MONO_TOKEN_METHOD_DEF;
3847 case CUSTOM_ATTR_TYPE_MEMBERREF:
3848 mtoken |= MONO_TOKEN_MEMBER_REF;
3851 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
3854 method = mono_get_method (image, mtoken, NULL);
3856 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
3857 mono_class_init (method->klass);
3858 /*g_print ("got attr %s\n", method->klass->name);*/
3859 params = g_new (void*, method->signature->param_count);
3860 named = fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
3861 attr = mono_object_new (mono_domain_get (), method->klass);
3862 mono_runtime_invoke (method, attr, params, NULL);
3863 free_param_data (method->signature, params);
3865 num_named = read16 (named);
3867 for (j = 0; j < num_named; j++) {
3869 char *name, named_type;
3870 named_type = *named++;
3871 named++; /* type of data */
3872 name_len = mono_metadata_decode_blob_size (named, &named);
3873 name = g_malloc (name_len + 1);
3874 memcpy (name, named, name_len);
3875 name [name_len] = 0;
3877 if (named_type == 0x53) {
3878 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
3879 void *val = load_cattr_value (image, field->type, named, &named);
3880 mono_field_set_value (attr, field, val);
3881 if (!type_is_reference (field->type))
3883 } else if (named_type == 0x54) {
3884 MonoProperty *prop = mono_class_get_property_from_name (mono_object_class (attr), name);
3886 MonoType *prop_type;
3887 /* can we have more that 1 arg in a custom attr named property? */
3888 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
3889 pparams [0] = load_cattr_value (image, prop_type, named, &named);
3890 mono_property_set_value (prop, attr, pparams, NULL);
3891 if (!type_is_reference (prop_type))
3892 g_free (pparams [0]);
3896 list = g_list_prepend (list, attr);
3899 len = g_list_length (list);
3901 * The return type is really object[], but System/Attribute.cs does a cast
3902 * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
3903 * probably fix that.
3905 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
3906 result = mono_array_new (mono_domain_get (), klass, len);
3907 for (i = 0; i < len; ++i) {
3908 mono_array_set (result, gpointer, i, list->data);
3911 g_list_free (g_list_first (list));
3916 static MonoMethodSignature*
3917 parameters_to_signature (MonoArray *parameters) {
3918 MonoMethodSignature *sig;
3921 count = parameters? mono_array_length (parameters): 0;
3923 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
3924 sig->param_count = count;
3925 sig->sentinelpos = -1; /* FIXME */
3926 for (i = 0; i < count; ++i) {
3927 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
3928 sig->params [i] = pt->type;
3933 static MonoMethodSignature*
3934 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
3935 MonoMethodSignature *sig;
3937 sig = parameters_to_signature (ctor->parameters);
3938 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
3939 sig->ret = &mono_defaults.void_class->byval_arg;
3943 static MonoMethodSignature*
3944 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
3945 MonoMethodSignature *sig;
3947 sig = parameters_to_signature (method->parameters);
3948 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
3949 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
3954 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
3956 MonoClass *klass = mono_object_class (prop);
3957 if (strcmp (klass->name, "PropertyBuilder") == 0) {
3958 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
3959 *name = mono_string_to_utf8 (pb->name);
3960 *type = pb->type->type;
3962 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
3963 *name = g_strdup (p->property->name);
3964 if (p->property->get)
3965 *type = p->property->get->signature->ret;
3967 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
3972 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
3974 MonoClass *klass = mono_object_class (field);
3975 if (strcmp (klass->name, "FieldBuilder") == 0) {
3976 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
3977 *name = mono_string_to_utf8 (fb->name);
3978 *type = fb->type->type;
3980 MonoReflectionField *f = (MonoReflectionField *)field;
3981 *name = g_strdup (f->field->name);
3982 *type = f->field->type;
3987 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
3988 char *name, *result;
3992 name = mono_type_get_name (type);
3993 klass = my_mono_class_from_mono_type (type);
3994 ta = klass->image->assembly;
3995 if (ta == ass || klass->image == mono_defaults.corlib)
3998 /* missing public key */
3999 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
4000 name, ta->aname.name,
4001 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
4002 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
4008 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
4011 MonoTypeEnum simple_type;
4013 if ((p-buffer) + 10 >= *buflen) {
4016 newbuf = g_realloc (buffer, *buflen);
4017 p = newbuf + (p-buffer);
4020 argval = ((char*)arg + sizeof (MonoObject));
4021 simple_type = type->type;
4023 switch (simple_type) {
4024 case MONO_TYPE_BOOLEAN:
4029 case MONO_TYPE_CHAR:
4032 swap_with_size (p, argval, 2, 1);
4038 swap_with_size (p, argval, 4, 1);
4044 swap_with_size (p, argval, 8, 1);
4047 case MONO_TYPE_VALUETYPE:
4048 if (type->data.klass->enumtype) {
4049 simple_type = type->data.klass->enum_basetype->type;
4052 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
4055 case MONO_TYPE_STRING: {
4062 str = mono_string_to_utf8 ((MonoString*)arg);
4063 slen = strlen (str);
4064 if ((p-buffer) + 10 + slen >= *buflen) {
4068 newbuf = g_realloc (buffer, *buflen);
4069 p = newbuf + (p-buffer);
4072 mono_metadata_encode_value (slen, p, &p);
4073 memcpy (p, str, slen);
4078 case MONO_TYPE_CLASS: {
4081 MonoClass *k = mono_object_class (arg);
4082 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
4083 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
4084 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
4086 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
4087 slen = strlen (str);
4088 if ((p-buffer) + 10 + slen >= *buflen) {
4092 newbuf = g_realloc (buffer, *buflen);
4093 p = newbuf + (p-buffer);
4096 mono_metadata_encode_value (slen, p, &p);
4097 memcpy (p, str, slen);
4102 /* it may be a boxed value or a Type */
4103 case MONO_TYPE_OBJECT: {
4104 MonoClass *klass = mono_object_class (arg);
4108 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
4111 } else if (klass->enumtype) {
4113 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
4114 *p++ = simple_type = klass->byval_arg.type;
4117 g_error ("unhandled type in custom attr");
4119 str = type_get_qualified_name (klass->enum_basetype, NULL);
4120 slen = strlen (str);
4121 if ((p-buffer) + 10 + slen >= *buflen) {
4125 newbuf = g_realloc (buffer, *buflen);
4126 p = newbuf + (p-buffer);
4129 mono_metadata_encode_value (slen, p, &p);
4130 memcpy (p, str, slen);
4133 simple_type = klass->enum_basetype->type;
4137 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
4140 *retbuffer = buffer;
4144 * mono_reflection_get_custom_attrs_blob:
4145 * @ctor: custom attribute constructor
4146 * @ctorArgs: arguments o the constructor
4152 * Creates the blob of data that needs to be saved in the metadata and that represents
4153 * the custom attributed described by @ctor, @ctorArgs etc.
4154 * Returns: a Byte array representing the blob of data.
4157 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) {
4159 MonoMethodSignature *sig;
4164 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4165 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
4167 sig = ((MonoReflectionMethod*)ctor)->method->signature;
4170 p = buffer = g_malloc (buflen);
4171 /* write the prolog */
4174 for (i = 0; i < sig->param_count; ++i) {
4175 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
4176 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
4180 i += mono_array_length (properties);
4182 i += mono_array_length (fields);
4184 *p++ = (i >> 8) & 0xff;
4187 for (i = 0; i < mono_array_length (properties); ++i) {
4192 prop = mono_array_get (properties, gpointer, i);
4193 get_prop_name_and_type (prop, &pname, &ptype);
4194 *p++ = 0x54; /* PROPERTY signature */
4195 mono_metadata_encode_value (ptype->type, p, &p);
4196 len = strlen (pname);
4197 mono_metadata_encode_value (len, p, &p);
4198 memcpy (p, pname, len);
4200 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
4207 for (i = 0; i < mono_array_length (fields); ++i) {
4212 field = mono_array_get (fields, gpointer, i);
4213 get_field_name_and_type (field, &fname, &ftype);
4214 *p++ = 0x53; /* FIELD signature */
4215 mono_metadata_encode_value (ftype->type, p, &p);
4216 len = strlen (fname);
4217 mono_metadata_encode_value (len, p, &p);
4218 memcpy (p, fname, len);
4220 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
4225 g_assert (p - buffer <= buflen);
4226 buflen = p - buffer;
4227 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
4228 p = mono_array_addr (result, char, 0);
4229 memcpy (p, buffer, buflen);
4231 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
4237 * mono_reflection_setup_internal_class:
4238 * @tb: a TypeBuilder object
4240 * Creates a MonoClass that represents the TypeBuilder.
4241 * This is a trick that lets us simplify a lot of reflection code
4242 * (and will allow us to support Build and Run assemblies easier).
4245 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
4247 MonoClass *klass, *parent;
4249 klass = g_new0 (MonoClass, 1);
4251 klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
4254 /* check so we can compile corlib correctly */
4255 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
4256 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
4257 parent = tb->parent->type->data.klass;
4259 parent = my_mono_class_from_mono_type (tb->parent->type);
4263 klass->inited = 1; /* we lie to the runtime */
4264 klass->name = mono_string_to_utf8 (tb->name);
4265 klass->name_space = mono_string_to_utf8 (tb->nspace);
4266 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
4267 klass->flags = tb->attrs;
4269 klass->element_class = klass;
4270 klass->reflection_info = tb; /* need to pin. */
4273 mono_class_setup_parent (klass, parent);
4274 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
4275 const char *old_n = klass->name;
4276 /* trick to get relative numbering right when compiling corlib */
4277 klass->name = "BuildingObject";
4278 mono_class_setup_parent (klass, mono_defaults.object_class);
4279 klass->name = old_n;
4281 mono_class_setup_mono_type (klass);
4284 * FIXME: handle interfaces.
4287 tb->type.type = &klass->byval_arg;
4289 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
4293 * mono_reflection_create_internal_class:
4294 * @tb: a TypeBuilder object
4296 * Actually create the MonoClass that is associated with the TypeBuilder.
4299 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
4303 klass = my_mono_class_from_mono_type (tb->type.type);
4305 if (klass->enumtype && klass->enum_basetype == NULL) {
4306 MonoReflectionFieldBuilder *fb;
4308 g_assert (tb->fields != NULL);
4309 g_assert (mono_array_length (tb->fields) >= 1);
4311 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
4313 klass->enum_basetype = fb->type->type;
4314 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
4315 if (!klass->element_class)
4316 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
4317 klass->instance_size = klass->element_class->instance_size;
4318 klass->size_inited = 1;
4320 * this is almost safe to do with enums and it's needed to be able
4321 * to create objects of the enum type (for use in SetConstant).
4323 mono_class_setup_vtable (klass);
4328 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb) {
4330 MonoMethodNormal *pm;
4331 pm = g_new0 (MonoMethodNormal, 1);
4332 m = (MonoMethod*)pm;
4334 m->flags = mb->attrs;
4335 m->iflags = mb->iattrs;
4336 m->name = mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor";
4338 m->signature = ctor_builder_to_signature (mb);
4339 /* FIXME: create header */
4345 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb) {
4349 MonoMethodPInvoke *pm;
4350 pm = g_new0 (MonoMethodPInvoke, 1);
4351 m = (MonoMethod*)pm;
4353 MonoMethodNormal *pm;
4354 pm = g_new0 (MonoMethodNormal, 1);
4355 m = (MonoMethod*)pm;
4357 m->flags = mb->attrs;
4358 m->iflags = mb->iattrs;
4359 m->name = mono_string_to_utf8 (mb->name);
4361 m->signature = method_builder_to_signature (mb);
4362 /* FIXME: create header */
4368 ensure_runtime_vtable (MonoClass *klass)
4370 MonoReflectionTypeBuilder *tb = klass->reflection_info;
4373 if (!tb || klass->wastypebuilder)
4376 ensure_runtime_vtable (klass->parent);
4378 num = tb->ctors? mono_array_length (tb->ctors): 0;
4379 num += tb->methods? mono_array_length (tb->methods): 0;
4380 klass->method.count = num;
4381 klass->methods = g_new (MonoMethod*, num);
4382 num = tb->ctors? mono_array_length (tb->ctors): 0;
4383 for (i = 0; i < num; ++i)
4384 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
4385 num = tb->methods? mono_array_length (tb->methods): 0;
4387 for (i = 0; i < num; ++i)
4388 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
4390 klass->wastypebuilder = TRUE;
4391 if (tb->interfaces) {
4392 klass->interface_count = mono_array_length (tb->interfaces);
4393 klass->interfaces = g_new (MonoClass*, klass->interface_count);
4394 for (i = 0; i < klass->interface_count; ++i) {
4395 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
4396 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
4399 mono_class_setup_vtable (klass);
4403 typebuilder_setup_fields (MonoClass *klass)
4405 MonoReflectionTypeBuilder *tb = klass->reflection_info;
4406 MonoReflectionFieldBuilder *fb;
4407 MonoClassField *field;
4410 klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
4412 if (klass->field.count || klass->fields)
4415 klass->fields = g_new0 (MonoClassField, klass->field.count);
4417 for (i = 0; i < klass->field.count; ++i) {
4418 fb = mono_array_get (tb->fields, gpointer, i);
4419 field = &klass->fields [i];
4420 field->name = mono_string_to_utf8 (fb->name);
4422 /* FIXME: handle type modifiers */
4423 field->type = g_memdup (fb->type->type, sizeof (MonoType));
4424 field->type->attrs = fb->attrs;
4426 field->type = fb->type->type;
4428 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
4429 field->data = mono_array_addr (fb->rva_data, char, 0);
4430 if (fb->offset != -1)
4431 field->offset = fb->offset;
4433 mono_class_layout_fields (klass);
4437 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
4440 MonoReflectionType* res;
4442 klass = my_mono_class_from_mono_type (tb->type.type);
4445 * Fields to set in klass:
4446 * the various flags: delegate/unicode/contextbound etc.
4452 klass->flags = tb->attrs;
4453 klass->element_class = klass;
4455 /* enums are done right away */
4456 if (!klass->enumtype)
4457 ensure_runtime_vtable (klass);
4459 /* fields and object layout */
4460 if (klass->parent) {
4461 if (!klass->parent->size_inited)
4462 mono_class_init (klass->parent);
4463 klass->instance_size += klass->parent->instance_size;
4464 klass->class_size += klass->parent->class_size;
4465 klass->min_align = klass->parent->min_align;
4467 klass->instance_size = sizeof (MonoObject);
4468 klass->min_align = 1;
4470 /* FIXME: handle packing_size and instance_size */
4471 typebuilder_setup_fields (klass);
4473 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
4474 /* with enums res == tb: need to fix that. */
4475 if (!klass->enumtype)
4476 g_assert (res != tb);
4481 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
4483 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
4484 guint32 na = mono_array_length (sig->arguments);
4489 p = buf = g_malloc (10 + na * 10);
4491 mono_metadata_encode_value (0x07, p, &p);
4492 mono_metadata_encode_value (na, p, &p);
4493 for (i = 0; i < na; ++i) {
4494 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
4495 encode_reflection_type (assembly, type, p, &p);
4499 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
4500 p = mono_array_addr (result, char, 0);
4501 memcpy (p, buf, buflen);
4508 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
4510 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
4511 guint32 na = mono_array_length (sig->arguments);
4516 p = buf = g_malloc (10 + na * 10);
4518 mono_metadata_encode_value (0x06, p, &p);
4519 for (i = 0; i < na; ++i) {
4520 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
4521 encode_reflection_type (assembly, type, p, &p);
4525 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
4526 p = mono_array_addr (result, char, 0);
4527 memcpy (p, buf, buflen);