3 * reflection.c: Routines for creating an image at runtime.
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
12 #include "mono/utils/mono-digest.h"
13 #include "mono/metadata/reflection.h"
14 #include "mono/metadata/tabledefs.h"
15 #include "mono/metadata/tokentype.h"
16 #include "mono/metadata/appdomain.h"
17 #include "mono/metadata/opcodes.h"
18 #include "mono/metadata/assembly.h"
19 #include <mono/metadata/exception.h>
28 #include "rawbuffer.h"
29 #include "mono-endian.h"
31 #include <mono/os/gc_wrapper.h>
33 #define TEXT_OFFSET 512
34 #define CLI_H_SIZE 136
35 #define FILE_ALIGN 512
36 #define VIRT_ALIGN 8192
37 #define START_TEXT_RVA 0x00002000
40 MonoReflectionILGen *ilgen;
41 MonoReflectionType *rtype;
42 MonoArray *parameters;
47 guint32 *table_idx; /* note: it's a pointer */
51 MonoBoolean init_locals;
53 } ReflectionMethodBuilder;
55 const unsigned char table_sizes [64] = {
65 MONO_INTERFACEIMPL_SIZE,
66 MONO_MEMBERREF_SIZE, /* 0x0A */
68 MONO_CUSTOM_ATTR_SIZE,
69 MONO_FIELD_MARSHAL_SIZE,
70 MONO_DECL_SECURITY_SIZE,
71 MONO_CLASS_LAYOUT_SIZE,
72 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
73 MONO_STAND_ALONE_SIGNATURE_SIZE,
77 MONO_PROPERTY_MAP_SIZE,
80 MONO_METHOD_SEMA_SIZE,
82 MONO_MODULEREF_SIZE, /* 0x1A */
88 MONO_ASSEMBLY_SIZE, /* 0x20 */
89 MONO_ASSEMBLY_PROCESSOR_SIZE,
91 MONO_ASSEMBLYREF_SIZE,
92 MONO_ASSEMBLYREFPROC_SIZE,
93 MONO_ASSEMBLYREFOS_SIZE,
97 MONO_NESTED_CLASS_SIZE,
102 * These macros can be used to allocate long living atomic data so it won't be
103 * tracked by the garbage collector. We use libgc because it's apparently faster
107 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
108 #define FREE_ATOMIC(ptr)
109 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
111 #define ALLOC_ATOMIC(size) g_malloc (size)
112 #define FREE_ATOMIC(ptr) g_free (ptr)
113 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
116 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
117 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
118 static guint32 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper);
119 static guint32 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo);
120 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
123 alloc_table (MonoDynamicTable *table, guint nrows)
126 g_assert (table->columns);
127 if (nrows + 1 >= table->alloc_rows) {
128 while (nrows + 1 >= table->alloc_rows)
129 if (table->alloc_rows == 0)
130 table->alloc_rows = 16;
132 table->alloc_rows *= 2;
135 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
137 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
142 make_room_in_stream (MonoDynamicStream *stream, int size)
144 while (stream->alloc_size <= size) {
145 if (stream->alloc_size < 4096)
146 stream->alloc_size = 4096;
148 stream->alloc_size *= 2;
151 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
153 stream->data = ALLOC_ATOMIC (stream->alloc_size);
157 string_heap_insert (MonoDynamicStream *sh, const char *str)
161 gpointer oldkey, oldval;
163 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
164 return GPOINTER_TO_UINT (oldval);
166 len = strlen (str) + 1;
168 if (idx + len > sh->alloc_size)
169 make_room_in_stream (sh, idx + len);
172 * We strdup the string even if we already copy them in sh->data
173 * so that the string pointers in the hash remain valid even if
174 * we need to realloc sh->data. We may want to avoid that later.
176 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
177 memcpy (sh->data + idx, str, len);
183 string_heap_init (MonoDynamicStream *sh)
186 sh->alloc_size = 4096;
187 sh->data = ALLOC_ATOMIC (4096);
188 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
189 string_heap_insert (sh, "");
192 #if 0 /* never used */
194 string_heap_free (MonoDynamicStream *sh)
196 FREE_ATOMIC (sh->data);
197 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
198 g_hash_table_destroy (sh->hash);
203 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
206 if (stream->alloc_size < stream->index + len)
207 make_room_in_stream (stream, stream->index + len);
208 memcpy (stream->data + stream->index, data, len);
210 stream->index += len;
212 * align index? Not without adding an additional param that controls it since
213 * we may store a blob value in pieces.
219 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
222 if (stream->alloc_size < stream->index + len)
223 make_room_in_stream (stream, stream->index + len);
224 memset (stream->data + stream->index, 0, len);
226 stream->index += len;
231 stream_data_align (MonoDynamicStream *stream)
234 guint32 count = stream->index % 4;
236 /* we assume the stream data will be aligned */
238 mono_image_add_stream_data (stream, buf, 4 - count);
242 mono_blob_entry_hash (const char* str)
246 len = mono_metadata_decode_blob_size (str, &str);
250 for (str += 1; str < end; str++)
251 h = (h << 5) - h + *str;
259 mono_blob_entry_equal (const char *str1, const char *str2) {
263 len = mono_metadata_decode_blob_size (str1, &end1);
264 len2 = mono_metadata_decode_blob_size (str2, &end2);
267 return memcmp (end1, end2, len) == 0;
271 add_to_blob_cached (MonoDynamicAssembly *assembly, char *b1, int s1, char *b2, int s2)
275 gpointer oldkey, oldval;
277 copy = ALLOC_ATOMIC (s1+s2);
278 memcpy (copy, b1, s1);
279 memcpy (copy + s1, b2, s2);
280 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
282 idx = GPOINTER_TO_UINT (oldval);
284 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
285 mono_image_add_stream_data (&assembly->blob, b2, s2);
286 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
291 /* modified version needed to handle building corlib */
293 my_mono_class_from_mono_type (MonoType *type) {
294 switch (type->type) {
295 case MONO_TYPE_ARRAY:
297 case MONO_TYPE_SZARRAY:
298 return mono_class_from_mono_type (type);
300 /* should be always valid when we reach this case... */
301 return type->data.klass;
306 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
309 g_assert_not_reached ();
314 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
318 case MONO_TYPE_BOOLEAN:
332 case MONO_TYPE_STRING:
333 case MONO_TYPE_OBJECT:
334 case MONO_TYPE_TYPEDBYREF:
335 mono_metadata_encode_value (type->type, p, &p);
338 case MONO_TYPE_SZARRAY:
339 mono_metadata_encode_value (type->type, p, &p);
340 encode_type (assembly, type->data.type, p, &p);
342 case MONO_TYPE_VALUETYPE:
343 case MONO_TYPE_CLASS:
344 mono_metadata_encode_value (type->type, p, &p);
345 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
348 case MONO_TYPE_VALUETYPE:
349 case MONO_TYPE_CLASS: {
350 MonoClass *k = mono_class_from_mono_type (type);
351 mono_metadata_encode_value (type->type, p, &p);
352 /* ensure only non-byref gets passed to mono_image_typedef_or_ref() */
353 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
357 case MONO_TYPE_ARRAY:
358 mono_metadata_encode_value (type->type, p, &p);
359 encode_type (assembly, type->data.array->type, p, &p);
360 mono_metadata_encode_value (type->data.array->rank, p, &p);
361 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
362 mono_metadata_encode_value (0, p, &p);
365 g_error ("need to encode type %x", type->type);
371 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
374 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
378 encode_type (assembly, type->type, p, endbuf);
382 g_assert_not_reached ();
387 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
392 guint32 nparams = sig->param_count;
393 guint32 size = 10 + nparams * 10;
401 p = buf = g_malloc (size);
403 * FIXME: vararg, explicit_this, differenc call_conv values...
405 *p = sig->call_convention;
407 *p |= 0x20; /* hasthis */
409 mono_metadata_encode_value (nparams, p, &p);
410 encode_type (assembly, sig->ret, p, &p);
411 for (i = 0; i < nparams; ++i)
412 encode_type (assembly, sig->params [i], p, &p);
414 g_assert (p - buf < size);
415 mono_metadata_encode_value (p-buf, b, &b);
416 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
422 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
425 * FIXME: reuse code from method_encode_signature().
430 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
431 guint32 size = 10 + nparams * 10;
436 p = buf = g_malloc (size);
437 /* LAMESPEC: all the call conv spec is foobared */
438 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
439 if (mb->call_conv & 2)
440 *p |= 0x5; /* vararg */
441 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
442 *p |= 0x20; /* hasthis */
444 mono_metadata_encode_value (nparams, p, &p);
445 encode_reflection_type (assembly, mb->rtype, p, &p);
446 for (i = 0; i < nparams; ++i) {
447 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
448 encode_reflection_type (assembly, pt, p, &p);
451 g_assert (p - buf < size);
452 mono_metadata_encode_value (p-buf, b, &b);
453 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
459 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
461 MonoDynamicTable *table;
464 guint32 idx, sig_idx, size;
465 guint nl = mono_array_length (ilgen->locals);
472 p = buf = g_malloc (size);
473 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
474 idx = table->next_idx ++;
476 alloc_table (table, table->rows);
477 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
479 mono_metadata_encode_value (0x07, p, &p);
480 mono_metadata_encode_value (nl, p, &p);
481 for (i = 0; i < nl; ++i) {
482 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
483 encode_reflection_type (assembly, lb->type, p, &p);
485 g_assert (p - buf < size);
486 mono_metadata_encode_value (p-buf, b, &b);
487 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
490 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
496 method_count_clauses (MonoReflectionILGen *ilgen)
498 guint32 num_clauses = 0;
501 MonoILExceptionInfo *ex_info;
502 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
503 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
504 if (ex_info->handlers)
505 num_clauses += mono_array_length (ex_info->handlers);
513 static MonoExceptionClause*
514 method_encode_clauses (MonoDynamicAssembly *assembly,
515 MonoReflectionILGen *ilgen, guint32 num_clauses)
517 MonoExceptionClause *clauses;
518 MonoExceptionClause *clause;
519 MonoILExceptionInfo *ex_info;
520 MonoILExceptionBlock *ex_block;
521 guint32 finally_start;
522 int i, j, clause_index;;
524 clauses = g_new0 (MonoExceptionClause, num_clauses);
527 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
528 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
529 finally_start = ex_info->start + ex_info->len;
530 g_assert (ex_info->handlers);
531 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
532 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
533 clause = &(clauses [clause_index]);
535 clause->flags = ex_block->type;
536 clause->try_offset = ex_info->start;
538 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
539 clause->try_len = finally_start - ex_info->start;
541 clause->try_len = ex_info->len;
542 clause->handler_offset = ex_block->start;
543 clause->handler_len = ex_block->len;
544 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
545 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
546 if (ex_block->extype) {
547 mono_g_hash_table_insert (assembly->tokens,
548 GUINT_TO_POINTER (clause->token_or_filter),
551 finally_start = ex_block->start + ex_block->len;
561 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
567 gint32 num_locals = 0;
568 gint32 num_exception = 0;
571 char fat_header [12];
574 guint32 local_sig = 0;
575 guint32 header_size = 12;
578 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
579 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
580 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
581 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
585 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
587 code = mb->ilgen->code;
588 code_size = mb->ilgen->code_len;
589 max_stack = mb->ilgen->max_stack;
590 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
591 if (mb->ilgen->ex_handlers)
592 num_exception = method_count_clauses (mb->ilgen);
596 mono_raise_exception (mono_get_exception_argument (NULL, "a method does not have any IL associated"));
598 code_size = mono_array_length (code);
599 max_stack = 8; /* we probably need to run a verifier on the code... */
602 /* check for exceptions, maxstack, locals */
603 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
605 if (code_size < 64 && !(code_size & 1)) {
606 flags = (code_size << 2) | 0x2;
607 } else if (code_size < 32 && (code_size & 1)) {
608 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
612 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
613 /* add to the fixup todo list */
614 if (mb->ilgen && mb->ilgen->num_token_fixups)
615 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
616 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
617 return assembly->text_rva + idx;
621 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
623 * FIXME: need to set also the header size in fat_flags.
624 * (and more sects and init locals flags)
628 fat_flags |= METHOD_HEADER_MORE_SECTS;
630 fat_flags |= METHOD_HEADER_INIT_LOCALS;
631 fat_header [0] = fat_flags;
632 fat_header [1] = (header_size / 4 ) << 4;
633 shortp = (guint16*)(fat_header + 2);
634 *shortp = GUINT16_TO_LE (max_stack);
635 intp = (guint32*)(fat_header + 4);
636 *intp = GUINT32_TO_LE (code_size);
637 intp = (guint32*)(fat_header + 8);
638 *intp = GUINT32_TO_LE (local_sig);
639 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
640 /* add to the fixup todo list */
641 if (mb->ilgen && mb->ilgen->num_token_fixups)
642 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
644 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
646 unsigned char sheader [4];
647 MonoExceptionClause clause;
648 MonoILExceptionInfo * ex_info;
649 MonoILExceptionBlock * ex_block;
652 stream_data_align (&assembly->code);
653 /* always use fat format for now */
654 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
655 num_exception *= sizeof (MonoExceptionClause);
656 num_exception += 4; /* include the size of the header */
657 sheader [1] = num_exception & 0xff;
658 sheader [2] = (num_exception >> 8) & 0xff;
659 sheader [3] = (num_exception >> 16) & 0xff;
660 mono_image_add_stream_data (&assembly->code, sheader, 4);
661 /* fat header, so we are already aligned */
663 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
664 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
665 if (ex_info->handlers) {
666 int finally_start = ex_info->start + ex_info->len;
667 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
668 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
669 clause.flags = GUINT32_TO_LE (ex_block->type);
670 clause.try_offset = GUINT32_TO_LE (ex_info->start);
671 /* need fault, too, probably */
672 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
673 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
675 clause.try_len = GUINT32_TO_LE (ex_info->len);
676 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
677 clause.handler_len = GUINT32_TO_LE (ex_block->len);
678 finally_start = ex_block->start + ex_block->len;
679 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
680 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
681 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
682 /*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",
683 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);*/
684 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
687 g_error ("No clauses for ex info block %d", i);
691 return assembly->text_rva + idx;
695 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 token)
698 MonoDynamicTable *table;
701 table = &assembly->tables [table_idx];
703 g_assert (col < table->columns);
705 values = table->values + table->columns;
706 for (i = 1; i <= table->rows; ++i) {
707 if (values [col] == token)
709 values += table->columns;
714 static GHashTable *dynamic_custom_attrs = NULL;
716 static MonoCustomAttrInfo*
717 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
720 MonoCustomAttrInfo *ainfo;
721 MonoReflectionCustomAttr *cattr;
725 /* FIXME: check in assembly the Run flag is set */
727 count = mono_array_length (cattrs);
729 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
731 ainfo->image = image;
732 ainfo->num_attrs = count;
733 for (i = 0; i < count; ++i) {
734 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
735 ainfo->attrs [i].ctor = cattr->ctor->method;
736 /* FIXME: might want to memdup the data here */
737 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
738 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
745 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
747 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
752 if (!dynamic_custom_attrs)
753 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
755 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
759 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
761 /* they are cached, so we don't free them */
762 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
768 * idx is the table index of the object
769 * type is one of CUSTOM_ATTR_*
772 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
774 MonoDynamicTable *table;
775 MonoReflectionCustomAttr *cattr;
777 guint32 count, i, token;
781 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
784 count = mono_array_length (cattrs);
785 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
786 table->rows += count;
787 alloc_table (table, table->rows);
788 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
789 idx <<= CUSTOM_ATTR_BITS;
791 for (i = 0; i < count; ++i) {
792 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
793 values [MONO_CUSTOM_ATTR_PARENT] = idx;
794 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
795 type = mono_metadata_token_index (token);
796 type <<= CUSTOM_ATTR_TYPE_BITS;
797 switch (mono_metadata_token_table (token)) {
798 case MONO_TABLE_METHOD:
799 type |= CUSTOM_ATTR_TYPE_METHODDEF;
801 case MONO_TABLE_MEMBERREF:
802 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
805 g_warning ("got wrong token in custom attr");
808 values [MONO_CUSTOM_ATTR_TYPE] = type;
810 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
811 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
812 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
813 values += MONO_CUSTOM_ATTR_SIZE;
819 * Fill in the MethodDef and ParamDef tables for a method.
820 * This is used for both normal methods and constructors.
823 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
825 MonoDynamicTable *table;
830 /* room in this table is already allocated */
831 table = &assembly->tables [MONO_TABLE_METHOD];
832 *mb->table_idx = table->next_idx ++;
833 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
834 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
836 name = mono_string_to_utf8 (mb->name);
837 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
839 } else { /* a constructor */
840 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
841 // MS.NET adds this automatically
842 mb->attrs |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
844 values [MONO_METHOD_FLAGS] = mb->attrs;
845 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
846 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
847 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
849 table = &assembly->tables [MONO_TABLE_PARAM];
850 values [MONO_METHOD_PARAMLIST] = table->next_idx;
853 MonoDynamicTable *mtable;
856 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
857 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
860 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
861 if (mono_array_get (mb->pinfo, gpointer, i))
864 table->rows += count;
865 alloc_table (table, table->rows);
866 values = table->values + table->next_idx * MONO_PARAM_SIZE;
867 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
868 MonoReflectionParamBuilder *pb;
869 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
870 values [MONO_PARAM_FLAGS] = pb->attrs;
871 values [MONO_PARAM_SEQUENCE] = i;
872 if (pb->name != NULL) {
873 name = mono_string_to_utf8 (pb->name);
874 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
878 values [MONO_PARAM_NAME] = 0;
879 values += MONO_PARAM_SIZE;
880 if (pb->marshal_info) {
882 alloc_table (mtable, mtable->rows);
883 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
884 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
885 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
887 pb->table_idx = table->next_idx++;
894 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
896 MonoDynamicTable *table;
899 ReflectionMethodBuilder rmb;
901 rmb.ilgen = mb->ilgen;
902 rmb.rtype = mb->rtype;
903 rmb.parameters = mb->parameters;
904 rmb.pinfo = mb->pinfo;
905 rmb.attrs = mb->attrs;
906 rmb.iattrs = mb->iattrs;
907 rmb.call_conv = mb->call_conv;
911 rmb.table_idx = &mb->table_idx;
912 rmb.init_locals = mb->init_locals;
913 rmb.mhandle = mb->mhandle;
915 mono_image_basic_method (&rmb, assembly);
917 if (mb->dll) { /* It's a P/Invoke method */
919 table = &assembly->tables [MONO_TABLE_IMPLMAP];
921 alloc_table (table, table->rows);
922 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
923 /* map CharSet values to on-disk values */
924 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (mb->charset ? (mb->charset - 1) * 2: 1);
925 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
926 name = mono_string_to_utf8 (mb->dllentry);
927 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
929 name = mono_string_to_utf8 (mb->dll);
930 moduleref = string_heap_insert (&assembly->sheap, name);
932 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
933 table = &assembly->tables [MONO_TABLE_MODULEREF];
935 alloc_table (table, table->rows);
936 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
937 values [MONO_IMPLMAP_SCOPE] = table->rows;
941 if (mb->override_method) {
942 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
944 table = &assembly->tables [MONO_TABLE_METHODIMPL];
946 alloc_table (table, table->rows);
947 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
948 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
949 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
950 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
951 switch (mono_metadata_token_table (tok)) {
952 case MONO_TABLE_MEMBERREF:
953 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
955 case MONO_TABLE_METHOD:
956 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
959 g_assert_not_reached ();
961 values [MONO_METHODIMPL_DECLARATION] = tok;
966 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
968 ReflectionMethodBuilder rmb;
970 rmb.ilgen = mb->ilgen;
971 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
972 rmb.parameters = mb->parameters;
973 rmb.pinfo = mb->pinfo;
974 rmb.attrs = mb->attrs;
975 rmb.iattrs = mb->iattrs;
976 rmb.call_conv = mb->call_conv;
980 rmb.table_idx = &mb->table_idx;
981 rmb.init_locals = mb->init_locals;
982 rmb.mhandle = mb->mhandle;
984 mono_image_basic_method (&rmb, assembly);
989 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
1000 p = buf = g_malloc (64);
1002 mono_metadata_encode_value (0x06, p, &p);
1003 /* encode custom attributes before the type */
1004 encode_type (assembly, field->type, p, &p);
1005 g_assert (p-buf < 64);
1006 mono_metadata_encode_value (p-buf, b, &b);
1007 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1013 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
1015 char blob_size [64];
1016 char *b = blob_size;
1021 p = buf = g_malloc (64);
1023 mono_metadata_encode_value (0x06, p, &p);
1024 /* encode custom attributes before the type */
1025 encode_reflection_type (assembly, fb->type, p, &p);
1026 g_assert (p-buf < 64);
1027 mono_metadata_encode_value (p-buf, b, &b);
1028 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1034 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
1035 * dest may be misaligned.
1038 swap_with_size (char *dest, const char* val, int len, int nelem) {
1039 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1042 for (elem = 0; elem < nelem; ++elem) {
1068 g_assert_not_reached ();
1074 memcpy (dest, val, len * nelem);
1079 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
1080 char blob_size [64];
1081 char *b = blob_size;
1084 guint32 idx, len, dummy = 0;
1086 p = buf = g_malloc (64);
1088 *ret_type = MONO_TYPE_CLASS;
1090 box_val = (char*)&dummy;
1092 box_val = ((char*)val) + sizeof (MonoObject);
1093 *ret_type = val->vtable->klass->byval_arg.type;
1096 switch (*ret_type) {
1097 case MONO_TYPE_BOOLEAN:
1102 case MONO_TYPE_CHAR:
1117 case MONO_TYPE_VALUETYPE:
1118 if (val->vtable->klass->enumtype) {
1119 *ret_type = val->vtable->klass->enum_basetype->type;
1122 g_error ("we can't encode valuetypes");
1123 case MONO_TYPE_CLASS:
1125 case MONO_TYPE_STRING: {
1126 MonoString *str = (MonoString*)val;
1127 /* there is no signature */
1128 len = str->length * 2;
1129 mono_metadata_encode_value (len, b, &b);
1130 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1132 char *swapped = g_malloc (2 * mono_string_length (str));
1133 const char *p = (const char*)mono_string_chars (str);
1135 swap_with_size (swapped, p, 2, mono_string_length (str));
1136 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1140 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1147 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1150 /* there is no signature */
1151 mono_metadata_encode_value (len, b, &b);
1152 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1153 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1154 swap_with_size (blob_size, box_val, len, 1);
1155 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1157 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1165 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo) {
1166 char blob_size [64];
1167 char *b = blob_size;
1168 char *p, *buf, *str;
1169 guint32 idx, len, bufsize = 256;
1171 p = buf = g_malloc (bufsize);
1173 switch (minfo->type) {
1174 case MONO_NATIVE_BYVALTSTR:
1175 case MONO_NATIVE_BYVALARRAY:
1176 mono_metadata_encode_value (minfo->type, p, &p);
1177 mono_metadata_encode_value (minfo->count, p, &p);
1179 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
1180 case MONO_NATIVE_CUSTOM:
1181 mono_metadata_encode_value (minfo->type, p, &p);
1183 str = mono_string_to_utf8 (minfo->guid);
1185 mono_metadata_encode_value (len, p, &p);
1186 memcpy (p, str, len);
1190 mono_metadata_encode_value (0, p, &p);
1192 if (minfo->marshaltype) {
1193 str = mono_string_to_utf8 (minfo->marshaltype);
1195 mono_metadata_encode_value (len, p, &p);
1196 if (p + len >= buf + bufsize) {
1199 buf = g_realloc (buf, bufsize);
1202 memcpy (p, str, len);
1206 mono_metadata_encode_value (0, p, &p);
1208 if (minfo->marshaltyperef) {
1209 str = type_get_qualified_name (minfo->marshaltyperef->type, &assembly->assembly);
1211 mono_metadata_encode_value (len, p, &p);
1212 if (p + len >= buf + bufsize) {
1215 buf = g_realloc (buf, bufsize);
1218 memcpy (p, str, len);
1222 mono_metadata_encode_value (0, p, &p);
1224 if (minfo->mcookie) {
1225 str = mono_string_to_utf8 (minfo->mcookie);
1227 mono_metadata_encode_value (len, p, &p);
1228 if (p + len >= buf + bufsize) {
1231 buf = g_realloc (buf, bufsize);
1234 memcpy (p, str, len);
1238 mono_metadata_encode_value (0, p, &p);
1242 mono_metadata_encode_value (minfo->type, p, &p);
1246 mono_metadata_encode_value (len, b, &b);
1247 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1253 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
1255 MonoDynamicTable *table;
1259 /* maybe this fixup should be done in the C# code */
1260 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1261 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1262 table = &assembly->tables [MONO_TABLE_FIELD];
1263 fb->table_idx = table->next_idx ++;
1264 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1265 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1266 name = mono_string_to_utf8 (fb->name);
1267 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1269 values [MONO_FIELD_FLAGS] = fb->attrs;
1270 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1272 if (fb->offset != -1) {
1273 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1275 alloc_table (table, table->rows);
1276 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1277 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1278 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1280 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1281 guint32 field_type = 0;
1282 table = &assembly->tables [MONO_TABLE_CONSTANT];
1284 alloc_table (table, table->rows);
1285 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1286 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1287 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1288 values [MONO_CONSTANT_TYPE] = field_type;
1289 values [MONO_CONSTANT_PADDING] = 0;
1293 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1295 alloc_table (table, table->rows);
1296 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1297 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1299 * We store it in the code section because it's simpler for now.
1301 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1302 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1304 if (fb->marshal_info) {
1305 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1307 alloc_table (table, table->rows);
1308 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1309 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1310 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1315 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
1319 char *b = blob_size;
1320 guint32 nparams = 0;
1321 MonoReflectionMethodBuilder *mb = fb->get_method;
1322 MonoReflectionMethodBuilder *smb = fb->set_method;
1323 guint32 idx, i, size;
1325 if (mb && mb->parameters)
1326 nparams = mono_array_length (mb->parameters);
1327 if (!mb && smb && smb->parameters)
1328 nparams = mono_array_length (smb->parameters) - 1;
1329 size = 24 + nparams * 10;
1330 buf = p = g_malloc (size);
1333 mono_metadata_encode_value (nparams, p, &p);
1335 encode_reflection_type (assembly, mb->rtype, p, &p);
1336 for (i = 0; i < nparams; ++i) {
1337 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1338 encode_reflection_type (assembly, pt, p, &p);
1341 /* the property type is the last param */
1342 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1343 for (i = 0; i < nparams; ++i) {
1344 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1345 encode_reflection_type (assembly, pt, p, &p);
1349 g_assert (p - buf < size);
1350 mono_metadata_encode_value (p-buf, b, &b);
1351 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1357 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
1359 MonoDynamicTable *table;
1362 guint num_methods = 0;
1366 * we need to set things in the following tables:
1367 * PROPERTYMAP (info already filled in _get_type_info ())
1368 * PROPERTY (rows already preallocated in _get_type_info ())
1369 * METHOD (method info already done with the generic method code)
1372 table = &assembly->tables [MONO_TABLE_PROPERTY];
1373 pb->table_idx = table->next_idx ++;
1374 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1375 name = mono_string_to_utf8 (pb->name);
1376 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1378 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1379 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1381 /* FIXME: we still don't handle 'other' methods */
1382 if (pb->get_method) num_methods ++;
1383 if (pb->set_method) num_methods ++;
1385 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1386 table->rows += num_methods;
1387 alloc_table (table, table->rows);
1389 if (pb->get_method) {
1390 semaidx = table->next_idx ++;
1391 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1392 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1393 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1394 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1396 if (pb->set_method) {
1397 semaidx = table->next_idx ++;
1398 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1399 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1400 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1401 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1406 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
1408 MonoDynamicTable *table;
1411 guint num_methods = 0;
1415 * we need to set things in the following tables:
1416 * EVENTMAP (info already filled in _get_type_info ())
1417 * EVENT (rows already preallocated in _get_type_info ())
1418 * METHOD (method info already done with the generic method code)
1421 table = &assembly->tables [MONO_TABLE_EVENT];
1422 eb->table_idx = table->next_idx ++;
1423 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1424 name = mono_string_to_utf8 (eb->name);
1425 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1427 values [MONO_EVENT_FLAGS] = eb->attrs;
1428 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1431 * FIXME: we still don't handle 'other' methods
1433 if (eb->add_method) num_methods ++;
1434 if (eb->remove_method) num_methods ++;
1435 if (eb->raise_method) num_methods ++;
1437 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1438 table->rows += num_methods;
1439 alloc_table (table, table->rows);
1441 if (eb->add_method) {
1442 semaidx = table->next_idx ++;
1443 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1444 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1445 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1446 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1448 if (eb->remove_method) {
1449 semaidx = table->next_idx ++;
1450 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1451 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1452 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1453 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1455 if (eb->raise_method) {
1456 semaidx = table->next_idx ++;
1457 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1458 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1459 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1460 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1465 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
1467 MonoDynamicTable *table;
1470 guint32 cols [MONO_ASSEMBLY_SIZE];
1474 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1477 if (image->assembly->dynamic)
1479 memset (cols, 0, sizeof (cols));
1481 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1483 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1484 token = table->next_idx ++;
1486 alloc_table (table, table->rows);
1487 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1488 if (strcmp ("corlib", image->assembly_name) == 0)
1489 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1491 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1492 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1493 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1494 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1495 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1496 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1497 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1498 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1500 if ((pubkey = mono_image_get_public_key (image, &publen))) {
1501 guchar pubtoken [9];
1503 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
1504 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
1507 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
1508 * This is currently only a problem with references to System.Xml (see bug#27706),
1509 * but there may be other cases that makes this necessary. Note, we need to set
1510 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
1511 * recognized by ms, yuck!
1512 * FIXME: need to add more assembly names, as needed.
1514 if (strcmp (image->assembly_name, "corlib") == 0 ||
1515 strcmp (image->assembly_name, "mscorlib") == 0 ||
1516 strcmp (image->assembly_name, "System") == 0 ||
1517 strcmp (image->assembly_name, "System.Xml") == 0 ||
1518 strcmp (image->assembly_name, "System.Data") == 0 ||
1519 strcmp (image->assembly_name, "System.Drawing") == 0 ||
1520 strcmp (image->assembly_name, "System.Web") == 0) {
1521 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
1522 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1523 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1524 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1526 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1529 token <<= RESOLTION_SCOPE_BITS;
1530 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1531 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1536 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1538 MonoDynamicTable *table;
1544 char *b = blob_size;
1546 switch (type->type) {
1547 case MONO_TYPE_FNPTR:
1549 case MONO_TYPE_SZARRAY:
1550 case MONO_TYPE_ARRAY:
1551 encode_type (assembly, type, p, &p);
1557 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1558 if (assembly->save) {
1559 g_assert (p-sig < 128);
1560 mono_metadata_encode_value (p-sig, b, &b);
1561 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
1562 alloc_table (table, table->rows + 1);
1563 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1564 values [MONO_TYPESPEC_SIGNATURE] = token;
1567 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1568 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1574 * Despite the name, we handle also TypeSpec (with the above helper).
1577 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1579 MonoDynamicTable *table;
1581 guint32 token, scope, enclosing;
1584 #define COMPILE_CORLIB 0
1586 /* nasty hack, need to find the proper solution */
1587 if (type->type == MONO_TYPE_OBJECT)
1588 return TYPEDEFORREF_TYPEDEF | (2 << TYPEDEFORREF_BITS);
1590 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1593 token = create_typespec (assembly, type);
1596 klass = my_mono_class_from_mono_type (type);
1598 klass = mono_class_from_mono_type (type);
1601 * If it's in the same module:
1603 if (klass->image == assembly->assembly.image) {
1604 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1605 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1606 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
1610 if (klass->nested_in) {
1611 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1612 /* get the typeref idx of the enclosing type */
1613 enclosing >>= TYPEDEFORREF_BITS;
1614 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1616 scope = resolution_scope_from_image (assembly, klass->image);
1618 table = &assembly->tables [MONO_TABLE_TYPEREF];
1619 if (assembly->save) {
1620 alloc_table (table, table->rows + 1);
1621 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1622 values [MONO_TYPEREF_SCOPE] = scope;
1623 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1624 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1626 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1627 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1629 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
1634 * Insert a memberef row into the metadata: the token that point to the memberref
1635 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1636 * mono_image_get_fieldref_token()).
1637 * The sig param is an index to an already built signature.
1640 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1642 MonoDynamicTable *table;
1644 guint32 token, pclass;
1647 parent = mono_image_typedef_or_ref (assembly, type);
1648 switch (parent & TYPEDEFORREF_MASK) {
1649 case TYPEDEFORREF_TYPEREF:
1650 pclass = MEMBERREF_PARENT_TYPEREF;
1652 case TYPEDEFORREF_TYPESPEC:
1653 pclass = MEMBERREF_PARENT_TYPESPEC;
1655 case TYPEDEFORREF_TYPEDEF:
1656 /* should never get here */
1658 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
1661 /* extract the index */
1662 parent >>= TYPEDEFORREF_BITS;
1664 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1666 if (assembly->save) {
1667 alloc_table (table, table->rows + 1);
1668 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1669 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1670 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1671 values [MONO_MEMBERREF_SIGNATURE] = sig;
1674 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1681 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1685 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1688 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1689 method->name, method_encode_signature (assembly, method->signature));
1690 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1695 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1699 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1702 field->parent = klass;
1703 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
1704 field->name, fieldref_encode_signature (assembly, field));
1705 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1710 mono_reflection_encode_sighelper (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1718 char *b = blob_size;
1720 if (!assembly->save)
1724 g_assert (helper->type == 2);
1726 if (helper->arguments)
1727 nargs = mono_array_length (helper->arguments);
1731 size = 10 + (nargs * 10);
1733 p = buf = g_malloc (size);
1735 /* Encode calling convention */
1736 /* Change Any to Standard */
1737 if ((helper->call_conv & 0x03) == 0x03)
1738 helper->call_conv = 0x01;
1739 /* explicit_this implies has_this */
1740 if (helper->call_conv & 0x40)
1741 helper->call_conv &= 0x20;
1743 if (helper->call_conv == 0) /* Unmanaged */
1744 *p = helper->unmanaged_call_conv - 1;
1747 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
1748 if (helper->call_conv & 0x02) /* varargs */
1753 mono_metadata_encode_value (nargs, p, &p);
1754 encode_reflection_type (assembly, helper->return_type, p, &p);
1755 for (i = 0; i < nargs; ++i) {
1756 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
1757 encode_reflection_type (assembly, pt, p, &p);
1760 g_assert (p - buf < size);
1761 mono_metadata_encode_value (p-buf, b, &b);
1762 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1769 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper)
1772 MonoDynamicTable *table;
1775 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1776 idx = table->next_idx ++;
1778 alloc_table (table, table->rows);
1779 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1781 values [MONO_STAND_ALONE_SIGNATURE] =
1782 mono_reflection_encode_sighelper (assembly, helper);
1788 reflection_cc_to_file (int call_conv) {
1789 switch (call_conv & 0x3) {
1791 case 1: return MONO_CALL_DEFAULT;
1792 case 2: return MONO_CALL_VARARG;
1794 g_assert_not_reached ();
1801 MonoMethodSignature *sig;
1807 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1812 MonoMethodSignature *sig;
1815 name = mono_string_to_utf8 (m->name);
1816 nparams = mono_array_length (m->parameters);
1817 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1819 sig->call_convention = reflection_cc_to_file (m->call_conv);
1820 sig->param_count = nparams;
1821 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1822 for (i = 0; i < nparams; ++i) {
1823 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1824 sig->params [i] = t->type;
1827 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1829 if (strcmp (name, am->name) == 0 &&
1830 mono_metadata_type_equal (am->parent, m->parent->type) &&
1831 mono_metadata_signature_equal (am->sig, sig)) {
1834 m->table_idx = am->token & 0xffffff;
1838 am = g_new0 (ArrayMethod, 1);
1841 am->parent = m->parent->type;
1842 am->token = mono_image_get_memberref_token (assembly, am->parent,
1843 name, method_encode_signature (assembly, sig));
1844 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1845 m->table_idx = am->token & 0xffffff;
1850 * Insert into the metadata tables all the info about the TypeBuilder tb.
1851 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1854 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1856 MonoDynamicTable *table;
1858 int i, is_object = 0, is_system = 0;
1861 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1862 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1863 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1864 n = mono_string_to_utf8 (tb->name);
1865 if (strcmp (n, "Object") == 0)
1867 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1869 n = mono_string_to_utf8 (tb->nspace);
1870 if (strcmp (n, "System") == 0)
1872 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1874 if (tb->parent && !(is_system && is_object) &&
1875 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
1876 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1878 values [MONO_TYPEDEF_EXTENDS] = 0;
1879 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1880 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1883 * if we have explicitlayout or sequentiallayouts, output data in the
1884 * ClassLayout table.
1886 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1887 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1889 alloc_table (table, table->rows);
1890 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1891 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1892 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1893 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1896 /* handle interfaces */
1897 if (tb->interfaces) {
1898 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1900 table->rows += mono_array_length (tb->interfaces);
1901 alloc_table (table, table->rows);
1902 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1903 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1904 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1905 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1906 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1907 values += MONO_INTERFACEIMPL_SIZE;
1913 table = &assembly->tables [MONO_TABLE_FIELD];
1914 table->rows += mono_array_length (tb->fields);
1915 alloc_table (table, table->rows);
1916 for (i = 0; i < mono_array_length (tb->fields); ++i)
1917 mono_image_get_field_info (
1918 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1921 /* handle constructors */
1923 table = &assembly->tables [MONO_TABLE_METHOD];
1924 table->rows += mono_array_length (tb->ctors);
1925 alloc_table (table, table->rows);
1926 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1927 mono_image_get_ctor_info (domain,
1928 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1931 /* handle methods */
1933 table = &assembly->tables [MONO_TABLE_METHOD];
1934 table->rows += mono_array_length (tb->methods);
1935 alloc_table (table, table->rows);
1936 for (i = 0; i < mono_array_length (tb->methods); ++i)
1937 mono_image_get_method_info (
1938 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1941 /* Do the same with properties etc.. */
1942 if (tb->events && mono_array_length (tb->events)) {
1943 table = &assembly->tables [MONO_TABLE_EVENT];
1944 table->rows += mono_array_length (tb->events);
1945 alloc_table (table, table->rows);
1946 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1948 alloc_table (table, table->rows);
1949 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1950 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1951 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1952 for (i = 0; i < mono_array_length (tb->events); ++i)
1953 mono_image_get_event_info (
1954 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1956 if (tb->properties && mono_array_length (tb->properties)) {
1957 table = &assembly->tables [MONO_TABLE_PROPERTY];
1958 table->rows += mono_array_length (tb->properties);
1959 alloc_table (table, table->rows);
1960 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1962 alloc_table (table, table->rows);
1963 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1964 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1965 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1966 for (i = 0; i < mono_array_length (tb->properties); ++i)
1967 mono_image_get_property_info (
1968 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1971 MonoDynamicTable *ntable;
1973 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1974 ntable->rows += mono_array_length (tb->subtypes);
1975 alloc_table (ntable, ntable->rows);
1976 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1978 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1979 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1981 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1982 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1983 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1984 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1985 mono_string_to_utf8 (tb->name), tb->table_idx,
1986 ntable->next_idx, ntable->rows);*/
1987 values += MONO_NESTED_CLASS_SIZE;
1994 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
1998 g_ptr_array_add (types, type);
2000 if (!type->subtypes)
2003 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2004 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2005 collect_types (types, subtype);
2010 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2011 MonoReflectionTypeBuilder **type2)
2013 if ((*type1)->table_idx < (*type2)->table_idx)
2016 if ((*type1)->table_idx > (*type2)->table_idx)
2023 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
2028 for (i = 0; i < mono_array_length (pinfo); ++i) {
2029 MonoReflectionParamBuilder *pb;
2030 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2033 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2038 type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
2041 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2043 for (i = 0; i < mono_array_length (tb->fields); ++i) {
2044 MonoReflectionFieldBuilder* fb;
2045 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2046 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2050 for (i = 0; i < mono_array_length (tb->events); ++i) {
2051 MonoReflectionEventBuilder* eb;
2052 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2053 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2056 if (tb->properties) {
2057 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2058 MonoReflectionPropertyBuilder* pb;
2059 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2060 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2064 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2065 MonoReflectionCtorBuilder* cb;
2066 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2067 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2068 params_add_cattrs (assembly, cb->pinfo);
2073 for (i = 0; i < mono_array_length (tb->methods); ++i) {
2074 MonoReflectionMethodBuilder* mb;
2075 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2076 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2077 params_add_cattrs (assembly, mb->pinfo);
2082 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2083 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2088 module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
2091 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2093 /* no types in the module */
2097 for (i = 0; i < mono_array_length (mb->types); ++i)
2098 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2102 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
2104 MonoDynamicTable *table;
2108 table = &assembly->tables [MONO_TABLE_MODULE];
2109 mb->table_idx = table->next_idx ++;
2110 name = mono_string_to_utf8 (mb->module.name);
2111 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2113 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2116 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2117 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2118 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2121 #define align_pointer(base,p)\
2123 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
2125 (p) += 4 - (__diff & 3);\
2129 compare_semantics (const void *a, const void *b)
2131 const guint32 *a_values = a;
2132 const guint32 *b_values = b;
2133 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
2136 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
2140 compare_custom_attrs (const void *a, const void *b)
2142 const guint32 *a_values = a;
2143 const guint32 *b_values = b;
2145 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
2149 compare_field_marshal (const void *a, const void *b)
2151 const guint32 *a_values = a;
2152 const guint32 *b_values = b;
2154 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
2158 compare_nested (const void *a, const void *b)
2160 const guint32 *a_values = a;
2161 const guint32 *b_values = b;
2163 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
2167 * build_compressed_metadata() fills in the blob of data that represents the
2168 * raw metadata as it will be saved in the PE file. The five streams are output
2169 * and the metadata tables are comnpressed from the guint32 array representation,
2170 * to the compressed on-disk format.
2173 build_compressed_metadata (MonoDynamicAssembly *assembly)
2175 MonoDynamicTable *table;
2177 guint64 valid_mask = 0;
2178 guint64 sorted_mask;
2179 guint32 heapt_size = 0;
2180 guint32 meta_size = 256; /* allow for header and other stuff */
2181 guint32 table_offset;
2182 guint32 ntables = 0;
2189 * We need to use the current ms version or the ms runtime it won't find
2190 * the support dlls. D'oh!
2191 * const char *version = "mono-" VERSION;
2193 const char *version = "v1.0.3705";
2196 MonoDynamicStream *stream;
2197 } stream_desc [] = {
2198 {"#~", &assembly->tstream},
2199 {"#Strings", &assembly->sheap},
2200 {"#US", &assembly->us},
2201 {"#Blob", &assembly->blob},
2202 {"#GUID", &assembly->guid}
2205 /* tables that are sorted */
2206 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
2207 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
2208 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
2209 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
2210 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
2211 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
2213 /* Compute table sizes */
2214 /* the MonoImage has already been created in mono_image_basic_init() */
2215 meta = assembly->assembly.image;
2217 /* Setup the info used by compute_sizes () */
2218 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
2219 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
2220 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
2222 meta_size += assembly->blob.index;
2223 meta_size += assembly->guid.index;
2224 meta_size += assembly->sheap.index;
2225 meta_size += assembly->us.index;
2227 for (i=0; i < 64; ++i)
2228 meta->tables [i].rows = assembly->tables [i].rows;
2230 for (i = 0; i < 64; i++){
2231 if (meta->tables [i].rows == 0)
2233 valid_mask |= (guint64)1 << i;
2235 meta->tables [i].row_size = mono_metadata_compute_size (
2236 meta, i, &meta->tables [i].size_bitfield);
2237 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
2239 heapt_size += 24; /* #~ header size */
2240 heapt_size += ntables * 4;
2241 meta_size += heapt_size;
2242 meta->raw_metadata = g_malloc0 (meta_size);
2243 p = meta->raw_metadata;
2244 /* the metadata signature */
2245 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
2246 /* version numbers and 4 bytes reserved */
2247 int16val = (guint16*)p;
2248 *int16val++ = GUINT16_TO_LE (1);
2249 *int16val = GUINT16_TO_LE (1);
2251 /* version string */
2252 int32val = (guint32*)p;
2253 *int32val = GUINT32_TO_LE ((strlen (version) + 3) & (~3)); /* needs to be multiple of 4 */
2255 memcpy (p, version, GUINT32_FROM_LE (*int32val));
2256 p += GUINT32_FROM_LE (*int32val);
2257 align_pointer (meta->raw_metadata, p);
2258 int16val = (guint16*)p;
2259 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
2260 *int16val = GUINT16_TO_LE (5); /* number of streams */
2264 * write the stream info.
2266 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
2267 table_offset += 3; table_offset &= ~3;
2269 assembly->tstream.index = heapt_size;
2270 for (i = 0; i < 5; ++i) {
2271 int32val = (guint32*)p;
2272 stream_desc [i].stream->offset = table_offset;
2273 *int32val++ = GUINT32_TO_LE (table_offset);
2274 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
2275 table_offset += GUINT32_FROM_LE (*int32val);
2276 table_offset += 3; table_offset &= ~3;
2278 strcpy (p, stream_desc [i].name);
2279 p += strlen (stream_desc [i].name) + 1;
2280 align_pointer (meta->raw_metadata, p);
2283 * now copy the data, the table stream header and contents goes first.
2285 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
2286 p = meta->raw_metadata + assembly->tstream.offset;
2287 int32val = (guint32*)p;
2288 *int32val = GUINT32_TO_LE (0); /* reserved */
2290 *p++ = 1; /* version */
2292 if (meta->idx_string_wide)
2294 if (meta->idx_guid_wide)
2296 if (meta->idx_blob_wide)
2299 *p++ = 0; /* reserved */
2300 int64val = (guint64*)p;
2301 *int64val++ = GUINT64_TO_LE (valid_mask);
2302 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
2304 int32val = (guint32*)p;
2305 for (i = 0; i < 64; i++){
2306 if (meta->tables [i].rows == 0)
2308 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
2310 p = (unsigned char*)int32val;
2312 /* sort the tables that still need sorting */
2313 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2315 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
2316 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2318 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
2319 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2321 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
2322 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2324 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
2326 /* compress the tables */
2327 for (i = 0; i < 64; i++){
2330 guint32 bitfield = meta->tables [i].size_bitfield;
2331 if (!meta->tables [i].rows)
2333 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
2334 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
2335 meta->tables [i].base = p;
2336 for (row = 1; row <= meta->tables [i].rows; ++row) {
2337 values = assembly->tables [i].values + row * assembly->tables [i].columns;
2338 for (col = 0; col < assembly->tables [i].columns; ++col) {
2339 switch (mono_metadata_table_size (bitfield, col)) {
2341 *p++ = values [col];
2344 *p++ = values [col] & 0xff;
2345 *p++ = (values [col] >> 8) & 0xff;
2348 *p++ = values [col] & 0xff;
2349 *p++ = (values [col] >> 8) & 0xff;
2350 *p++ = (values [col] >> 16) & 0xff;
2351 *p++ = (values [col] >> 24) & 0xff;
2354 g_assert_not_reached ();
2358 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
2361 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
2362 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
2363 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
2364 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
2365 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
2367 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
2371 * Some tables in metadata need to be sorted according to some criteria, but
2372 * when methods and fields are first created with reflection, they may be assigned a token
2373 * that doesn't correspond to the final token they will get assigned after the sorting.
2374 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
2375 * with the reflection objects that represent them. Once all the tables are set up, the
2376 * reflection objects will contains the correct table index. fixup_method() will fixup the
2377 * tokens for the method with ILGenerator @ilgen.
2380 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
2381 guint32 code_idx = GPOINTER_TO_UINT (value);
2382 MonoReflectionILTokenInfo *iltoken;
2383 MonoReflectionFieldBuilder *field;
2384 MonoReflectionCtorBuilder *ctor;
2385 MonoReflectionMethodBuilder *method;
2386 MonoReflectionTypeBuilder *tb;
2387 MonoReflectionArrayMethod *am;
2389 unsigned char *target;
2391 for (i = 0; i < ilgen->num_token_fixups; ++i) {
2392 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
2393 target = assembly->code.data + code_idx + iltoken->code_pos;
2394 switch (target [3]) {
2395 case MONO_TABLE_FIELD:
2396 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
2397 field = (MonoReflectionFieldBuilder *)iltoken->member;
2398 idx = field->table_idx;
2399 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
2400 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
2401 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
2403 g_assert_not_reached ();
2406 case MONO_TABLE_METHOD:
2407 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
2408 method = (MonoReflectionMethodBuilder *)iltoken->member;
2409 idx = method->table_idx;
2410 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
2411 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
2412 idx = ctor->table_idx;
2413 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
2414 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
2415 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
2417 g_assert_not_reached ();
2420 case MONO_TABLE_TYPEDEF:
2421 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
2422 g_assert_not_reached ();
2423 tb = (MonoReflectionTypeBuilder *)iltoken->member;
2424 idx = tb->table_idx;
2426 case MONO_TABLE_MEMBERREF:
2427 if (strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod"))
2428 g_assert_not_reached ();
2429 am = (MonoReflectionArrayMethod*)iltoken->member;
2430 idx = am->table_idx;
2433 g_error ("got unexpected table 0x%02x in fixup", target [3]);
2435 target [0] = idx & 0xff;
2436 target [1] = (idx >> 8) & 0xff;
2437 target [2] = (idx >> 16) & 0xff;
2442 assembly_add_resource (MonoDynamicAssembly *assembly, MonoReflectionResource *rsrc)
2444 MonoDynamicTable *table;
2448 char *b = blob_size;
2450 guint32 idx, offset;
2452 if (rsrc->filename) {
2453 name = mono_string_to_utf8 (rsrc->filename);
2454 sname = g_path_get_basename (name);
2456 table = &assembly->tables [MONO_TABLE_FILE];
2458 alloc_table (table, table->rows);
2459 values = table->values + table->next_idx * MONO_FILE_SIZE;
2460 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
2461 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
2464 mono_sha1_get_digest_from_file (name, hash);
2465 mono_metadata_encode_value (20, b, &b);
2466 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2467 mono_image_add_stream_data (&assembly->blob, hash, 20);
2469 idx = table->next_idx++;
2470 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
2474 offset = mono_array_length (rsrc->data);
2475 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
2476 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
2477 offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
2478 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
2482 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
2484 alloc_table (table, table->rows);
2485 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
2486 values [MONO_MANIFEST_OFFSET] = offset;
2487 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
2488 name = mono_string_to_utf8 (rsrc->name);
2489 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
2491 values [MONO_MANIFEST_IMPLEMENTATION] = idx;
2496 set_version_from_string (MonoString *version, guint32 *values)
2498 gchar *ver, *p, *str;
2501 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
2502 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
2503 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
2504 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
2507 ver = str = mono_string_to_utf8 (version);
2508 for (i = 0; i < 4; ++i) {
2509 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
2515 /* handle Revision and Build */
2525 load_public_key (MonoString *fname, MonoDynamicAssembly *assembly) {
2526 char *name, *content;
2532 name = mono_string_to_utf8 (fname);
2533 if (g_file_get_contents (name, &content, &len, NULL)) {
2535 char *b = blob_size;
2536 /* check it's a public key or keypair */
2537 mono_metadata_encode_value (len, b, &b);
2538 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
2539 mono_image_add_stream_data (&assembly->blob, content, len);
2541 /* need to get the actual value from the key type... */
2542 assembly->strong_name_size = 128;
2543 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
2545 /* FIXME: how do we tell mcs if loading fails? */
2551 * mono_image_build_metadata() will fill the info in all the needed metadata tables
2552 * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
2553 * and recursively outputs the info for a module. Each module will output all the info
2554 * about it's types etc.
2555 * At the end of the process, method and field tokens are fixed up and the on-disk
2556 * compressed metadata representation is created.
2559 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
2561 MonoDynamicTable *table;
2562 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
2563 MonoDomain *domain = mono_object_domain (assemblyb);
2569 if (assembly->text_rva)
2572 assembly->text_rva = START_TEXT_RVA;
2574 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2575 alloc_table (table, 1);
2576 values = table->values + MONO_ASSEMBLY_SIZE;
2577 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2578 name = mono_string_to_utf8 (assemblyb->name);
2579 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
2581 if (assemblyb->culture) {
2582 name = mono_string_to_utf8 (assemblyb->culture);
2583 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
2586 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2588 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->keyfile, assembly);
2589 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2590 set_version_from_string (assemblyb->version, values);
2592 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2593 table->rows = 1; /* .<Module> */
2595 alloc_table (table, table->rows);
2597 * Set the first entry.
2599 values = table->values + table->columns;
2600 values [MONO_TYPEDEF_FLAGS] = 0;
2601 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2602 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2603 values [MONO_TYPEDEF_EXTENDS] = 0;
2604 values [MONO_TYPEDEF_FIELD_LIST] = 1;
2605 values [MONO_TYPEDEF_METHOD_LIST] = 1;
2608 * handle global methods
2609 * FIXME: test what to do when global methods are defined in multiple modules.
2611 if (assemblyb->modules) {
2612 MonoReflectionModuleBuilder *mod = mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, 0);
2613 if (mod->global_methods) {
2614 table = &assembly->tables [MONO_TABLE_METHOD];
2615 table->rows += mono_array_length (mod->global_methods);
2616 alloc_table (table, table->rows);
2617 for (i = 0; i < mono_array_length (mod->global_methods); ++i)
2618 mono_image_get_method_info (
2619 mono_array_get (mod->global_methods, MonoReflectionMethodBuilder*, i), assembly);
2621 if (mod->global_fields) {
2622 table = &assembly->tables [MONO_TABLE_FIELD];
2623 table->rows += mono_array_length (mod->global_fields);
2624 alloc_table (table, table->rows);
2625 for (i = 0; i < mono_array_length (mod->global_fields); ++i)
2626 mono_image_get_field_info (
2627 mono_array_get (mod->global_fields, MonoReflectionFieldBuilder*, i), assembly);
2631 if (assemblyb->modules) {
2632 len = mono_array_length (assemblyb->modules);
2633 table = &assembly->tables [MONO_TABLE_MODULE];
2634 alloc_table (table, len);
2635 for (i = 0; i < len; ++i)
2636 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
2638 table = &assembly->tables [MONO_TABLE_MODULE];
2640 alloc_table (table, table->rows);
2641 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
2646 if (assemblyb->modules) {
2647 /* Collect all types into a list sorted by their table_idx */
2648 GPtrArray *types = g_ptr_array_new ();
2650 len = mono_array_length (assemblyb->modules);
2651 for (i = 0; i < len; ++i) {
2652 MonoReflectionModuleBuilder *mb =
2653 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2655 for (i = 0; i < mono_array_length (mb->types); ++i) {
2656 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
2657 collect_types (types, type);
2661 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
2662 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2663 table->rows += types->len;
2664 alloc_table (table, table->rows);
2666 for (i = 0; i < types->len; ++i) {
2667 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
2668 mono_image_get_type_info (domain, type, assembly);
2670 g_ptr_array_free (types, TRUE);
2674 * table->rows is already set above and in mono_image_fill_module_table.
2676 /* add all the custom attributes at the end, once all the indexes are stable */
2677 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
2679 if (assemblyb->modules) {
2680 len = mono_array_length (assemblyb->modules);
2681 for (i = 0; i < len; ++i)
2682 module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
2686 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2690 * mono_image_insert_string:
2691 * @assembly: assembly builder object
2694 * Insert @str into the user string stream of @assembly.
2697 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
2703 MONO_ARCH_SAVE_REGS;
2705 if (!assembly->dynamic_assembly)
2706 mono_image_basic_init (assembly);
2708 if (assembly->dynamic_assembly->save) {
2709 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
2710 idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
2711 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2713 char *swapped = g_malloc (2 * mono_string_length (str));
2714 const char *p = (const char*)mono_string_chars (str);
2716 swap_with_size (swapped, p, 2, mono_string_length (str));
2717 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2721 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2723 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2726 idx = assembly->dynamic_assembly->us.index ++;
2728 mono_g_hash_table_insert (assembly->dynamic_assembly->tokens,
2729 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
2731 return MONO_TOKEN_STRING | idx;
2735 * mono_image_create_token:
2736 * @assembly: a dynamic assembly
2739 * Get a token to insert in the IL code stream for the given MemberInfo.
2740 * @obj can be one of:
2741 * ConstructorBuilder
2751 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2756 klass = obj->vtable->klass;
2757 if (strcmp (klass->name, "MethodBuilder") == 0) {
2758 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2759 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2760 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2762 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2763 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2764 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2765 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2767 else if (strcmp (klass->name, "FieldBuilder") == 0) {
2768 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2769 token = mb->table_idx | MONO_TOKEN_FIELD_DEF;
2771 else if (strcmp (klass->name, "TypeBuilder") == 0) {
2772 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2773 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
2775 else if (strcmp (klass->name, "MonoType") == 0) {
2776 MonoReflectionType *tb = (MonoReflectionType *)obj;
2777 token = mono_metadata_token_from_dor (
2778 mono_image_typedef_or_ref (assembly, tb->type));
2780 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
2781 strcmp (klass->name, "MonoMethod") == 0) {
2782 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2783 if (m->method->klass->image == assembly->assembly.image) {
2784 static guint32 method_table_idx = 0xffffff;
2786 * Each token should have a unique index, but the indexes are
2787 * assigned by managed code, so we don't know about them. An
2788 * easy solution is to count backwards...
2790 method_table_idx --;
2791 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
2793 token = mono_image_get_methodref_token (assembly, m->method);
2794 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2796 else if (strcmp (klass->name, "MonoField") == 0) {
2797 MonoReflectionField *f = (MonoReflectionField *)obj;
2798 if (f->klass->image == assembly->assembly.image) {
2799 static guint32 field_table_idx = 0xffffff;
2801 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
2803 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2804 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2806 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2807 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2808 token = mono_image_get_array_token (assembly, m);
2810 else if (strcmp (klass->name, "SignatureHelper") == 0) {
2811 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
2812 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
2815 g_error ("requested token for %s\n", klass->name);
2817 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
2824 guint32 import_lookup_table;
2828 guint32 import_address_table_rva;
2836 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
2839 create_dynamic_mono_image (char *assembly_name, char *module_name)
2843 image = g_new0 (MonoImage, 1);
2845 /* keep in sync with image.c */
2846 image->name = assembly_name;
2847 image->assembly_name = image->name; /* they may be different */
2848 image->module_name = module_name;
2849 image->references = g_new0 (MonoAssembly*, 1);
2850 image->references [0] = NULL;
2852 image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2853 image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2854 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2855 image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2857 image->delegate_begin_invoke_cache =
2858 g_hash_table_new ((GHashFunc)mono_signature_hash,
2859 (GCompareFunc)mono_metadata_signature_equal);
2860 image->delegate_end_invoke_cache =
2861 g_hash_table_new ((GHashFunc)mono_signature_hash,
2862 (GCompareFunc)mono_metadata_signature_equal);
2863 image->delegate_invoke_cache =
2864 g_hash_table_new ((GHashFunc)mono_signature_hash,
2865 (GCompareFunc)mono_metadata_signature_equal);
2867 image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2868 image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2869 image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2870 image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2871 image->synchronized_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2877 * mono_image_basic_init:
2878 * @assembly: an assembly builder object
2880 * Create the MonoImage that represents the assembly builder and setup some
2881 * of the helper hash table and the basic metadata streams.
2884 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2886 static const guchar entrycode [16] = {0xff, 0x25, 0};
2887 MonoDynamicAssembly *assembly;
2891 MONO_ARCH_SAVE_REGS;
2893 if (assemblyb->dynamic_assembly)
2897 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
2899 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2902 assembly->assembly.dynamic = assembly;
2903 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
2904 assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2905 assembly->method_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2906 assembly->field_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2907 assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2908 assembly->tokens = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2909 assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2910 assembly->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
2912 string_heap_init (&assembly->sheap);
2913 mono_image_add_stream_data (&assembly->us, "", 1);
2914 add_to_blob_cached (assembly, (char*) "", 1, NULL, 0);
2915 /* import tables... */
2916 mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2917 assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2918 assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2919 mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2920 assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2921 mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2922 assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2923 stream_data_align (&assembly->code);
2925 assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2927 for (i=0; i < 64; ++i) {
2928 assembly->tables [i].next_idx = 1;
2929 assembly->tables [i].columns = table_sizes [i];
2932 assembly->run = assemblyb->access != 2;
2933 assembly->save = assemblyb->access != 1;
2935 image = create_dynamic_mono_image (mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
2936 assembly->assembly.aname.name = image->name;
2937 image->assembly = (MonoAssembly*)assembly;
2938 assembly->assembly.image = image;
2940 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
2941 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
2945 calc_section_size (MonoDynamicAssembly *assembly)
2949 /* alignment constraints */
2950 assembly->code.index += 3;
2951 assembly->code.index &= ~3;
2952 assembly->meta_size += 3;
2953 assembly->meta_size &= ~3;
2954 assembly->resources.index += 3;
2955 assembly->resources.index &= ~3;
2957 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2958 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2961 assembly->sections [MONO_SECTION_RELOC].size = 12;
2962 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2969 * mono_image_create_pefile:
2970 * @assemblyb: an assembly builder object
2972 * When we need to save an assembly, we first call this function that ensures the metadata
2973 * tables are built for all the modules in the assembly. This function creates the PE-COFF
2974 * header, the image sections, the CLI header etc. all the data is written in
2975 * assembly->pefile where it can be easily retrieved later in chunks.
2978 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
2979 MonoMSDOSHeader *msdos;
2980 MonoDotNetHeader *header;
2981 MonoSectionTable *section;
2982 MonoCLIHeader *cli_header;
2983 guint32 size, image_size, virtual_base, text_offset;
2984 guint32 header_start, section_start, file_offset, virtual_offset;
2985 MonoDynamicAssembly *assembly;
2986 MonoDynamicStream *pefile;
2988 guint32 *rva, value;
2991 static const unsigned char msheader[] = {
2992 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2993 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2994 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2995 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2996 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2997 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2998 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2999 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3002 mono_image_basic_init (assemblyb);
3003 assembly = assemblyb->dynamic_assembly;
3005 /* already created */
3006 if (assembly->pefile.index)
3009 mono_image_build_metadata (assemblyb);
3011 if (assemblyb->resources) {
3012 int len = mono_array_length (assemblyb->resources);
3013 for (i = 0; i < len; ++i)
3014 assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
3018 build_compressed_metadata (assembly);
3020 nsections = calc_section_size (assembly);
3022 pefile = &assembly->pefile;
3024 /* The DOS header and stub */
3025 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
3026 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
3028 /* the dotnet header */
3029 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
3031 /* the section tables */
3032 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
3034 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
3035 virtual_offset = VIRT_ALIGN;
3038 for (i = 0; i < MONO_SECTION_MAX; ++i) {
3039 if (!assembly->sections [i].size)
3042 file_offset += FILE_ALIGN - 1;
3043 file_offset &= ~(FILE_ALIGN - 1);
3044 virtual_offset += VIRT_ALIGN - 1;
3045 virtual_offset &= ~(VIRT_ALIGN - 1);
3047 assembly->sections [i].offset = file_offset;
3048 assembly->sections [i].rva = virtual_offset;
3050 file_offset += assembly->sections [i].size;
3051 virtual_offset += assembly->sections [i].size;
3052 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
3055 file_offset += FILE_ALIGN - 1;
3056 file_offset &= ~(FILE_ALIGN - 1);
3057 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
3059 image_size += section_start + sizeof (MonoSectionTable) * nsections;
3061 /* back-patch info */
3062 msdos = (MonoMSDOSHeader*)pefile->data;
3063 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
3064 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
3065 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
3067 header = (MonoDotNetHeader*)(pefile->data + header_start);
3068 header->pesig [0] = 'P';
3069 header->pesig [1] = 'E';
3071 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
3072 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
3073 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
3074 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
3075 if (assemblyb->pekind == 1) {
3077 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
3080 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
3083 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
3085 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
3086 header->pe.pe_major = 6;
3087 header->pe.pe_minor = 0;
3088 size = assembly->sections [MONO_SECTION_TEXT].size;
3089 size += FILE_ALIGN - 1;
3090 size &= ~(FILE_ALIGN - 1);
3091 header->pe.pe_code_size = size;
3092 size = assembly->sections [MONO_SECTION_RSRC].size;
3093 size += FILE_ALIGN - 1;
3094 size &= ~(FILE_ALIGN - 1);
3095 header->pe.pe_data_size = size;
3096 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
3097 header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
3098 header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
3099 /* pe_rva_entry_point always at the beginning of the text section */
3100 header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
3102 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
3103 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
3104 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
3105 header->nt.pe_os_major = GUINT16_FROM_LE (4);
3106 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
3107 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
3108 size = section_start;
3109 size += FILE_ALIGN - 1;
3110 size &= ~(FILE_ALIGN - 1);
3111 header->nt.pe_header_size = GUINT32_FROM_LE (size);
3113 size += VIRT_ALIGN - 1;
3114 size &= ~(VIRT_ALIGN - 1);
3115 header->nt.pe_image_size = GUINT32_FROM_LE (size);
3118 // Translate the PEFileKind value to the value expected by the Windows loader
3121 short kind = assemblyb->pekind;
3124 // PEFileKinds.ConsoleApplication == 2
3125 // PEFileKinds.WindowApplication == 3
3128 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
3129 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
3135 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
3137 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
3138 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
3139 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
3140 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
3141 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
3142 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
3144 /* fill data directory entries */
3146 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
3147 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
3149 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
3150 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
3152 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
3153 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
3154 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
3155 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
3156 /* patch imported function RVA name */
3157 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
3158 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
3160 /* the import table */
3161 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
3162 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
3163 /* patch imported dll RVA name and other entries in the dir */
3164 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
3165 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
3166 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
3167 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
3168 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
3169 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
3171 p = (assembly->code.data + assembly->ilt_offset);
3172 value = (assembly->text_rva + assembly->imp_names_offset - 2);
3173 *p++ = (value) & 0xff;
3174 *p++ = (value >> 8) & (0xff);
3175 *p++ = (value >> 16) & (0xff);
3176 *p++ = (value >> 24) & (0xff);
3178 /* the CLI header info */
3179 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
3180 cli_header->ch_size = GUINT32_FROM_LE (72);
3181 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
3182 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
3183 if (assemblyb->entry_point)
3184 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
3186 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
3187 /* The embedded managed resources */
3188 text_offset = assembly->text_rva + assembly->code.index;
3189 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
3190 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
3191 text_offset += assembly->resources.index;
3192 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
3193 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
3194 text_offset += assembly->meta_size;
3195 if (assembly->strong_name_size) {
3196 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
3197 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
3198 text_offset += assembly->strong_name_size;
3201 /* write the section tables and section content */
3202 section = (MonoSectionTable*)(pefile->data + section_start);
3203 for (i = 0; i < MONO_SECTION_MAX; ++i) {
3204 static const char *section_names [] = {
3205 ".text", ".rsrc", ".reloc"
3207 if (!assembly->sections [i].size)
3209 strcpy (section->st_name, section_names [i]);
3210 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
3211 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
3212 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
3213 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
3214 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
3215 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
3216 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
3218 case MONO_SECTION_TEXT:
3219 /* patch entry point */
3220 p = (assembly->code.data + 2);
3221 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
3222 *p++ = (value) & 0xff;
3223 *p++ = (value >> 8) & 0xff;
3224 *p++ = (value >> 16) & 0xff;
3225 *p++ = (value >> 24) & 0xff;
3227 text_offset = assembly->sections [i].offset;
3228 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
3229 text_offset += assembly->code.index;
3230 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
3231 text_offset += assembly->resources.index;
3232 memcpy (pefile->data + text_offset, assembly->assembly.image->raw_metadata, assembly->meta_size);
3233 text_offset += assembly->meta_size;
3234 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
3236 g_free (assembly->assembly.image->raw_metadata);
3238 case MONO_SECTION_RELOC:
3239 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
3240 *rva = GUINT32_FROM_LE (assembly->text_rva);
3242 *rva = GUINT32_FROM_LE (12);
3244 data16 = (guint16*)rva;
3246 * the entrypoint is always at the start of the text section
3247 * 3 is IMAGE_REL_BASED_HIGHLOW
3248 * 2 is patch_size_rva - text_rva
3250 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
3252 *data16 = 0; /* terminate */
3254 case MONO_SECTION_RSRC:
3256 g_assert_not_reached ();
3261 /* check that the file is properly padded */
3264 FILE *f = fopen ("mypetest.exe", "w");
3265 fwrite (pefile->data, pefile->index, 1, f);
3272 * We need to return always the same object for MethodInfo, FieldInfo etc..
3273 * but we need to consider the reflected type.
3274 * type uses a different hash, since it uses custom hash/equal functions.
3279 MonoClass *refclass;
3283 reflected_equal (gconstpointer a, gconstpointer b) {
3284 const ReflectedEntry *ea = a;
3285 const ReflectedEntry *eb = b;
3287 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
3291 reflected_hash (gconstpointer a) {
3292 const ReflectedEntry *ea = a;
3293 return GPOINTER_TO_UINT (ea->item);
3296 #define CHECK_OBJECT(t,p,k) \
3302 mono_domain_lock (domain); \
3303 if (!domain->refobject_hash) \
3304 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
3305 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
3306 mono_domain_unlock (domain); \
3312 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
3314 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
3317 #define CACHE_OBJECT(p,o,k) \
3319 ReflectedEntry *e = ALLOC_REFENTRY; \
3321 e->refclass = (k); \
3322 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
3323 mono_domain_unlock (domain); \
3327 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
3329 /* this is done only once */
3330 mono_domain_lock (domain);
3331 CACHE_OBJECT (assembly, res, NULL);
3335 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoImage *module)
3337 /* this is done only once */
3338 mono_domain_lock (domain);
3339 CACHE_OBJECT (module, res, NULL);
3343 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
3345 MonoImage *image = moduleb->module.image;
3346 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
3349 /* a MonoImage was already created in mono_image_basic_init () */
3350 image = ab->dynamic_assembly->assembly.image;
3352 image = create_dynamic_mono_image (mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.name));
3354 moduleb->module.image = image;
3355 register_module (mono_object_domain (moduleb), moduleb, image);
3360 * mono_assembly_get_object:
3361 * @domain: an app domain
3362 * @assembly: an assembly
3364 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
3366 MonoReflectionAssembly*
3367 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
3369 static MonoClass *System_Reflection_Assembly;
3370 MonoReflectionAssembly *res;
3372 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
3373 if (!System_Reflection_Assembly)
3374 System_Reflection_Assembly = mono_class_from_name (
3375 mono_defaults.corlib, "System.Reflection", "Assembly");
3376 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
3377 res->assembly = assembly;
3378 CACHE_OBJECT (assembly, res, NULL);
3384 MonoReflectionModule*
3385 mono_module_get_object (MonoDomain *domain, MonoImage *image)
3387 static MonoClass *System_Reflection_Module;
3388 MonoReflectionModule *res;
3390 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
3391 if (!System_Reflection_Module)
3392 System_Reflection_Module = mono_class_from_name (
3393 mono_defaults.corlib, "System.Reflection", "Module");
3394 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
3397 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
3399 res->fqname = mono_string_new (domain, image->name);
3400 res->name = mono_string_new (domain, image->name);
3401 res->scopename = mono_string_new (domain, image->module_name);
3403 CACHE_OBJECT (image, res, NULL);
3407 MonoReflectionModule*
3408 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
3410 static MonoClass *System_Reflection_Module;
3411 MonoReflectionModule *res;
3412 MonoTableInfo *table;
3413 guint32 cols [MONO_FILE_SIZE];
3415 guint32 i, name_idx;
3418 if (!System_Reflection_Module)
3419 System_Reflection_Module = mono_class_from_name (
3420 mono_defaults.corlib, "System.Reflection", "Module");
3421 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
3423 table = &image->tables [MONO_TABLE_FILE];
3424 g_assert (table_index < table->rows);
3425 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
3428 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
3429 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
3431 // Check whenever the row has a corresponding row in the moduleref table
3432 table = &image->tables [MONO_TABLE_MODULEREF];
3433 for (i = 0; i < table->rows; ++i) {
3434 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
3435 val = mono_metadata_string_heap (image, name_idx);
3436 if (strcmp (val, name) == 0)
3437 res->image = image->modules [i];
3440 res->fqname = mono_string_new (domain, name);
3441 res->name = mono_string_new (domain, name);
3442 res->scopename = mono_string_new (domain, name);
3443 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
3449 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
3451 if ((t1->type != t2->type) ||
3452 (t1->byref != t2->byref))
3456 case MONO_TYPE_VOID:
3457 case MONO_TYPE_BOOLEAN:
3458 case MONO_TYPE_CHAR:
3469 case MONO_TYPE_STRING:
3472 case MONO_TYPE_OBJECT:
3473 case MONO_TYPE_TYPEDBYREF:
3475 case MONO_TYPE_VALUETYPE:
3476 case MONO_TYPE_CLASS:
3477 return t1->data.klass == t2->data.klass;
3479 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3480 case MONO_TYPE_SZARRAY:
3482 if (t1->data.type->type != t2->data.type->type)
3484 if (t1->data.type->type == MONO_TYPE_CLASS || t1->data.type->type == MONO_TYPE_VALUETYPE)
3485 return t1->data.type->data.klass == t2->data.type->data.klass;
3486 if (t1->data.type->type == MONO_TYPE_SZARRAY) {
3491 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
3492 case MONO_TYPE_ARRAY:
3493 if (t1->data.array->rank != t2->data.array->rank)
3495 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
3497 g_error ("implement type compare for %0x!", t1->type);
3505 mymono_metadata_type_hash (MonoType *t1)
3511 hash |= t1->byref << 6; /* do not collide with t1->type values */
3513 case MONO_TYPE_VALUETYPE:
3514 case MONO_TYPE_CLASS:
3515 /* check if the distribution is good enough */
3516 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
3518 case MONO_TYPE_SZARRAY:
3519 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
3525 * mono_type_get_object:
3526 * @domain: an app domain
3529 * Return an System.MonoType object representing the type @type.
3532 mono_type_get_object (MonoDomain *domain, MonoType *type)
3534 MonoReflectionType *res;
3535 MonoClass *klass = mono_class_from_mono_type (type);
3537 mono_domain_lock (domain);
3538 if (!domain->type_hash)
3539 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
3540 (GCompareFunc)mymono_metadata_type_equal);
3541 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
3542 mono_domain_unlock (domain);
3545 if (klass->reflection_info && !klass->wastypebuilder) {
3546 //g_assert_not_reached ();
3547 /* should this be considered an error condition? */
3549 mono_domain_unlock (domain);
3550 return klass->reflection_info;
3553 mono_class_init (klass);
3554 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
3556 mono_g_hash_table_insert (domain->type_hash, type, res);
3557 mono_domain_unlock (domain);
3562 * mono_method_get_object:
3563 * @domain: an app domain
3565 * @refclass: the reflected type (can be NULL)
3567 * Return an System.Reflection.MonoMethod object representing the method @method.
3569 MonoReflectionMethod*
3570 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
3573 * We use the same C representation for methods and constructors, but the type
3574 * name in C# is different.
3578 MonoReflectionMethod *ret;
3581 refclass = method->klass;
3583 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
3584 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3585 cname = "MonoCMethod";
3587 cname = "MonoMethod";
3588 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
3590 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
3591 ret->method = method;
3592 ret->name = mono_string_new (domain, method->name);
3593 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
3594 CACHE_OBJECT (method, ret, refclass);
3599 * mono_field_get_object:
3600 * @domain: an app domain
3604 * Return an System.Reflection.MonoField object representing the field @field
3607 MonoReflectionField*
3608 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
3610 MonoReflectionField *res;
3613 CHECK_OBJECT (MonoReflectionField *, field, klass);
3614 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
3615 res = (MonoReflectionField *)mono_object_new (domain, oklass);
3618 CACHE_OBJECT (field, res, klass);
3623 * mono_property_get_object:
3624 * @domain: an app domain
3626 * @property: a property
3628 * Return an System.Reflection.MonoProperty object representing the property @property
3631 MonoReflectionProperty*
3632 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
3634 MonoReflectionProperty *res;
3637 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
3638 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
3639 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
3641 res->property = property;
3642 CACHE_OBJECT (property, res, klass);
3647 * mono_event_get_object:
3648 * @domain: an app domain
3652 * Return an System.Reflection.MonoEvent object representing the event @event
3655 MonoReflectionEvent*
3656 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
3658 MonoReflectionEvent *res;
3661 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
3662 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
3663 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
3666 CACHE_OBJECT (event, res, klass);
3671 * mono_param_get_objects:
3672 * @domain: an app domain
3675 * Return an System.Reflection.ParameterInfo array object representing the parameters
3676 * in the method @method.
3678 MonoReflectionParameter**
3679 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
3681 MonoReflectionParameter **res;
3682 MonoReflectionMethod *member;
3687 if (!method->signature->param_count)
3690 /* Note: the cache is based on the address of the signature into the method
3691 * since we already cache MethodInfos with the method as keys.
3693 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature), NULL);
3695 member = mono_method_get_object (domain, method, NULL);
3696 names = g_new (char *, method->signature->param_count);
3697 mono_method_get_param_names (method, (const char **) names);
3699 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
3701 res = GC_MALLOC (sizeof (MonoReflectionParameter*) * method->signature->param_count);
3703 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
3705 for (i = 0; i < method->signature->param_count; ++i) {
3706 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
3707 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
3708 res [i]->DefaultValueImpl = NULL; /* FIXME */
3709 res [i]->MemberImpl = (MonoObject*)member;
3710 res [i]->NameImpl = mono_string_new (domain, names [i]);
3711 res [i]->PositionImpl = i + 1;
3712 res [i]->AttrsImpl = method->signature->params [i]->attrs;
3715 CACHE_OBJECT (&(method->signature), res, NULL);
3720 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
3724 memset (assembly, 0, sizeof (MonoAssemblyName));
3726 assembly->culture = "";
3728 while (*p && (isalnum (*p) || *p == '.' || *p == '-'))
3731 while (*p == ' ' || *p == ',') {
3740 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
3742 assembly->major = strtoul (p, &s, 10);
3743 if (s == p || *s != '.')
3746 assembly->minor = strtoul (p, &s, 10);
3747 if (s == p || *s != '.')
3750 assembly->build = strtoul (p, &s, 10);
3751 if (s == p || *s != '.')
3754 assembly->revision = strtoul (p, &s, 10);
3757 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
3759 if (strncmp (p, "neutral", 7) == 0) {
3760 assembly->culture = "";
3763 assembly->culture = p;
3764 while (*p && *p != ',') {
3768 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
3771 while (*s && isxdigit (*s)) {
3775 assembly->hash_len = s - p;
3776 if (!(s-p) || ((s-p) & 1))
3778 assembly->hash_value = s = p;
3779 while (*s && isxdigit (*s)) {
3781 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3784 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
3789 while (*p && *p != ',')
3793 while (*p == ' ' || *p == ',') {
3807 * mono_reflection_parse_type:
3810 * Parse a type name as accepted by the GetType () method and output the info
3811 * extracted in the info structure.
3812 * the name param will be mangled, so, make a copy before passing it to this function.
3813 * The fields in info will be valid until the memory pointed to by name is valid.
3814 * Returns 0 on parse error.
3815 * See also mono_type_get_name () below.
3818 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
3820 char *start, *p, *w, *last_point, *startn;
3821 int in_modifiers = 0;
3822 int isbyref = 0, rank;
3824 start = p = w = name;
3826 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
3827 info->name = info->name_space = NULL;
3828 info->nested = NULL;
3829 info->modifiers = NULL;
3831 /* last_point separates the namespace from the name */
3837 *p = 0; /* NULL terminate the name */
3839 info->nested = g_list_append (info->nested, startn);
3840 /* we have parsed the nesting namespace + name */
3844 info->name_space = start;
3846 info->name = last_point + 1;
3848 info->name_space = (char *)"";
3874 info->name_space = start;
3876 info->name = last_point + 1;
3878 info->name_space = (char *)"";
3885 if (isbyref) /* only one level allowed by the spec */
3888 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
3892 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
3903 else if (*p != '*') /* '*' means unknown lower bound */
3909 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
3921 return 0; /* missing assembly name */
3922 if (!assembly_name_to_aname (&info->assembly, p))
3928 if (info->assembly.name)
3931 *w = 0; /* terminate class name */
3932 if (!info->name || !*info->name)
3934 /* add other consistency checks */
3939 mono_type_get_name_recurse (MonoType *type, GString *str)
3943 switch (type->type) {
3944 case MONO_TYPE_ARRAY: {
3945 int i, rank = type->data.array->rank;
3947 mono_type_get_name_recurse (type->data.array->type, str);
3948 g_string_append_c (str, '[');
3949 for (i = 1; i < rank; i++)
3950 g_string_append_c (str, ',');
3951 g_string_append_c (str, ']');
3954 case MONO_TYPE_SZARRAY:
3955 mono_type_get_name_recurse (type->data.type, str);
3956 g_string_append (str, "[]");
3959 mono_type_get_name_recurse (type->data.type, str);
3960 g_string_append_c (str, '*');
3963 klass = mono_class_from_mono_type (type);
3964 if (klass->nested_in) {
3965 mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
3966 g_string_append_c (str, '+');
3968 if (*klass->name_space) {
3969 g_string_append (str, klass->name_space);
3970 g_string_append_c (str, '.');
3972 g_string_append (str, klass->name);
3978 * mono_type_get_name:
3981 * Returns the string representation for type as required by System.Reflection.
3982 * The inverse of mono_reflection_parse_type ().
3985 mono_type_get_name (MonoType *type)
3987 GString* result = g_string_new ("");
3988 mono_type_get_name_recurse (type, result);
3991 g_string_append_c (result, '&');
3993 return g_string_free (result, FALSE);
3997 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
4004 image = mono_defaults.corlib;
4007 klass = mono_class_from_name_case (image, info->name_space, info->name);
4009 klass = mono_class_from_name (image, info->name_space, info->name);
4012 for (mod = info->nested; mod; mod = mod->next) {
4015 mono_class_init (klass);
4016 nested = klass->nested_classes;
4019 klass = nested->data;
4021 if (g_strcasecmp (klass->name, mod->data) == 0)
4024 if (strcmp (klass->name, mod->data) == 0)
4028 nested = nested->next;
4035 mono_class_init (klass);
4036 for (mod = info->modifiers; mod; mod = mod->next) {
4037 modval = GPOINTER_TO_UINT (mod->data);
4038 if (!modval) { /* byref: must be last modifier */
4039 return &klass->this_arg;
4040 } else if (modval == -1) {
4041 klass = mono_ptr_class_get (&klass->byval_arg);
4042 } else { /* array rank */
4043 klass = mono_array_class_get (&klass->byval_arg, modval);
4045 mono_class_init (klass);
4048 return &klass->byval_arg;
4052 * mono_reflection_get_type:
4053 * @image: a metadata context
4054 * @info: type description structure
4055 * @ignorecase: flag for case-insensitive string compares
4057 * Build a MonoType from the type description in @info.
4062 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
4065 MonoReflectionAssembly *assembly;
4069 type = mono_reflection_get_type_internal (image, info, ignorecase);
4072 if (!mono_domain_has_type_resolve (mono_domain_get ()))
4075 // Reconstruct the type name
4076 fullName = g_string_new ("");
4077 if (info->name_space && (info->name_space [0] != '\0'))
4078 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
4080 g_string_printf (fullName, info->name);
4081 for (mod = info->nested; mod; mod = mod->next)
4082 g_string_append_printf (fullName, "+%s", (char*)mod->data);
4085 mono_domain_try_type_resolve (
4086 mono_domain_get (), fullName->str, NULL);
4087 if (assembly && (!image || (assembly->assembly->image == image)))
4088 type = mono_reflection_get_type_internal (assembly->assembly->image,
4090 g_string_free (fullName, TRUE);
4095 * mono_reflection_type_from_name:
4097 * @image: a metadata context (can be NULL).
4099 * Retrieves a MonoType from its @name. If the name is not fully qualified,
4100 * it defaults to get the type from @image or, if @image is NULL or loading
4101 * from it fails, uses corlib.
4105 mono_reflection_type_from_name (char *name, MonoImage *image)
4108 MonoTypeNameParse info;
4110 /*g_print ("requested type %s\n", str);*/
4111 if (!mono_reflection_parse_type (name, &info)) {
4112 g_list_free (info.modifiers);
4113 g_list_free (info.nested);
4117 if (info.assembly.name) {
4118 image = mono_image_loaded (info.assembly.name);
4119 /* do we need to load if it's not already loaded? */
4121 g_list_free (info.modifiers);
4122 g_list_free (info.nested);
4125 } else if (image == NULL) {
4126 image = mono_defaults.corlib;
4129 type = mono_reflection_get_type (image, &info, FALSE);
4130 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
4131 image = mono_defaults.corlib;
4132 type = mono_reflection_get_type (image, &info, FALSE);
4135 g_list_free (info.modifiers);
4136 g_list_free (info.nested);
4141 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
4143 int slen, type = t->type;
4148 case MONO_TYPE_BOOLEAN: {
4149 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
4154 case MONO_TYPE_CHAR:
4156 case MONO_TYPE_I2: {
4157 guint16 *val = g_malloc (sizeof (guint16));
4162 #if SIZEOF_VOID_P == 4
4168 case MONO_TYPE_I4: {
4169 guint32 *val = g_malloc (sizeof (guint32));
4174 #if SIZEOF_VOID_P == 8
4175 case MONO_TYPE_U: /* error out instead? this should probably not happen */
4180 case MONO_TYPE_I8: {
4181 guint64 *val = g_malloc (sizeof (guint64));
4186 case MONO_TYPE_VALUETYPE:
4187 if (t->data.klass->enumtype) {
4188 type = t->data.klass->enum_basetype->type;
4191 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
4194 case MONO_TYPE_STRING:
4195 if (*p == (char)0xFF) {
4199 slen = mono_metadata_decode_value (p, &p);
4201 return mono_string_new_len (mono_domain_get (), p, slen);
4202 case MONO_TYPE_CLASS: {
4205 if (*p == (char)0xFF) {
4210 slen = mono_metadata_decode_value (p, &p);
4211 n = g_memdup (p, slen + 1);
4213 t = mono_reflection_type_from_name (n, image);
4215 g_warning ("Cannot load type '%s'", n);
4218 return mono_type_get_object (mono_domain_get (), t);
4220 case MONO_TYPE_OBJECT: {
4228 } else if (subt == 0x0E) {
4229 type = MONO_TYPE_STRING;
4231 } else if (subt == 0x55) {
4234 slen = mono_metadata_decode_value (p, &p);
4235 n = g_memdup (p, slen + 1);
4237 t = mono_reflection_type_from_name (n, image);
4239 g_warning ("Cannot load type '%s'", n);
4242 subc = mono_class_from_mono_type (t);
4243 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
4244 MonoType simple_type = {{0}};
4245 simple_type.type = subt;
4246 subc = mono_class_from_mono_type (&simple_type);
4248 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
4250 val = load_cattr_value (image, &subc->byval_arg, p, end);
4251 obj = mono_object_new (mono_domain_get (), subc);
4252 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
4256 case MONO_TYPE_SZARRAY:
4262 if (alen == 0xffffffff) {
4266 arr = mono_array_new (mono_domain_get(), mono_class_from_mono_type (t->data.type), alen);
4267 switch (t->data.type->type)
4271 case MONO_TYPE_BOOLEAN:
4272 for (i=0;i<alen;i++)
4274 MonoBoolean val=*p++;
4275 mono_array_set(arr,MonoBoolean,i,val);
4278 case MONO_TYPE_CHAR:
4281 for (i=0;i<alen;i++)
4283 guint16 val=read16(p);
4284 mono_array_set(arr,guint16,i,val);
4291 for (i=0;i<alen;i++)
4293 guint32 val=read32(p);
4294 mono_array_set(arr,guint32,i,val);
4301 for (i=0;i<alen;i++)
4303 guint64 val=read64(p);
4304 mono_array_set(arr,guint64,i,val);
4308 case MONO_TYPE_CLASS:
4309 case MONO_TYPE_STRING:
4310 for (i = 0; i < alen; i++) {
4311 MonoObject *item = load_cattr_value (image, t->data.type, p, &p);
4312 mono_array_set (arr, gpointer, i, item);
4316 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
4322 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
4328 type_is_reference (MonoType *type)
4330 switch (type->type) {
4331 case MONO_TYPE_BOOLEAN:
4332 case MONO_TYPE_CHAR:
4345 case MONO_TYPE_VALUETYPE:
4353 free_param_data (MonoMethodSignature *sig, void **params) {
4355 for (i = 0; i < sig->param_count; ++i) {
4356 if (!type_is_reference (sig->params [i]))
4357 g_free (params [i]);
4362 * Find the method index in the metadata methodDef table.
4363 * Later put these three helper methods in metadata and export them.
4366 find_method_index (MonoMethod *method) {
4367 MonoClass *klass = method->klass;
4370 for (i = 0; i < klass->method.count; ++i) {
4371 if (method == klass->methods [i])
4372 return klass->method.first + 1 + i;
4378 * Find the field index in the metadata FieldDef table.
4381 find_field_index (MonoClass *klass, MonoClassField *field) {
4384 for (i = 0; i < klass->field.count; ++i) {
4385 if (field == &klass->fields [i])
4386 return klass->field.first + 1 + i;
4392 * Find the property index in the metadata Property table.
4395 find_property_index (MonoClass *klass, MonoProperty *property) {
4398 for (i = 0; i < klass->property.count; ++i) {
4399 if (property == &klass->properties [i])
4400 return klass->property.first + 1 + i;
4406 * Find the event index in the metadata Event table.
4409 find_event_index (MonoClass *klass, MonoEvent *event) {
4412 for (i = 0; i < klass->event.count; ++i) {
4413 if (event == &klass->events [i])
4414 return klass->event.first + 1 + i;
4420 create_custom_attr (MonoImage *image, MonoMethod *method,
4421 const char *data, guint32 len)
4423 const char *p = data;
4425 guint32 i, j, num_named;
4429 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
4432 mono_class_init (method->klass);
4433 /*g_print ("got attr %s\n", method->klass->name);*/
4435 params = g_new (void*, method->signature->param_count);
4439 for (i = 0; i < method->signature->param_count; ++i) {
4440 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
4444 attr = mono_object_new (mono_domain_get (), method->klass);
4445 mono_runtime_invoke (method, attr, params, NULL);
4446 free_param_data (method->signature, params);
4448 num_named = read16 (named);
4450 for (j = 0; j < num_named; j++) {
4452 char *name, named_type, data_type;
4453 named_type = *named++;
4454 data_type = *named++; /* type of data */
4455 if (data_type == 0x55) {
4458 type_len = mono_metadata_decode_blob_size (named, &named);
4459 type_name = g_malloc (type_len + 1);
4460 memcpy (type_name, named, type_len);
4461 type_name [type_len] = 0;
4463 /* FIXME: lookup the type and check type consistency */
4465 name_len = mono_metadata_decode_blob_size (named, &named);
4466 name = g_malloc (name_len + 1);
4467 memcpy (name, named, name_len);
4468 name [name_len] = 0;
4470 if (named_type == 0x53) {
4471 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
4472 void *val = load_cattr_value (image, field->type, named, &named);
4473 mono_field_set_value (attr, field, val);
4474 if (!type_is_reference (field->type))
4476 } else if (named_type == 0x54) {
4479 MonoType *prop_type;
4481 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
4482 /* can we have more that 1 arg in a custom attr named property? */
4483 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
4484 pparams [0] = load_cattr_value (image, prop_type, named, &named);
4485 mono_property_set_value (prop, attr, pparams, NULL);
4486 if (!type_is_reference (prop_type))
4487 g_free (pparams [0]);
4496 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
4503 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
4504 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
4505 for (i = 0; i < cinfo->num_attrs; ++i) {
4506 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
4507 mono_array_set (result, gpointer, i, attr);
4513 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
4515 guint32 mtoken, i, len;
4516 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
4518 MonoCustomAttrInfo *ainfo;
4519 GList *tmp, *list = NULL;
4522 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4523 /* the table is not sorted */
4524 for (i = 0; i < ca->rows; ++i) {
4525 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
4527 list = g_list_prepend (list, GUINT_TO_POINTER (i));
4529 len = g_list_length (list);
4532 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
4533 ainfo->num_attrs = len;
4534 ainfo->image = image;
4535 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
4536 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
4537 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
4538 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
4539 case CUSTOM_ATTR_TYPE_METHODDEF:
4540 mtoken |= MONO_TOKEN_METHOD_DEF;
4542 case CUSTOM_ATTR_TYPE_MEMBERREF:
4543 mtoken |= MONO_TOKEN_MEMBER_REF;
4546 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
4549 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
4550 if (!ainfo->attrs [i].ctor)
4551 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
4552 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
4553 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
4554 ainfo->attrs [i].data = data;
4562 mono_custom_attrs_from_method (MonoMethod *method)
4564 MonoCustomAttrInfo *cinfo;
4567 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
4569 idx = find_method_index (method);
4570 idx <<= CUSTOM_ATTR_BITS;
4571 idx |= CUSTOM_ATTR_METHODDEF;
4572 return mono_custom_attrs_from_index (method->klass->image, idx);
4576 mono_custom_attrs_from_class (MonoClass *klass)
4578 MonoCustomAttrInfo *cinfo;
4581 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
4583 idx = mono_metadata_token_index (klass->type_token);
4584 idx <<= CUSTOM_ATTR_BITS;
4585 idx |= CUSTOM_ATTR_TYPEDEF;
4586 return mono_custom_attrs_from_index (klass->image, idx);
4590 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
4592 MonoCustomAttrInfo *cinfo;
4595 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
4597 idx = 1; /* there is only one assembly */
4598 idx <<= CUSTOM_ATTR_BITS;
4599 idx |= CUSTOM_ATTR_ASSEMBLY;
4600 return mono_custom_attrs_from_index (assembly->image, idx);
4604 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
4606 MonoCustomAttrInfo *cinfo;
4609 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
4611 idx = find_property_index (klass, property);
4612 idx <<= CUSTOM_ATTR_BITS;
4613 idx |= CUSTOM_ATTR_PROPERTY;
4614 return mono_custom_attrs_from_index (klass->image, idx);
4618 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
4620 MonoCustomAttrInfo *cinfo;
4623 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
4625 idx = find_event_index (klass, event);
4626 idx <<= CUSTOM_ATTR_BITS;
4627 idx |= CUSTOM_ATTR_EVENT;
4628 return mono_custom_attrs_from_index (klass->image, idx);
4632 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
4634 MonoCustomAttrInfo *cinfo;
4637 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
4639 idx = find_field_index (klass, field);
4640 idx <<= CUSTOM_ATTR_BITS;
4641 idx |= CUSTOM_ATTR_FIELDDEF;
4642 return mono_custom_attrs_from_index (klass->image, idx);
4646 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
4649 guint32 i, idx, method_index;
4650 guint32 param_list, param_last, param_pos, found;
4653 /* FIXME: handle dynamic custom attrs for parameters */
4654 /*if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
4656 image = method->klass->image;
4657 method_index = find_method_index (method);
4658 ca = &image->tables [MONO_TABLE_METHOD];
4660 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
4661 if (method_index == ca->rows) {
4662 ca = &image->tables [MONO_TABLE_PARAM];
4663 param_last = ca->rows + 1;
4665 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
4666 ca = &image->tables [MONO_TABLE_PARAM];
4669 for (i = param_list; i < param_last; ++i) {
4670 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
4671 if (param_pos == param) {
4679 idx <<= CUSTOM_ATTR_BITS;
4680 idx |= CUSTOM_ATTR_PARAMDEF;
4681 return mono_custom_attrs_from_index (image, idx);
4685 * mono_reflection_get_custom_attrs:
4686 * @obj: a reflection object handle
4688 * Return an array with all the custom attributes defined of the
4689 * reflection handle @obj. The objects are fully build.
4692 mono_reflection_get_custom_attrs (MonoObject *obj)
4696 MonoCustomAttrInfo *cinfo;
4698 MONO_ARCH_SAVE_REGS;
4700 klass = obj->vtable->klass;
4701 /* FIXME: need to handle: Module */
4702 if (klass == mono_defaults.monotype_class) {
4703 MonoReflectionType *rtype = (MonoReflectionType*)obj;
4704 klass = mono_class_from_mono_type (rtype->type);
4705 cinfo = mono_custom_attrs_from_class (klass);
4706 } else if (strcmp ("Assembly", klass->name) == 0) {
4707 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
4708 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
4709 } else if (strcmp ("MonoProperty", klass->name) == 0) {
4710 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
4711 cinfo = mono_custom_attrs_from_property (rprop->klass, rprop->property);
4712 } else if (strcmp ("MonoEvent", klass->name) == 0) {
4713 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
4714 cinfo = mono_custom_attrs_from_event (revent->klass, revent->event);
4715 } else if (strcmp ("MonoField", klass->name) == 0) {
4716 MonoReflectionField *rfield = (MonoReflectionField*)obj;
4717 cinfo = mono_custom_attrs_from_field (rfield->klass, rfield->field);
4718 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
4719 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
4720 cinfo = mono_custom_attrs_from_method (rmethod->method);
4721 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
4722 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
4723 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
4724 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl);
4725 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
4726 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
4727 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
4728 } else { /* handle other types here... */
4729 g_error ("get custom attrs not yet supported for %s", klass->name);
4733 result = mono_custom_attrs_construct (cinfo);
4735 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
4736 result = mono_array_new (mono_domain_get (), klass, 0);
4742 static MonoMethodSignature*
4743 parameters_to_signature (MonoArray *parameters) {
4744 MonoMethodSignature *sig;
4747 count = parameters? mono_array_length (parameters): 0;
4749 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
4750 sig->param_count = count;
4751 sig->sentinelpos = -1; /* FIXME */
4752 for (i = 0; i < count; ++i) {
4753 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
4754 sig->params [i] = pt->type;
4759 static MonoMethodSignature*
4760 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
4761 MonoMethodSignature *sig;
4763 sig = parameters_to_signature (ctor->parameters);
4764 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4765 sig->ret = &mono_defaults.void_class->byval_arg;
4769 static MonoMethodSignature*
4770 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
4771 MonoMethodSignature *sig;
4773 sig = parameters_to_signature (method->parameters);
4774 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
4775 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
4780 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
4782 MonoClass *klass = mono_object_class (prop);
4783 if (strcmp (klass->name, "PropertyBuilder") == 0) {
4784 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
4785 *name = mono_string_to_utf8 (pb->name);
4786 *type = pb->type->type;
4788 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
4789 *name = g_strdup (p->property->name);
4790 if (p->property->get)
4791 *type = p->property->get->signature->ret;
4793 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
4798 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
4800 MonoClass *klass = mono_object_class (field);
4801 if (strcmp (klass->name, "FieldBuilder") == 0) {
4802 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
4803 *name = mono_string_to_utf8 (fb->name);
4804 *type = fb->type->type;
4806 MonoReflectionField *f = (MonoReflectionField *)field;
4807 *name = g_strdup (f->field->name);
4808 *type = f->field->type;
4813 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
4814 char *name, *result;
4818 name = mono_type_get_name (type);
4819 klass = my_mono_class_from_mono_type (type);
4820 ta = klass->image->assembly;
4821 if (ta == ass || klass->image == mono_defaults.corlib)
4824 /* missing public key */
4825 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
4826 name, ta->aname.name,
4827 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
4828 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
4834 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
4837 MonoTypeEnum simple_type;
4839 if ((p-buffer) + 10 >= *buflen) {
4842 newbuf = g_realloc (buffer, *buflen);
4843 p = newbuf + (p-buffer);
4846 argval = ((char*)arg + sizeof (MonoObject));
4847 simple_type = type->type;
4849 switch (simple_type) {
4850 case MONO_TYPE_BOOLEAN:
4855 case MONO_TYPE_CHAR:
4858 swap_with_size (p, argval, 2, 1);
4864 swap_with_size (p, argval, 4, 1);
4870 swap_with_size (p, argval, 8, 1);
4873 case MONO_TYPE_VALUETYPE:
4874 if (type->data.klass->enumtype) {
4875 simple_type = type->data.klass->enum_basetype->type;
4878 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
4881 case MONO_TYPE_STRING: {
4888 str = mono_string_to_utf8 ((MonoString*)arg);
4889 slen = strlen (str);
4890 if ((p-buffer) + 10 + slen >= *buflen) {
4894 newbuf = g_realloc (buffer, *buflen);
4895 p = newbuf + (p-buffer);
4898 mono_metadata_encode_value (slen, p, &p);
4899 memcpy (p, str, slen);
4904 case MONO_TYPE_CLASS: {
4912 k = mono_object_class (arg);
4913 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
4914 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
4915 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
4917 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
4918 slen = strlen (str);
4919 if ((p-buffer) + 10 + slen >= *buflen) {
4923 newbuf = g_realloc (buffer, *buflen);
4924 p = newbuf + (p-buffer);
4927 mono_metadata_encode_value (slen, p, &p);
4928 memcpy (p, str, slen);
4933 case MONO_TYPE_SZARRAY: {
4938 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
4941 len = mono_array_length ((MonoArray*)arg);
4943 *p++ = (len >> 8) & 0xff;
4944 *p++ = (len >> 16) & 0xff;
4945 *p++ = (len >> 24) & 0xff;
4947 *retbuffer = buffer;
4948 eclass = mono_class_from_mono_type (type)->element_class;
4949 for (i = 0; i < len; ++i) {
4950 encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
4954 /* it may be a boxed value or a Type */
4955 case MONO_TYPE_OBJECT: {
4956 MonoClass *klass = mono_object_class (arg);
4960 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
4963 } else if (klass->enumtype) {
4965 } else if (klass == mono_defaults.string_class) {
4966 simple_type = MONO_TYPE_STRING;
4969 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
4970 *p++ = simple_type = klass->byval_arg.type;
4973 g_error ("unhandled type in custom attr");
4975 str = type_get_qualified_name (klass->enum_basetype, NULL);
4976 slen = strlen (str);
4977 if ((p-buffer) + 10 + slen >= *buflen) {
4981 newbuf = g_realloc (buffer, *buflen);
4982 p = newbuf + (p-buffer);
4985 mono_metadata_encode_value (slen, p, &p);
4986 memcpy (p, str, slen);
4989 simple_type = klass->enum_basetype->type;
4993 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
4996 *retbuffer = buffer;
5000 * mono_reflection_get_custom_attrs_blob:
5001 * @ctor: custom attribute constructor
5002 * @ctorArgs: arguments o the constructor
5008 * Creates the blob of data that needs to be saved in the metadata and that represents
5009 * the custom attributed described by @ctor, @ctorArgs etc.
5010 * Returns: a Byte array representing the blob of data.
5013 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
5016 MonoMethodSignature *sig;
5021 MONO_ARCH_SAVE_REGS;
5023 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
5024 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
5026 sig = ((MonoReflectionMethod*)ctor)->method->signature;
5028 g_assert (mono_array_length (ctorArgs) == sig->param_count);
5030 p = buffer = g_malloc (buflen);
5031 /* write the prolog */
5034 for (i = 0; i < sig->param_count; ++i) {
5035 arg = mono_array_get (ctorArgs, MonoObject*, i);
5036 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
5040 i += mono_array_length (properties);
5042 i += mono_array_length (fields);
5044 *p++ = (i >> 8) & 0xff;
5047 for (i = 0; i < mono_array_length (properties); ++i) {
5052 prop = mono_array_get (properties, gpointer, i);
5053 get_prop_name_and_type (prop, &pname, &ptype);
5054 *p++ = 0x54; /* PROPERTY signature */
5055 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
5056 char *str = type_get_qualified_name (ptype, NULL);
5057 int slen = strlen (str);
5058 if ((p-buffer) + 10 + slen >= buflen) {
5062 newbuf = g_realloc (buffer, buflen);
5063 p = newbuf + (p-buffer);
5068 * This seems to be optional...
5071 mono_metadata_encode_value (slen, p, &p);
5072 memcpy (p, str, slen);
5076 mono_metadata_encode_value (ptype->type, p, &p);
5078 len = strlen (pname);
5079 mono_metadata_encode_value (len, p, &p);
5080 memcpy (p, pname, len);
5082 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
5089 for (i = 0; i < mono_array_length (fields); ++i) {
5094 field = mono_array_get (fields, gpointer, i);
5095 get_field_name_and_type (field, &fname, &ftype);
5096 *p++ = 0x53; /* FIELD signature */
5097 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
5098 char *str = type_get_qualified_name (ftype, NULL);
5099 int slen = strlen (str);
5100 if ((p-buffer) + 10 + slen >= buflen) {
5104 newbuf = g_realloc (buffer, buflen);
5105 p = newbuf + (p-buffer);
5110 * This seems to be optional...
5113 mono_metadata_encode_value (slen, p, &p);
5114 memcpy (p, str, slen);
5118 mono_metadata_encode_value (ftype->type, p, &p);
5120 len = strlen (fname);
5121 mono_metadata_encode_value (len, p, &p);
5122 memcpy (p, fname, len);
5124 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
5129 g_assert (p - buffer <= buflen);
5130 buflen = p - buffer;
5131 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5132 p = mono_array_addr (result, char, 0);
5133 memcpy (p, buffer, buflen);
5135 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
5141 * mono_reflection_setup_internal_class:
5142 * @tb: a TypeBuilder object
5144 * Creates a MonoClass that represents the TypeBuilder.
5145 * This is a trick that lets us simplify a lot of reflection code
5146 * (and will allow us to support Build and Run assemblies easier).
5149 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
5151 MonoClass *klass, *parent;
5153 MONO_ARCH_SAVE_REGS;
5155 klass = g_new0 (MonoClass, 1);
5157 klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
5160 /* check so we can compile corlib correctly */
5161 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
5162 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
5163 parent = tb->parent->type->data.klass;
5165 parent = my_mono_class_from_mono_type (tb->parent->type);
5169 klass->inited = 1; /* we lie to the runtime */
5170 klass->name = mono_string_to_utf8 (tb->name);
5171 klass->name_space = mono_string_to_utf8 (tb->nspace);
5172 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
5173 klass->flags = tb->attrs;
5175 klass->element_class = klass;
5176 klass->reflection_info = tb; /* need to pin. */
5178 /* Put into cache so mono_class_get () will find it */
5179 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
5182 mono_g_hash_table_insert (tb->module->assemblyb->dynamic_assembly->tokens,
5183 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
5187 mono_class_setup_parent (klass, parent);
5188 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
5189 const char *old_n = klass->name;
5190 /* trick to get relative numbering right when compiling corlib */
5191 klass->name = "BuildingObject";
5192 mono_class_setup_parent (klass, mono_defaults.object_class);
5193 klass->name = old_n;
5195 mono_class_setup_mono_type (klass);
5197 mono_class_setup_supertypes (klass);
5200 * FIXME: handle interfaces.
5203 tb->type.type = &klass->byval_arg;
5205 if (tb->nesting_type) {
5206 g_assert (tb->nesting_type->type);
5207 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
5210 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
5214 * mono_reflection_create_internal_class:
5215 * @tb: a TypeBuilder object
5217 * Actually create the MonoClass that is associated with the TypeBuilder.
5220 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
5224 MONO_ARCH_SAVE_REGS;
5226 klass = my_mono_class_from_mono_type (tb->type.type);
5228 if (klass->enumtype && klass->enum_basetype == NULL) {
5229 MonoReflectionFieldBuilder *fb;
5231 g_assert (tb->fields != NULL);
5232 g_assert (mono_array_length (tb->fields) >= 1);
5234 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
5236 klass->enum_basetype = fb->type->type;
5237 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
5238 if (!klass->element_class)
5239 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
5240 klass->instance_size = klass->element_class->instance_size;
5241 klass->size_inited = 1;
5243 * this is almost safe to do with enums and it's needed to be able
5244 * to create objects of the enum type (for use in SetConstant).
5246 /* FIXME: Does this mean enums can't have method overrides ? */
5247 mono_class_setup_vtable (klass, NULL, 0);
5252 reflection_methodbuilder_to_mono_method (MonoClass *klass,
5253 ReflectionMethodBuilder *rmb,
5254 MonoMethodSignature *sig)
5257 MonoMethodNormal *pm;
5259 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5260 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5261 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
5263 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
5265 pm = (MonoMethodNormal*)m;
5268 m->flags = rmb->attrs;
5269 m->iflags = rmb->iattrs;
5270 m->name = mono_string_to_utf8 (rmb->name);
5273 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
5275 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
5276 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
5279 m->addr = mono_lookup_internal_call (m);
5280 m->signature->pinvoke = 1;
5281 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
5283 m->signature->pinvoke = 1;
5285 } else if (!m->klass->dummy &&
5286 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
5287 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
5288 MonoMethodHeader *header;
5290 gint32 max_stack, i;
5291 gint32 num_locals = 0;
5292 gint32 num_clauses = 0;
5296 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
5297 code_size = rmb->ilgen->code_len;
5298 max_stack = rmb->ilgen->max_stack;
5299 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
5300 if (rmb->ilgen->ex_handlers)
5301 num_clauses = method_count_clauses (rmb->ilgen);
5304 code = mono_array_addr (rmb->code, guint8, 0);
5305 code_size = mono_array_length (rmb->code);
5306 /* we probably need to run a verifier on the code... */
5316 header = g_malloc0 (sizeof (MonoMethodHeader) +
5317 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
5318 header->code_size = code_size;
5319 header->code = g_malloc (code_size);
5320 memcpy ((char*)header->code, code, code_size);
5321 header->max_stack = max_stack;
5322 header->init_locals = rmb->init_locals;
5323 header->num_locals = num_locals;
5325 for (i = 0; i < num_locals; ++i) {
5326 MonoReflectionLocalBuilder *lb =
5327 mono_array_get (rmb->ilgen->locals,
5328 MonoReflectionLocalBuilder*, i);
5330 header->locals [i] = g_new0 (MonoType, 1);
5331 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
5334 header->num_clauses = num_clauses;
5336 header->clauses = method_encode_clauses (klass->image->assembly->dynamic,
5341 pm->header = header;
5348 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
5350 ReflectionMethodBuilder rmb;
5352 MonoMethodSignature *sig;
5354 name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
5356 sig = ctor_builder_to_signature (mb);
5358 rmb.ilgen = mb->ilgen;
5359 rmb.parameters = mb->parameters;
5360 rmb.pinfo = mb->pinfo;
5361 rmb.attrs = mb->attrs | METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
5362 rmb.iattrs = mb->iattrs;
5363 rmb.call_conv = mb->call_conv;
5364 rmb.type = mb->type;
5365 rmb.name = mono_string_new (mono_domain_get (), name);
5366 rmb.table_idx = &mb->table_idx;
5367 rmb.init_locals = mb->init_locals;
5370 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
5371 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
5373 if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
5374 /* ilgen is no longer needed */
5382 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
5384 ReflectionMethodBuilder rmb;
5385 MonoMethodSignature *sig;
5387 sig = method_builder_to_signature (mb);
5389 rmb.ilgen = mb->ilgen;
5390 rmb.parameters = mb->parameters;
5391 rmb.pinfo = mb->pinfo;
5392 rmb.attrs = mb->attrs;
5393 rmb.iattrs = mb->iattrs;
5394 rmb.call_conv = mb->call_conv;
5395 rmb.type = mb->type;
5396 rmb.name = mb->name;
5397 rmb.table_idx = &mb->table_idx;
5398 rmb.init_locals = mb->init_locals;
5399 rmb.code = mb->code;
5401 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
5402 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
5404 if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
5405 /* ilgen is no longer needed */
5412 ensure_runtime_vtable (MonoClass *klass)
5414 MonoReflectionTypeBuilder *tb = klass->reflection_info;
5415 int i, num, j, onum;
5416 MonoMethod **overrides;
5418 if (!tb || klass->wastypebuilder)
5421 ensure_runtime_vtable (klass->parent);
5423 num = tb->ctors? mono_array_length (tb->ctors): 0;
5424 num += tb->methods? mono_array_length (tb->methods): 0;
5425 klass->method.count = num;
5426 klass->methods = g_new (MonoMethod*, num);
5427 num = tb->ctors? mono_array_length (tb->ctors): 0;
5428 for (i = 0; i < num; ++i)
5429 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
5430 num = tb->methods? mono_array_length (tb->methods): 0;
5432 for (i = 0; i < num; ++i)
5433 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
5435 klass->wastypebuilder = TRUE;
5436 if (tb->interfaces) {
5437 klass->interface_count = mono_array_length (tb->interfaces);
5438 klass->interfaces = g_new (MonoClass*, klass->interface_count);
5439 for (i = 0; i < klass->interface_count; ++i) {
5440 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
5441 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
5445 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
5446 for (i = 0; i < klass->method.count; ++i)
5447 klass->methods [i]->slot = i;
5452 for (i = 0; i < mono_array_length (tb->methods); ++i) {
5453 MonoReflectionMethodBuilder *mb =
5454 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
5455 if (mb->override_method)
5460 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
5464 for (i = 0; i < mono_array_length (tb->methods); ++i) {
5465 MonoReflectionMethodBuilder *mb =
5466 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
5467 if (mb->override_method) {
5468 /* FIXME: What if 'override_method' is a MethodBuilder ? */
5469 overrides [onum * 2] =
5470 mb->override_method->method;
5471 overrides [onum * 2 + 1] =
5474 g_assert (mb->mhandle);
5481 mono_class_setup_vtable (klass, overrides, onum);
5485 typebuilder_setup_fields (MonoClass *klass)
5487 MonoReflectionTypeBuilder *tb = klass->reflection_info;
5488 MonoReflectionFieldBuilder *fb;
5489 MonoClassField *field;
5494 klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
5495 klass->field.first = 0;
5496 klass->field.last = klass->field.count;
5498 if (!klass->field.count)
5501 klass->fields = g_new0 (MonoClassField, klass->field.count);
5503 for (i = 0; i < klass->field.count; ++i) {
5504 fb = mono_array_get (tb->fields, gpointer, i);
5505 field = &klass->fields [i];
5506 field->name = mono_string_to_utf8 (fb->name);
5508 /* FIXME: handle type modifiers */
5509 field->type = g_memdup (fb->type->type, sizeof (MonoType));
5510 field->type->attrs = fb->attrs;
5512 field->type = fb->type->type;
5514 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
5515 field->data = mono_array_addr (fb->rva_data, char, 0);
5516 if (fb->offset != -1)
5517 field->offset = fb->offset;
5518 field->parent = klass;
5520 mono_save_custom_attrs (klass->image, field, fb->cattrs);
5522 if (fb->def_value) {
5523 MonoDynamicAssembly *assembly = klass->image->assembly->dynamic;
5524 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
5525 field->def_value = g_new0 (MonoConstant, 1);
5526 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
5527 /* Copy the data from the blob since it might get realloc-ed */
5528 p = assembly->blob.data + idx;
5529 len = mono_metadata_decode_blob_size (p, &p2);
5531 field->def_value->value = g_malloc (len);
5532 memcpy (field->def_value->value, p, len);
5535 mono_class_layout_fields (klass);
5539 typebuilder_setup_properties (MonoClass *klass)
5541 MonoReflectionTypeBuilder *tb = klass->reflection_info;
5542 MonoReflectionPropertyBuilder *pb;
5545 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
5546 klass->property.first = 0;
5547 klass->property.last = klass->property.count;
5549 klass->properties = g_new0 (MonoProperty, klass->property.count);
5550 for (i = 0; i < klass->property.count; ++i) {
5551 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
5552 klass->properties [i].attrs = pb->attrs;
5553 klass->properties [i].name = mono_string_to_utf8 (pb->name);
5555 klass->properties [i].get = pb->get_method->mhandle;
5557 klass->properties [i].set = pb->set_method->mhandle;
5562 typebuilder_setup_events (MonoClass *klass)
5564 MonoReflectionTypeBuilder *tb = klass->reflection_info;
5565 MonoReflectionEventBuilder *eb;
5568 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
5569 klass->event.first = 0;
5570 klass->event.last = klass->event.count;
5572 klass->events = g_new0 (MonoEvent, klass->event.count);
5573 for (i = 0; i < klass->event.count; ++i) {
5574 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
5575 klass->events [i].attrs = eb->attrs;
5576 klass->events [i].name = mono_string_to_utf8 (eb->name);
5578 klass->events [i].add = eb->add_method->mhandle;
5579 if (eb->remove_method)
5580 klass->events [i].remove = eb->remove_method->mhandle;
5581 if (eb->raise_method)
5582 klass->events [i].raise = eb->raise_method->mhandle;
5584 if (eb->other_methods) {
5585 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
5586 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
5587 MonoReflectionMethodBuilder *mb =
5588 mono_array_get (eb->other_methods,
5589 MonoReflectionMethodBuilder*, j);
5590 klass->events [i].other [j] = mb->mhandle;
5597 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
5600 MonoReflectionType* res;
5602 MONO_ARCH_SAVE_REGS;
5604 klass = my_mono_class_from_mono_type (tb->type.type);
5606 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
5609 * Fields to set in klass:
5610 * the various flags: delegate/unicode/contextbound etc.
5613 klass->flags = tb->attrs;
5614 klass->element_class = klass;
5616 if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->run)
5617 /* No need to fully construct the type */
5618 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5620 /* enums are done right away */
5621 if (!klass->enumtype)
5622 ensure_runtime_vtable (klass);
5624 /* fields and object layout */
5625 if (klass->parent) {
5626 if (!klass->parent->size_inited)
5627 mono_class_init (klass->parent);
5628 klass->instance_size += klass->parent->instance_size;
5629 klass->class_size += klass->parent->class_size;
5630 klass->min_align = klass->parent->min_align;
5632 klass->instance_size = sizeof (MonoObject);
5633 klass->min_align = 1;
5636 /* FIXME: handle packing_size and instance_size */
5637 typebuilder_setup_fields (klass);
5639 typebuilder_setup_properties (klass);
5641 typebuilder_setup_events (klass);
5643 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5644 /* with enums res == tb: need to fix that. */
5645 if (!klass->enumtype)
5646 g_assert (res != (MonoReflectionType*)tb);
5651 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
5653 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5654 guint32 na = mono_array_length (sig->arguments);
5659 MONO_ARCH_SAVE_REGS;
5661 p = buf = g_malloc (10 + na * 10);
5663 mono_metadata_encode_value (0x07, p, &p);
5664 mono_metadata_encode_value (na, p, &p);
5665 for (i = 0; i < na; ++i) {
5666 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5667 encode_reflection_type (assembly, type, p, &p);
5671 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5672 p = mono_array_addr (result, char, 0);
5673 memcpy (p, buf, buflen);
5680 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
5682 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
5683 guint32 na = mono_array_length (sig->arguments);
5688 MONO_ARCH_SAVE_REGS;
5690 p = buf = g_malloc (10 + na * 10);
5692 mono_metadata_encode_value (0x06, p, &p);
5693 for (i = 0; i < na; ++i) {
5694 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
5695 encode_reflection_type (assembly, type, p, &p);
5699 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
5700 p = mono_array_addr (result, char, 0);
5701 memcpy (p, buf, buflen);
5708 * mono_reflection_lookup_dynamic_token:
5710 * Finish the Builder object pointed to by TOKEN and return the corresponding
5711 * runtime structure.
5714 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
5716 MonoDynamicAssembly *assembly = image->assembly->dynamic;
5720 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5723 if (strcmp (obj->vtable->klass->name, "String") == 0) {
5724 result = mono_string_intern ((MonoString*)obj);
5727 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
5728 MonoReflectionType *tb = (MonoReflectionType*)obj;
5729 result = mono_class_from_mono_type (tb->type);
5732 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
5733 result = ((MonoReflectionMethod*)obj)->method;
5736 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
5737 result = ((MonoReflectionMethod*)obj)->method;
5740 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
5741 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
5742 result = mb->mhandle;
5744 /* Type is not yet created */
5745 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5747 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5750 * Hopefully this has been filled in by calling CreateType() on the
5754 * TODO: This won't work if the application finishes another
5755 * TypeBuilder instance instead of this one.
5757 result = mb->mhandle;
5760 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
5761 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
5763 result = cb->mhandle;
5765 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
5767 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5768 result = cb->mhandle;
5771 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
5772 result = ((MonoReflectionField*)obj)->field;
5775 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
5776 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
5777 result = fb->handle;
5780 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
5782 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5783 result = fb->handle;
5786 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
5787 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
5790 klass = tb->type.type->data.klass;
5791 if (klass->wastypebuilder) {
5792 /* Already created */
5796 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
5797 result = tb->type.type->data.klass;
5801 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
5802 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
5803 MonoMethodSignature *sig;
5806 if (helper->arguments)
5807 nargs = mono_array_length (helper->arguments);
5811 sig = mono_metadata_signature_alloc (image, nargs);
5812 sig->explicit_this = helper->call_conv & 64;
5813 sig->hasthis = helper->call_conv & 32;
5815 if (helper->call_conv == 0) /* unmanaged */
5816 sig->call_convention = helper->unmanaged_call_conv - 1;
5818 if (helper->call_conv & 0x02)
5819 sig->call_convention = MONO_CALL_VARARG;
5821 sig->call_convention = MONO_CALL_DEFAULT;
5823 sig->param_count = nargs;
5824 /* TODO: Copy type ? */
5825 sig->ret = helper->return_type->type;
5826 for (i = 0; i < nargs; ++i) {
5827 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
5828 sig->params [i] = rt->type;
5834 g_print (obj->vtable->klass->name);
5835 g_assert_not_reached ();