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/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/tokentype.h"
15 #include "mono/metadata/appdomain.h"
16 #include "mono/metadata/opcodes.h"
24 #include "rawbuffer.h"
25 #include "mono-endian.h"
31 #define TEXT_OFFSET 512
32 #define CLI_H_SIZE 136
33 #define FILE_ALIGN 512
34 #define START_TEXT_RVA 0x00002000
37 MonoReflectionILGen *ilgen;
38 MonoReflectionType *rtype;
39 MonoArray *parameters;
44 guint32 *table_idx; /* note: it's a pointer */
48 } ReflectionMethodBuilder;
50 const unsigned char table_sizes [64] = {
60 MONO_INTERFACEIMPL_SIZE,
61 MONO_MEMBERREF_SIZE, /* 0x0A */
63 MONO_CUSTOM_ATTR_SIZE,
64 MONO_FIELD_MARSHAL_SIZE,
65 MONO_DECL_SECURITY_SIZE,
66 MONO_CLASS_LAYOUT_SIZE,
67 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
68 MONO_STAND_ALONE_SIGNATURE_SIZE,
72 MONO_PROPERTY_MAP_SIZE,
75 MONO_METHOD_SEMA_SIZE,
77 MONO_MODULEREF_SIZE, /* 0x1A */
83 MONO_ASSEMBLY_SIZE, /* 0x20 */
84 MONO_ASSEMBLY_PROCESSOR_SIZE,
86 MONO_ASSEMBLYREF_SIZE,
87 MONO_ASSEMBLYREFPROC_SIZE,
88 MONO_ASSEMBLYREFOS_SIZE,
92 MONO_NESTED_CLASS_SIZE,
96 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
97 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
100 alloc_table (MonoDynamicTable *table, guint nrows)
103 g_assert (table->columns);
104 table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
108 string_heap_insert (MonoDynamicStream *sh, const char *str)
112 gpointer oldkey, oldval;
114 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
115 return GPOINTER_TO_UINT (oldval);
117 len = strlen (str) + 1;
119 if (idx + len > sh->alloc_size) {
120 sh->alloc_size += len + 4096;
121 sh->data = g_realloc (sh->data, sh->alloc_size);
124 * We strdup the string even if we already copy them in sh->data
125 * so that the string pointers in the hash remain valid even if
126 * we need to realloc sh->data. We may want to avoid that later.
128 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
129 memcpy (sh->data + idx, str, len);
135 string_heap_init (MonoDynamicStream *sh)
138 sh->alloc_size = 4096;
139 sh->data = g_malloc (4096);
140 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
141 string_heap_insert (sh, "");
144 #if 0 /* never used */
146 string_heap_free (MonoDynamicStream *sh)
149 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
150 g_hash_table_destroy (sh->hash);
155 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
158 if (stream->alloc_size < stream->index + len) {
159 stream->alloc_size += len + 4096;
160 stream->data = g_realloc (stream->data, stream->alloc_size);
162 memcpy (stream->data + stream->index, data, len);
164 stream->index += len;
166 * align index? Not without adding an additional param that controls it since
167 * we may store a blob value in pieces.
173 stream_data_align (MonoDynamicStream *stream)
176 guint32 count = stream->index % 4;
178 /* we assume the stream data will be aligned */
180 mono_image_add_stream_data (stream, buf, 4 - count);
184 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
187 g_assert_not_reached ();
192 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
196 case MONO_TYPE_BOOLEAN:
210 case MONO_TYPE_STRING:
211 case MONO_TYPE_OBJECT:
212 case MONO_TYPE_TYPEDBYREF:
213 mono_metadata_encode_value (type->type, p, &p);
216 case MONO_TYPE_SZARRAY:
217 mono_metadata_encode_value (type->type, p, &p);
218 encode_type (assembly, type->data.type, p, &p);
220 case MONO_TYPE_VALUETYPE:
221 case MONO_TYPE_CLASS:
222 mono_metadata_encode_value (type->type, p, &p);
223 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
225 case MONO_TYPE_ARRAY:
226 mono_metadata_encode_value (type->type, p, &p);
227 encode_type (assembly, type->data.array->type, p, &p);
228 mono_metadata_encode_value (type->data.array->rank, p, &p);
229 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
230 mono_metadata_encode_value (0, p, &p);
233 g_error ("need to encode type %x", type->type);
239 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
242 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
246 encode_type (assembly, type->type, p, endbuf);
250 g_assert_not_reached ();
255 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
260 guint32 nparams = sig->param_count;
261 guint32 size = 10 + nparams * 10;
266 p = buf = g_malloc (size);
268 * FIXME: vararg, explicit_this, differenc call_conv values...
270 *p = sig->call_convention;
272 *p |= 0x20; /* hasthis */
274 mono_metadata_encode_value (nparams, p, &p);
275 encode_type (assembly, sig->ret, p, &p);
276 for (i = 0; i < nparams; ++i)
277 encode_type (assembly, sig->params [i], p, &p);
279 g_assert (p - buf < size);
280 mono_metadata_encode_value (p-buf, b, &b);
281 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
282 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
288 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
291 * FIXME: reuse code from method_encode_signature().
296 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
297 guint32 size = 10 + nparams * 10;
302 p = buf = g_malloc (size);
303 /* LAMESPEC: all the call conv spec is foobared */
304 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
305 if (mb->call_conv & 2)
306 *p |= 0x5; /* vararg */
307 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
308 *p |= 0x20; /* hasthis */
310 mono_metadata_encode_value (nparams, p, &p);
311 encode_reflection_type (assembly, mb->rtype, p, &p);
312 for (i = 0; i < nparams; ++i) {
313 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
314 encode_reflection_type (assembly, pt, p, &p);
317 g_assert (p - buf < size);
318 mono_metadata_encode_value (p-buf, b, &b);
319 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
320 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
326 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
328 MonoDynamicTable *table;
331 guint32 idx, sig_idx, size;
332 guint nl = mono_array_length (ilgen->locals);
339 p = buf = g_malloc (size);
340 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
341 idx = table->next_idx ++;
343 alloc_table (table, table->rows);
344 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
346 mono_metadata_encode_value (0x07, p, &p);
347 mono_metadata_encode_value (nl, p, &p);
348 for (i = 0; i < nl; ++i) {
349 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
350 encode_reflection_type (assembly, lb->type, p, &p);
352 g_assert (p - buf < size);
353 mono_metadata_encode_value (p-buf, b, &b);
354 sig_idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
355 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
358 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
364 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
370 gint32 num_locals = 0;
371 gint32 num_exception = 0;
374 char fat_header [12];
377 guint32 local_sig = 0;
378 guint32 header_size = 12;
381 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
382 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
383 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
384 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
388 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
390 code = mb->ilgen->code;
391 code_size = mb->ilgen->code_len;
392 max_stack = mb->ilgen->max_stack;
393 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
394 if (mb->ilgen->ex_handlers) {
395 MonoILExceptionInfo *ex_info;
396 for (i = 0; i < mono_array_length (mb->ilgen->ex_handlers); ++i) {
397 ex_info = (MonoILExceptionInfo*)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
398 if (ex_info->handlers)
399 num_exception += mono_array_length (ex_info->handlers);
406 code_size = mono_array_length (code);
407 max_stack = 8; /* we probably need to run a verifier on the code... */
410 /* check for exceptions, maxstack, locals */
411 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
413 if (code_size < 64 && !(code_size & 1)) {
414 flags = (code_size << 2) | 0x2;
415 } else if (code_size < 32 && (code_size & 1)) {
416 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
420 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
421 /* add to the fixup todo list */
422 if (mb->ilgen && mb->ilgen->num_token_fixups)
423 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
424 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
425 return assembly->text_rva + idx + CLI_H_SIZE;
429 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
431 * FIXME: need to set also the header size in fat_flags.
432 * (and more sects and init locals flags)
436 fat_flags |= METHOD_HEADER_MORE_SECTS;
437 fat_header [0] = fat_flags;
438 fat_header [1] = (header_size / 4 ) << 4;
439 shortp = (guint16*)(fat_header + 2);
441 intp = (guint32*)(fat_header + 4);
443 intp = (guint32*)(fat_header + 8);
445 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
446 /* add to the fixup todo list */
447 if (mb->ilgen && mb->ilgen->num_token_fixups)
448 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
450 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
452 unsigned char sheader [4];
453 MonoExceptionClause clause;
454 MonoILExceptionInfo * ex_info;
455 MonoILExceptionBlock * ex_block;
458 stream_data_align (&assembly->code);
459 /* always use fat format for now */
460 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
461 num_exception *= sizeof (MonoExceptionClause);
462 sheader [1] = num_exception & 0xff;
463 sheader [2] = (num_exception >> 8) & 0xff;
464 sheader [3] = (num_exception >> 16) & 0xff;
465 mono_image_add_stream_data (&assembly->code, sheader, 4);
466 /* fat header, so we are already aligned */
468 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
469 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
470 if (ex_info->handlers) {
471 int finally_start = 0;
472 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
473 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
474 clause.flags = ex_block->type;
475 clause.try_offset = ex_info->start;
476 /* need fault, too, probably */
477 if (clause.flags == MONO_EXCEPTION_CLAUSE_FINALLY)
478 clause.try_len = finally_start - ex_info->start;
480 clause.try_len = ex_info->len;
481 clause.handler_offset = ex_block->start;
482 clause.handler_len = ex_block->len;
483 finally_start = clause.handler_offset + clause.handler_len;
484 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
485 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
486 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d\n",
487 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len);*/
488 /* FIXME: ENOENDIAN */
489 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
492 g_error ("No clauses for ex info block %d", i);
496 return assembly->text_rva + idx + CLI_H_SIZE;
500 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 token)
503 MonoDynamicTable *table;
506 table = &assembly->tables [table_idx];
508 g_assert (col < table->columns);
510 values = table->values + table->columns;
511 for (i = 1; i <= table->rows; ++i) {
512 if (values [col] == token)
519 * idx is the table index of the object
520 * type is one of CUSTOM_ATTR_*
523 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
525 MonoDynamicTable *table;
526 MonoReflectionCustomAttr *cattr;
528 guint32 count, i, token;
532 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
535 count = mono_array_length (cattrs);
536 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
537 table->rows += count;
538 alloc_table (table, table->rows);
539 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
540 idx <<= CUSTOM_ATTR_BITS;
542 for (i = 0; i < count; ++i) {
543 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
544 values [MONO_CUSTOM_ATTR_PARENT] = idx;
545 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
546 type = mono_metadata_token_index (token);
547 type <<= CUSTOM_ATTR_TYPE_BITS;
548 switch (mono_metadata_token_table (token)) {
549 case MONO_TABLE_METHOD:
550 type |= CUSTOM_ATTR_TYPE_METHODDEF;
552 case MONO_TABLE_MEMBERREF:
553 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
556 g_error ("got wrong token in custom attr");
558 values [MONO_CUSTOM_ATTR_TYPE] = type;
560 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
561 values [MONO_CUSTOM_ATTR_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, p - blob_size);
562 mono_image_add_stream_data (&assembly->blob,
563 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
564 values += MONO_CUSTOM_ATTR_SIZE;
570 * Fill in the MethodDef and ParamDef tables for a method.
571 * This is used for both normal methods and constructors.
574 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
576 MonoDynamicTable *table;
581 /* room in this table is already allocated */
582 table = &assembly->tables [MONO_TABLE_METHOD];
583 *mb->table_idx = table->next_idx ++;
584 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
586 name = mono_string_to_utf8 (mb->name);
587 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
589 } else { /* a constructor */
590 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
592 values [MONO_METHOD_FLAGS] = mb->attrs;
593 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
594 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
595 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
597 table = &assembly->tables [MONO_TABLE_PARAM];
598 values [MONO_METHOD_PARAMLIST] = table->next_idx;
602 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
603 if (mono_array_get (mb->pinfo, gpointer, i))
606 table->rows += count;
607 alloc_table (table, table->rows);
608 values = table->values + table->next_idx * MONO_PARAM_SIZE;
609 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
610 MonoReflectionParamBuilder *pb;
611 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
612 values [MONO_PARAM_FLAGS] = pb->attrs;
613 values [MONO_PARAM_SEQUENCE] = i;
614 name = mono_string_to_utf8 (pb->name);
615 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
617 values += MONO_PARAM_SIZE;
619 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
626 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
628 MonoDynamicTable *table;
631 ReflectionMethodBuilder rmb;
633 rmb.ilgen = mb->ilgen;
634 rmb.rtype = mb->rtype;
635 rmb.parameters = mb->parameters;
636 rmb.pinfo = mb->pinfo;
637 rmb.attrs = mb->attrs;
638 rmb.iattrs = mb->iattrs;
639 rmb.call_conv = mb->call_conv;
643 rmb.table_idx = &mb->table_idx;
645 mono_image_basic_method (&rmb, assembly);
647 if (mb->dll) { /* It's a P/Invoke method */
649 table = &assembly->tables [MONO_TABLE_IMPLMAP];
651 alloc_table (table, table->rows);
652 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
653 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
654 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
655 name = mono_string_to_utf8 (mb->dllentry);
656 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
658 name = mono_string_to_utf8 (mb->dll);
659 moduleref = string_heap_insert (&assembly->sheap, name);
661 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
662 table = &assembly->tables [MONO_TABLE_MODULEREF];
664 alloc_table (table, table->rows);
665 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
666 values [MONO_IMPLMAP_SCOPE] = table->rows;
669 if (mb->override_method) {
670 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
671 table = &assembly->tables [MONO_TABLE_METHODIMPL];
673 alloc_table (table, table->rows);
674 values = table->values + table->rows * MONO_MTHODIMPL_SIZE;
675 values [MONO_MTHODIMPL_CLASS] = tb->table_idx;
676 values [MONO_MTHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
677 if (mb->override_method->method)
678 values [MONO_MTHODIMPL_DECLARATION] = mono_image_get_methodref_token (assembly, mb->override_method->method);
680 MonoReflectionMethodBuilder *omb = (MonoReflectionMethodBuilder*)mb->override_method;
681 values [MONO_MTHODIMPL_DECLARATION] = METHODDEFORREF_METHODDEF | (omb->table_idx << METHODDEFORREF_BITS);
684 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
688 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
690 ReflectionMethodBuilder rmb;
692 rmb.ilgen = mb->ilgen;
693 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
694 rmb.parameters = mb->parameters;
695 rmb.pinfo = mb->pinfo;
696 rmb.attrs = mb->attrs;
697 rmb.iattrs = mb->iattrs;
698 rmb.call_conv = mb->call_conv;
702 rmb.table_idx = &mb->table_idx;
704 mono_image_basic_method (&rmb, assembly);
705 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
710 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
718 p = buf = g_malloc (64);
720 /* No start code with field refs...
721 * mono_metadata_encode_value (0x06, p, &p);
723 /* encode custom attributes before the type */
724 encode_type (assembly, field->type, p, &p);
725 g_assert (p-buf < 64);
726 mono_metadata_encode_value (p-buf, b, &b);
727 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
728 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
734 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
742 p = buf = g_malloc (64);
744 mono_metadata_encode_value (0x06, p, &p);
745 /* encode custom attributes before the type */
746 encode_reflection_type (assembly, fb->type, p, &p);
747 g_assert (p-buf < 64);
748 mono_metadata_encode_value (p-buf, b, &b);
749 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
750 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
756 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
763 p = buf = g_malloc (64);
765 box_val = ((char*)val) + sizeof (MonoObject);
766 *ret_type = val->vtable->klass->byval_arg.type;
769 case MONO_TYPE_BOOLEAN:
789 case MONO_TYPE_VALUETYPE:
790 if (val->vtable->klass->enumtype) {
791 *ret_type = val->vtable->klass->enum_basetype->type;
794 g_error ("we can't encode valuetypes");
795 case MONO_TYPE_STRING: {
796 MonoString *str = (MonoString*)val;
797 /* there is no signature */
798 len = str->length * 2;
799 mono_metadata_encode_value (len, b, &b);
800 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
801 /* FIXME: ENOENDIAN */
802 mono_image_add_stream_data (&assembly->blob, (const char*)mono_string_chars (str), len);
808 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
811 /* there is no signature */
812 mono_metadata_encode_value (len, b, &b);
813 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
814 /* FIXME: ENOENDIAN */
815 mono_image_add_stream_data (&assembly->blob, box_val, len);
822 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
824 MonoDynamicTable *table;
828 /* maybe this fixup should be done in the C# code */
829 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
830 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
831 table = &assembly->tables [MONO_TABLE_FIELD];
832 fb->table_idx = table->next_idx ++;
833 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
834 name = mono_string_to_utf8 (fb->name);
835 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
837 values [MONO_FIELD_FLAGS] = fb->attrs;
838 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
840 if (fb->offset != -1) {
841 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
843 alloc_table (table, table->rows);
844 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
845 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
846 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
848 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
849 guint32 field_type = 0;
850 table = &assembly->tables [MONO_TABLE_CONSTANT];
852 alloc_table (table, table->rows);
853 values = table->values + table->rows * MONO_CONSTANT_SIZE;
854 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
855 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
856 values [MONO_CONSTANT_TYPE] = field_type;
857 values [MONO_CONSTANT_PADDING] = 0;
861 table = &assembly->tables [MONO_TABLE_FIELDRVA];
863 alloc_table (table, table->rows);
864 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
865 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
867 * We store it in the code section because it's simpler for now.
869 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
870 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva + CLI_H_SIZE;
872 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
876 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
882 MonoReflectionMethodBuilder *mb = fb->get_method;
883 guint32 idx, i, size;
885 if (mb && mb->parameters)
886 nparams = mono_array_length (mb->parameters);
887 size = 24 + nparams * 10;
888 buf = p = g_malloc (size);
891 mono_metadata_encode_value (nparams, p, &p);
893 encode_reflection_type (assembly, mb->rtype, p, &p);
894 for (i = 0; i < nparams; ++i) {
895 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
896 encode_reflection_type (assembly, pt, p, &p);
899 *p++ = 1; /* void: a property should probably not be allowed without a getter */
902 g_assert (p - buf < size);
903 mono_metadata_encode_value (p-buf, b, &b);
904 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
905 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
911 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
913 MonoDynamicTable *table;
916 guint num_methods = 0;
920 * we need to set things in the following tables:
921 * PROPERTYMAP (info already filled in _get_type_info ())
922 * PROPERTY (rows already preallocated in _get_type_info ())
923 * METHOD (method info already done with the generic method code)
926 table = &assembly->tables [MONO_TABLE_PROPERTY];
927 pb->table_idx = table->next_idx ++;
928 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
929 name = mono_string_to_utf8 (pb->name);
930 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
932 values [MONO_PROPERTY_FLAGS] = pb->attrs;
933 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
935 /* FIXME: we still don't handle 'other' methods */
936 if (pb->get_method) num_methods ++;
937 if (pb->set_method) num_methods ++;
939 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
940 table->rows += num_methods;
941 alloc_table (table, table->rows);
943 if (pb->get_method) {
944 semaidx = table->next_idx ++;
945 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
946 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
947 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
948 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
950 if (pb->set_method) {
951 semaidx = table->next_idx ++;
952 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
953 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
954 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
955 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
957 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
961 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
963 MonoDynamicTable *table;
966 guint num_methods = 0;
970 * we need to set things in the following tables:
971 * EVENTMAP (info already filled in _get_type_info ())
972 * EVENT (rows already preallocated in _get_type_info ())
973 * METHOD (method info already done with the generic method code)
976 table = &assembly->tables [MONO_TABLE_EVENT];
977 eb->table_idx = table->next_idx ++;
978 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
979 name = mono_string_to_utf8 (eb->name);
980 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
982 values [MONO_EVENT_FLAGS] = eb->attrs;
983 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
986 * FIXME: we still don't handle 'other' methods
988 if (eb->add_method) num_methods ++;
989 if (eb->remove_method) num_methods ++;
990 if (eb->raise_method) num_methods ++;
992 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
993 table->rows += num_methods;
994 alloc_table (table, table->rows);
996 if (eb->add_method) {
997 semaidx = table->next_idx ++;
998 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
999 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1000 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1001 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1003 if (eb->remove_method) {
1004 semaidx = table->next_idx ++;
1005 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1006 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1007 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1008 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1010 if (eb->raise_method) {
1011 semaidx = table->next_idx ++;
1012 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1013 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1014 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1015 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1017 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1021 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
1023 MonoDynamicTable *table;
1026 guint32 cols [MONO_ASSEMBLY_SIZE];
1028 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1031 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1033 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1034 token = table->next_idx ++;
1036 alloc_table (table, table->rows);
1037 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1038 if (strcmp ("corlib", image->assembly_name) == 0)
1039 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1041 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1042 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1043 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1044 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1045 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1046 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1047 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1048 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1049 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1051 token <<= RESOLTION_SCOPE_BITS;
1052 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1053 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1058 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1060 MonoDynamicTable *table;
1066 char *b = blob_size;
1068 switch (type->type) {
1069 case MONO_TYPE_FNPTR:
1071 case MONO_TYPE_SZARRAY:
1072 case MONO_TYPE_ARRAY:
1073 encode_type (assembly, type, p, &p);
1079 g_assert (p-sig < 128);
1080 mono_metadata_encode_value (p-sig, b, &b);
1081 token = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1082 mono_image_add_stream_data (&assembly->blob, sig, p-sig);
1084 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1085 alloc_table (table, table->rows + 1);
1086 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1087 values [MONO_TYPESPEC_SIGNATURE] = token;
1089 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1090 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1096 * Despite the name, we handle also TypeSpec (with the above helper).
1099 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1101 MonoDynamicTable *table;
1106 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1109 token = create_typespec (assembly, type);
1112 klass = mono_class_from_mono_type (type);
1114 * If it's in the same module:
1116 if (klass->image == assembly->assembly.image) {
1117 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1118 return TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1121 table = &assembly->tables [MONO_TABLE_TYPEREF];
1122 alloc_table (table, table->rows + 1);
1123 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1124 values [MONO_TYPEREF_SCOPE] = resolution_scope_from_image (assembly, klass->image);
1125 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1126 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1127 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1128 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1134 * Insert a memberef row into the metadata: the token that point to the memberref
1135 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1136 * mono_image_get_fieldref_token()).
1137 * The sig param is an index to an already built signature.
1140 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoClass *klass, const char *name, guint32 sig)
1142 MonoDynamicTable *table;
1144 guint32 token, pclass;
1147 parent = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1148 switch (parent & TYPEDEFORREF_MASK) {
1149 case TYPEDEFORREF_TYPEREF:
1150 pclass = MEMBERREF_PARENT_TYPEREF;
1152 case TYPEDEFORREF_TYPESPEC:
1153 pclass = MEMBERREF_PARENT_TYPESPEC;
1155 case TYPEDEFORREF_TYPEDEF:
1156 /* should never get here */
1158 g_error ("unknow typeref or def token");
1160 /* extract the index */
1161 parent >>= TYPEDEFORREF_BITS;
1163 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1164 alloc_table (table, table->rows + 1);
1165 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1166 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1167 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1168 values [MONO_MEMBERREF_SIGNATURE] = sig;
1169 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1176 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1180 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1183 token = mono_image_get_memberref_token (assembly, method->klass,
1184 method->name, method_encode_signature (assembly, method->signature));
1185 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1190 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1194 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1197 token = mono_image_get_memberref_token (assembly, klass,
1198 field->name, fieldref_encode_signature (assembly, field));
1199 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1204 * Insert into the metadata tables all the info about the TypeBuilder tb.
1205 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1208 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1210 MonoDynamicTable *table;
1215 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1216 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1217 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1218 if (tb->parent) { /* interfaces don't have a parent */
1219 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1221 values [MONO_TYPEDEF_EXTENDS] = 0;
1222 n = mono_string_to_utf8 (tb->name);
1223 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1225 n = mono_string_to_utf8 (tb->nspace);
1226 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1228 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1229 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1232 * if we have explicitlayout or sequentiallayouts, output data in the
1233 * ClassLayout table.
1235 if ((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1236 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1238 alloc_table (table, table->rows);
1239 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1240 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1241 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1242 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1245 /* handle interfaces */
1246 if (tb->interfaces) {
1247 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1249 table->rows += mono_array_length (tb->interfaces);
1250 alloc_table (table, table->rows);
1251 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1252 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1253 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1254 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1255 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1256 values += MONO_INTERFACEIMPL_SIZE;
1262 table = &assembly->tables [MONO_TABLE_FIELD];
1263 table->rows += mono_array_length (tb->fields);
1264 alloc_table (table, table->rows);
1265 for (i = 0; i < mono_array_length (tb->fields); ++i)
1266 mono_image_get_field_info (
1267 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1270 /* handle constructors */
1272 table = &assembly->tables [MONO_TABLE_METHOD];
1273 table->rows += mono_array_length (tb->ctors);
1274 alloc_table (table, table->rows);
1275 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1276 mono_image_get_ctor_info (domain,
1277 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1280 /* handle methods */
1282 table = &assembly->tables [MONO_TABLE_METHOD];
1283 table->rows += mono_array_length (tb->methods);
1284 alloc_table (table, table->rows);
1285 for (i = 0; i < mono_array_length (tb->methods); ++i)
1286 mono_image_get_method_info (
1287 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1290 /* Do the same with properties etc.. */
1292 * FIXME: note that the methodsemantics table needs to be sorted, so events
1293 * go before properties; not sure if this is enough...
1295 if (tb->events && mono_array_length (tb->events)) {
1296 table = &assembly->tables [MONO_TABLE_EVENT];
1297 table->rows += mono_array_length (tb->events);
1298 alloc_table (table, table->rows);
1299 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1301 alloc_table (table, table->rows);
1302 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1303 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1304 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1305 for (i = 0; i < mono_array_length (tb->events); ++i)
1306 mono_image_get_event_info (
1307 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1309 if (tb->properties && mono_array_length (tb->properties)) {
1310 table = &assembly->tables [MONO_TABLE_PROPERTY];
1311 table->rows += mono_array_length (tb->properties);
1312 alloc_table (table, table->rows);
1313 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1315 alloc_table (table, table->rows);
1316 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1317 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1318 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1319 for (i = 0; i < mono_array_length (tb->properties); ++i)
1320 mono_image_get_property_info (
1321 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1324 MonoDynamicTable *ntable;
1326 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1327 table->rows += mono_array_length (tb->subtypes);
1328 alloc_table (table, table->rows);
1330 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1331 ntable->rows += mono_array_length (tb->subtypes);
1332 alloc_table (ntable, ntable->rows);
1333 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1335 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1336 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1338 mono_image_get_type_info (domain, subtype, assembly);
1339 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1340 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1341 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1342 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1343 mono_string_to_utf8 (tb->name), tb->table_idx,
1344 ntable->next_idx, ntable->rows);*/
1345 values += MONO_NESTED_CLASS_SIZE;
1349 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1353 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1355 MonoDynamicTable *table;
1359 table = &assembly->tables [MONO_TABLE_MODULE];
1360 mb->table_idx = table->next_idx ++;
1361 name = mono_string_to_utf8 (mb->module.name);
1362 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1364 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1367 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1368 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1369 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1371 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1373 * fill-in info in other tables as well.
1375 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1376 table->rows += mono_array_length (mb->types);
1377 alloc_table (table, table->rows);
1379 * We assign here the typedef indexes to avoid mismatches if a type that
1380 * has not yet been stored in the tables is referenced by another type.
1382 for (i = 0; i < mono_array_length (mb->types); ++i) {
1384 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1385 type->table_idx = table->next_idx ++;
1386 if (!type->subtypes)
1388 for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1389 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1390 subtype->table_idx = table->next_idx ++;
1393 for (i = 0; i < mono_array_length (mb->types); ++i)
1394 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1397 #define align_pointer(base,p)\
1399 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1401 (p) += 4 - (__diff & 3);\
1405 * build_compressed_metadata() fills in the blob of data that represents the
1406 * raw metadata as it will be saved in the PE file. The five streams are output
1407 * and the metadata tables are comnpressed from the guint32 array representation,
1408 * to the compressed on-disk format.
1411 build_compressed_metadata (MonoDynamicAssembly *assembly)
1414 guint64 valid_mask = 0;
1415 guint64 sorted_mask;
1416 guint32 heapt_size = 0;
1417 guint32 meta_size = 256; /* allow for header and other stuff */
1418 guint32 table_offset;
1419 guint32 ntables = 0;
1425 const char *version = "mono" VERSION;
1428 MonoDynamicStream *stream;
1429 } stream_desc [] = {
1430 {"#~", &assembly->tstream},
1431 {"#Strings", &assembly->sheap},
1432 {"#US", &assembly->us},
1433 {"#Blob", &assembly->blob},
1434 {"#GUID", &assembly->guid},
1437 /* tables that are sorted */
1438 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
1439 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
1440 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
1441 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
1442 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
1443 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
1445 /* Compute table sizes */
1446 /* the MonoImage has already been created in mono_image_basic_init() */
1447 meta = assembly->assembly.image;
1449 /* Setup the info used by compute_sizes () */
1450 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1451 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1452 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1454 meta_size += assembly->blob.index;
1455 meta_size += assembly->guid.index;
1456 meta_size += assembly->sheap.index;
1457 meta_size += assembly->us.index;
1459 for (i=0; i < 64; ++i)
1460 meta->tables [i].rows = assembly->tables [i].rows;
1462 for (i = 0; i < 64; i++){
1463 if (meta->tables [i].rows == 0)
1465 valid_mask |= (guint64)1 << i;
1467 meta->tables [i].row_size = mono_metadata_compute_size (
1468 meta, i, &meta->tables [i].size_bitfield);
1469 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1471 heapt_size += 24; /* #~ header size */
1472 heapt_size += ntables * 4;
1473 meta_size += heapt_size;
1474 meta->raw_metadata = g_malloc0 (meta_size);
1475 p = meta->raw_metadata;
1476 /* the metadata signature */
1477 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1478 /* version numbers and 4 bytes reserved */
1479 int16val = (guint16*)p;
1483 /* version string */
1484 int32val = (guint32*)p;
1485 *int32val = strlen (version);
1487 memcpy (p, version, *int32val);
1489 align_pointer (meta->raw_metadata, p);
1490 int16val = (guint16*)p;
1491 *int16val++ = 0; /* flags must be 0 */
1492 *int16val = 5; /* number of streams */
1496 * write the stream info.
1498 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1499 table_offset += 3; table_offset &= ~3;
1501 assembly->tstream.index = heapt_size;
1502 for (i = 0; i < 5; ++i) {
1503 int32val = (guint32*)p;
1504 *int32val++ = stream_desc [i].stream->offset = table_offset;
1505 *int32val = stream_desc [i].stream->index;
1506 table_offset += *int32val;
1507 table_offset += 3; table_offset &= ~3;
1509 strcpy (p, stream_desc [i].name);
1510 p += strlen (stream_desc [i].name) + 1;
1511 align_pointer (meta->raw_metadata, p);
1514 * now copy the data, the table stream header and contents goes first.
1516 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1517 p = meta->raw_metadata + assembly->tstream.offset;
1518 int32val = (guint32*)p;
1519 *int32val = 0; /* reserved */
1521 *p++ = 1; /* version */
1523 if (meta->idx_string_wide)
1525 if (meta->idx_guid_wide)
1527 if (meta->idx_blob_wide)
1530 *p++ = 0; /* reserved */
1531 int64val = (guint64*)p;
1532 *int64val++ = valid_mask;
1533 *int64val++ = valid_mask & sorted_mask; /* bitvector of sorted tables */
1535 int32val = (guint32*)p;
1536 for (i = 0; i < 64; i++){
1537 if (meta->tables [i].rows == 0)
1539 *int32val++ = meta->tables [i].rows;
1541 p = (unsigned char*)int32val;
1542 /* compress the tables */
1543 for (i = 0; i < 64; i++){
1546 guint32 bitfield = meta->tables [i].size_bitfield;
1547 if (!meta->tables [i].rows)
1549 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1550 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1551 meta->tables [i].base = p;
1552 for (row = 1; row <= meta->tables [i].rows; ++row) {
1553 values = assembly->tables [i].values + row * assembly->tables [i].columns;
1554 for (col = 0; col < assembly->tables [i].columns; ++col) {
1555 switch (mono_metadata_table_size (bitfield, col)) {
1557 *p++ = values [col];
1560 int16val = (guint16*)p;
1561 *int16val = values [col];
1565 int32val = (guint32*)p;
1566 *int32val = values [col];
1570 g_assert_not_reached ();
1574 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1577 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1578 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1579 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1580 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1581 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1583 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1587 * Some tables in metadata need to be sorted according to some criteria, but
1588 * when methods and fields are first created with reflection, they may be assigned a token
1589 * that doesn't correspond to the final token they will get assigned after the sorting.
1590 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
1591 * with the reflection objects that represent them. Once all the tables are set up, the
1592 * reflection objects will contains the correct table index. fixup_method() will fixup the
1593 * tokens for the method with ILGenerator @ilgen.
1596 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
1597 guint32 code_idx = GPOINTER_TO_UINT (value);
1598 MonoReflectionILTokenInfo *iltoken;
1599 MonoReflectionFieldBuilder *field;
1600 MonoReflectionCtorBuilder *ctor;
1601 MonoReflectionMethodBuilder *method;
1603 unsigned char *target;
1605 for (i = 0; i < ilgen->num_token_fixups; ++i) {
1606 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
1607 target = assembly->code.data + code_idx + iltoken->code_pos;
1608 switch (target [3]) {
1609 case MONO_TABLE_FIELD:
1610 if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
1611 g_assert_not_reached ();
1612 field = (MonoReflectionFieldBuilder *)iltoken->member;
1613 idx = field->table_idx;
1615 case MONO_TABLE_METHOD:
1616 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1617 method = (MonoReflectionMethodBuilder *)iltoken->member;
1618 idx = method->table_idx;
1619 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1620 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
1621 idx = ctor->table_idx;
1623 g_assert_not_reached ();
1627 g_error ("got unexpected table 0x%02x in fixup", target [3]);
1629 target [0] = idx & 0xff;
1630 target [1] = (idx >> 8) & 0xff;
1631 target [2] = (idx >> 16) & 0xff;
1636 * mono_image_build_metadata() will fill the info in all the needed metadata tables
1637 * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
1638 * and recursively outputs the info for a module. Each module will output all the info
1639 * about it's types etc.
1640 * At the end of the process, method and field tokens are fixed up and the on-disk
1641 * compressed metadata representation is created.
1644 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
1646 MonoDynamicTable *table;
1647 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
1648 MonoDomain *domain = ((MonoObject *)assemblyb)->vtable->domain;
1654 assembly->text_rva = START_TEXT_RVA;
1656 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
1657 alloc_table (table, 1);
1658 values = table->values + MONO_ASSEMBLY_SIZE;
1659 values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
1660 name = mono_string_to_utf8 (assemblyb->name);
1661 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
1663 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
1664 values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
1665 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1666 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1667 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1668 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1669 values [MONO_ASSEMBLY_FLAGS] = 0;
1671 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
1673 assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
1674 assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
1676 if (assemblyb->modules) {
1677 len = mono_array_length (assemblyb->modules);
1678 table = &assembly->tables [MONO_TABLE_MODULE];
1679 alloc_table (table, len);
1680 for (i = 0; i < len; ++i)
1681 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
1683 table = &assembly->tables [MONO_TABLE_MODULE];
1685 alloc_table (table, table->rows);
1686 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
1690 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1692 * table->rows is already set above and in mono_image_fill_module_table.
1694 alloc_table (table, table->rows);
1696 * Set the first entry.
1698 values = table->values + table->columns;
1699 values [MONO_TYPEDEF_FLAGS] = 0;
1700 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
1701 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
1702 values [MONO_TYPEDEF_EXTENDS] = 0;
1703 values [MONO_TYPEDEF_FIELD_LIST] = 1;
1704 values [MONO_TYPEDEF_METHOD_LIST] = 1;
1707 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
1709 build_compressed_metadata (assembly);
1713 * mono_image_insert_string:
1714 * @assembly: assembly builder object
1717 * Insert @str into the user string stream of @assembly.
1720 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
1726 if (!assembly->dynamic_assembly)
1727 mono_image_basic_init (assembly);
1728 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
1729 idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
1730 /* FIXME: ENOENDIAN */
1731 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
1732 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
1733 return MONO_TOKEN_STRING | idx;
1737 * mono_image_create_token:
1738 * @assembly: a dynamic assembly
1741 * Get a token to insert in the IL code stream for the given MemberInfo.
1742 * @obj can be one of:
1743 * ConstructorBuilder
1753 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
1759 g_error ("System.Array methods not yet supported");
1761 klass = obj->vtable->klass;
1762 if (strcmp (klass->name, "MethodBuilder") == 0) {
1763 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
1764 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1765 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1768 if (strcmp (klass->name, "ConstructorBuilder") == 0) {
1769 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
1770 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1771 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1774 if (strcmp (klass->name, "FieldBuilder") == 0) {
1775 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
1776 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
1778 if (strcmp (klass->name, "TypeBuilder") == 0) {
1779 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
1780 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
1782 if (strcmp (klass->name, "MonoType") == 0) {
1783 MonoReflectionType *tb = (MonoReflectionType *)obj;
1784 return mono_metadata_token_from_dor (
1785 mono_image_typedef_or_ref (assembly, tb->type));
1787 if (strcmp (klass->name, "MonoCMethod") == 0 ||
1788 strcmp (klass->name, "MonoMethod") == 0) {
1789 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
1790 token = mono_image_get_methodref_token (assembly, m->method);
1791 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1794 if (strcmp (klass->name, "MonoField") == 0) {
1795 MonoReflectionField *f = (MonoReflectionField *)obj;
1796 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
1797 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1800 g_print ("requested token for %s\n", klass->name);
1805 * mono_image_basic_ini:
1806 * @assembly: an assembly builder object
1808 * Create the MonoImage that represents the assembly builder and setup some
1809 * of the helper hash table and the basic metadata streams.
1812 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1814 MonoDynamicAssembly *assembly;
1818 if (assemblyb->dynamic_assembly)
1822 assembly = assemblyb->dynamic_assembly = GC_malloc (sizeof (MonoDynamicAssembly));
1824 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1827 assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
1828 assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
1829 assembly->typeref = g_hash_table_new (mono_metadata_type_hash, mono_metadata_type_equal);
1831 string_heap_init (&assembly->sheap);
1832 mono_image_add_stream_data (&assembly->us, "", 1);
1833 mono_image_add_stream_data (&assembly->blob, "", 1);
1835 for (i=0; i < 64; ++i) {
1836 assembly->tables [i].next_idx = 1;
1837 assembly->tables [i].columns = table_sizes [i];
1840 image = g_new0 (MonoImage, 1);
1842 /* keep in sync with image.c */
1843 image->name = mono_string_to_utf8 (assemblyb->name);
1844 image->assembly_name = image->name; /* they may be different */
1846 image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
1847 image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
1848 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
1849 image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
1851 assembly->assembly.image = image;
1856 * mono_image_get_heade:
1857 * @assemblyb: an assembly builder object
1861 * When we need to save an assembly, we first call this function that ensures the metadata
1862 * tables are built for all the modules in the assembly. This function creates the PE-COFF
1863 * header, the image sections, the CLI header etc. The header is written in @buffer
1864 * and the length of the data written is returned.
1865 * If @buffer is not big enough (@maxsize), -1 is returned.
1868 mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, int maxsize)
1870 MonoMSDOSHeader *msdos;
1871 MonoDotNetHeader *header;
1872 MonoSectionTable *section;
1873 MonoCLIHeader *cli_header;
1874 guint32 header_size = TEXT_OFFSET + CLI_H_SIZE;
1875 MonoDynamicAssembly *assembly;
1877 static const unsigned char msheader[] = {
1878 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
1879 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
1882 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
1883 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
1884 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
1885 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1888 if (maxsize < header_size)
1891 mono_image_basic_init (assemblyb);
1892 assembly = assemblyb->dynamic_assembly;
1894 mono_image_build_metadata (assemblyb);
1896 memset (buffer, 0, header_size);
1897 memcpy (buffer, msheader, sizeof (MonoMSDOSHeader));
1899 msdos = (MonoMSDOSHeader *)buffer;
1900 header = (MonoDotNetHeader *)(buffer + sizeof (MonoMSDOSHeader));
1901 section = (MonoSectionTable*) (buffer + sizeof (MonoMSDOSHeader) + sizeof (MonoDotNetHeader));
1903 /* FIXME: ENDIAN problem: byteswap as needed */
1904 msdos->pe_offset = sizeof (MonoMSDOSHeader);
1906 header->pesig [0] = 'P';
1907 header->pesig [1] = 'E';
1908 header->pesig [2] = header->pesig [3] = 0;
1910 header->coff.coff_machine = 0x14c;
1911 header->coff.coff_sections = 1; /* only .text supported now */
1912 header->coff.coff_time = time (NULL);
1913 header->coff.coff_opt_header_size = sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4;
1915 header->coff.coff_attributes = 0x010e;
1917 //header->coff.coff_attributes = 0x210e;
1918 header->pe.pe_magic = 0x10B;
1919 header->pe.pe_major = 6;
1920 header->pe.pe_minor = 0;
1921 /* need to set: pe_code_size pe_data_size pe_rva_entry_point pe_rva_code_base pe_rva_data_base */
1923 header->nt.pe_image_base = 0x400000;
1924 header->nt.pe_section_align = 8192;
1925 header->nt.pe_file_alignment = FILE_ALIGN;
1926 header->nt.pe_os_major = 4;
1927 header->nt.pe_os_minor = 0;
1928 header->nt.pe_subsys_major = 4;
1929 /* need to set pe_image_size, pe_header_size */
1930 header->nt.pe_header_size = 0x200;
1931 header->nt.pe_image_size = 0x00008000;
1932 header->nt.pe_subsys_required = 3; /* 3 -> cmdline app, 2 -> GUI app */
1933 header->nt.pe_stack_reserve = 0x00100000;
1934 header->nt.pe_stack_commit = 0x00001000;
1935 header->nt.pe_heap_reserve = 0x00100000;
1936 header->nt.pe_heap_commit = 0x00001000;
1937 header->nt.pe_loader_flags = 0;
1938 header->nt.pe_data_dir_count = 16;
1942 header->datadir.pe_import_table
1947 header->datadir.pe_cli_header.size = 72;
1948 header->datadir.pe_cli_header.rva = assembly->text_rva; /* we put it always at the beginning */
1950 /* Write section tables */
1951 strcpy (section->st_name, ".text");
1952 section->st_virtual_address = START_TEXT_RVA;
1953 section->st_virtual_size = assembly->meta_size + assembly->code.index;
1954 section->st_raw_data_size = section->st_virtual_size + (FILE_ALIGN - 1);
1955 section->st_raw_data_size &= ~(FILE_ALIGN - 1);
1956 section->st_raw_data_ptr = TEXT_OFFSET;
1957 section->st_flags = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
1960 * align: build_compressed_metadata () assumes metadata is aligned
1962 * cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1964 assembly->code.index += 3;
1965 assembly->code.index &= ~3;
1968 * Write the MonoCLIHeader header
1970 cli_header = (MonoCLIHeader*)(buffer + TEXT_OFFSET);
1971 cli_header->ch_size = 72;
1972 cli_header->ch_runtime_major = 2;
1973 cli_header->ch_flags = CLI_FLAGS_ILONLY;
1974 if (assemblyb->entry_point)
1975 cli_header->ch_entry_point = assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF;
1977 cli_header->ch_entry_point = 0;
1978 cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1979 cli_header->ch_metadata.size = assembly->meta_size;
1985 * We need to return always the same object for MethodInfo, FieldInfo etc..
1986 * type uses a different hash, since it uses custom hash/equal functions.
1988 static MonoGHashTable *object_cache = NULL;
1989 static MonoGHashTable *type_cache = NULL;
1991 #define CHECK_OBJECT(t,p) \
1994 if (!object_cache) \
1995 object_cache = mono_g_hash_table_new (g_direct_hash, g_direct_equal); \
1996 if ((_obj = mono_g_hash_table_lookup (object_cache, (p)))) \
2000 #define CACHE_OBJECT(p,o) \
2002 mono_g_hash_table_insert (object_cache, p,o); \
2006 * mono_assembly_get_object:
2007 * @domain: an app domain
2008 * @assembly: an assembly
2010 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
2012 MonoReflectionAssembly*
2013 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
2015 static MonoClass *System_Reflection_Assembly;
2016 MonoReflectionAssembly *res;
2018 CHECK_OBJECT (MonoReflectionAssembly *, assembly);
2019 if (!System_Reflection_Assembly)
2020 System_Reflection_Assembly = mono_class_from_name (
2021 mono_defaults.corlib, "System.Reflection", "Assembly");
2022 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
2023 res->assembly = assembly;
2024 CACHE_OBJECT (assembly, res);
2029 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
2031 if ((t1->type != t2->type) ||
2032 (t1->byref != t2->byref))
2036 case MONO_TYPE_VOID:
2037 case MONO_TYPE_BOOLEAN:
2038 case MONO_TYPE_CHAR:
2049 case MONO_TYPE_STRING:
2052 case MONO_TYPE_OBJECT:
2054 case MONO_TYPE_VALUETYPE:
2055 case MONO_TYPE_CLASS:
2056 return t1->data.klass == t2->data.klass;
2058 case MONO_TYPE_SZARRAY:
2059 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
2060 case MONO_TYPE_ARRAY:
2061 if (t1->data.array->rank != t2->data.array->rank)
2063 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
2065 g_error ("implement type compare for %0x!", t1->type);
2073 mymono_metadata_type_hash (MonoType *t1)
2079 hash |= t1->byref << 6; /* do not collide with t1->type values */
2081 case MONO_TYPE_VALUETYPE:
2082 case MONO_TYPE_CLASS:
2083 /* check if the distribution is good enough */
2084 return hash << 7 | g_str_hash (t1->data.klass->name);
2086 case MONO_TYPE_SZARRAY:
2087 return hash << 7 | mymono_metadata_type_hash (t1->data.type);
2093 * mono_type_get_object:
2094 * @domain: an app domain
2097 * Return an System.MonoType object representing the type @type.
2100 mono_type_get_object (MonoDomain *domain, MonoType *type)
2102 MonoReflectionType *res;
2103 MonoClass *klass = mono_class_from_mono_type (type);
2106 type_cache = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
2107 (GCompareFunc)mymono_metadata_type_equal);
2108 if ((res = mono_g_hash_table_lookup (type_cache, type)))
2110 if (klass->reflection_info) {
2111 /* should this be considered an error condition? */
2113 return klass->reflection_info;
2115 mono_class_init (klass);
2116 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
2118 mono_g_hash_table_insert (type_cache, type, res);
2123 * mono_method_get_object:
2124 * @domain: an app domain
2127 * Return an System.Reflection.MonoMethod object representing the method @method.
2129 MonoReflectionMethod*
2130 mono_method_get_object (MonoDomain *domain, MonoMethod *method)
2133 * We use the same C representation for methods and constructors, but the type
2134 * name in C# is different.
2138 MonoReflectionMethod *ret;
2140 CHECK_OBJECT (MonoReflectionMethod *, method);
2141 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
2142 cname = "MonoCMethod";
2144 cname = "MonoMethod";
2145 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
2147 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
2148 ret->method = method;
2149 ret->name = mono_string_new (domain, method->name);
2150 CACHE_OBJECT (method, ret);
2155 * mono_field_get_object:
2156 * @domain: an app domain
2160 * Return an System.Reflection.MonoField object representing the field @field
2163 MonoReflectionField*
2164 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
2166 MonoReflectionField *res;
2169 CHECK_OBJECT (MonoReflectionField *, field);
2170 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
2171 res = (MonoReflectionField *)mono_object_new (domain, oklass);
2174 CACHE_OBJECT (field, res);
2179 * mono_property_get_object:
2180 * @domain: an app domain
2182 * @property: a property
2184 * Return an System.Reflection.MonoProperty object representing the property @property
2187 MonoReflectionProperty*
2188 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
2190 MonoReflectionProperty *res;
2193 CHECK_OBJECT (MonoReflectionProperty *, property);
2194 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
2195 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
2197 res->property = property;
2198 CACHE_OBJECT (property, res);
2203 * mono_event_get_object:
2204 * @domain: an app domain
2208 * Return an System.Reflection.MonoEvent object representing the event @event
2211 MonoReflectionEvent*
2212 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
2214 MonoReflectionEvent *res;
2217 CHECK_OBJECT (MonoReflectionEvent *, event);
2218 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
2219 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
2222 CACHE_OBJECT (event, res);
2227 * mono_param_get_objects:
2228 * @domain: an app domain
2231 * Return an System.Reflection.ParameterInfo array object representing the parameters
2232 * in the method @method.
2234 MonoReflectionParameter**
2235 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
2237 MonoReflectionParameter **res;
2238 MonoReflectionMethod *member;
2243 if (!method->signature->param_count)
2246 member = mono_method_get_object (domain, method);
2247 names = g_new (char *, method->signature->param_count);
2248 mono_method_get_param_names (method, (const char **) names);
2250 /* Note: the cache is based on the address of the signature into the method
2251 * since we already cache MethodInfos with the method as keys.
2253 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature));
2254 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
2256 res = GC_malloc (sizeof (MonoReflectionParameter*) * method->signature->param_count);
2258 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
2260 for (i = 0; i < method->signature->param_count; ++i) {
2261 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
2262 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
2263 res [i]->DefaultValueImpl = NULL; /* FIXME */
2264 res [i]->MemberImpl = (MonoObject*)member;
2265 res [i]->NameImpl = mono_string_new (domain, names [i]);
2266 res [i]->PositionImpl = i + 1;
2267 res [i]->AttrsImpl = method->signature->params [i]->attrs;
2270 CACHE_OBJECT (&(method->signature), res);
2275 * mono_reflection_parse_type:
2278 * Parse a type name as accepted by the GetType () method and output the info
2279 * extracted in the info structure.
2280 * the name param will be mangled, so, make a copy before passing it to this function.
2281 * The fields in info will be valid until the memory pointed to by name is valid.
2282 * Returns 0 on parse error.
2283 * See also mono_type_get_name () below.
2286 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
2288 char *start, *p, *w, *last_point;
2289 int in_modifiers = 0;
2290 int isbyref = 0, rank;
2292 start = p = w = name;
2294 info->name = info->name_space = info->assembly = NULL;
2295 info->nest_name = info->nest_name_space = NULL;
2296 info->modifiers = NULL;
2303 /* we have parsed the nesting namespace + name */
2305 info->nest_name_space = start;
2307 info->nest_name = last_point + 1;
2309 info->nest_name_space = (char *)"";
2310 info->nest_name = start;
2312 *p = 0; /* NULL terminate */
2337 info->name_space = start;
2339 info->name = last_point + 1;
2341 info->name_space = (char *)"";
2347 if (isbyref) /* only one level allowed by the spec */
2350 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
2354 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
2365 else if (*p != '*') /* '*' means unknown lower bound */
2371 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
2383 return 0; /* missing assembly name */
2390 *w = 0; /* terminate class name */
2391 if (!info->name || !*info->name)
2393 if (info->nest_name && !*info->nest_name)
2395 /* add other consistency checks */
2400 mono_type_get_name_recurse (MonoType *type, GString *str)
2404 switch (type->type) {
2405 case MONO_TYPE_ARRAY: {
2406 int i, rank = type->data.array->rank;
2408 mono_type_get_name_recurse (type->data.array->type, str);
2409 g_string_append_c (str, '[');
2410 for (i = 1; i < rank; i++)
2411 g_string_append_c (str, ',');
2412 g_string_append_c (str, ']');
2415 case MONO_TYPE_SZARRAY:
2416 mono_type_get_name_recurse (type->data.type, str);
2417 g_string_append (str, "[]");
2420 mono_type_get_name_recurse (type->data.type, str);
2421 g_string_append_c (str, '*');
2424 klass = mono_class_from_mono_type (type);
2425 if (klass->nested_in) {
2426 mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
2427 g_string_append_c (str, '+');
2429 if (*klass->name_space) {
2430 g_string_append (str, klass->name_space);
2431 g_string_append_c (str, '.');
2433 g_string_append (str, klass->name);
2439 * mono_type_get_name:
2442 * Returns the string representation for type as required by System.Reflection.
2443 * The inverse of mono_reflection_parse_type ().
2446 mono_type_get_name (MonoType *type)
2448 GString* result = g_string_new ("");
2449 mono_type_get_name_recurse (type, result);
2452 g_string_append_c (result, '&');
2454 return g_string_free (result, FALSE);
2458 * mono_reflection_get_type:
2459 * @image: a metadata context
2460 * @info: type description structure
2461 * @ignorecase: flag for case-insensitive string compares
2463 * Build a MonoType from the type description in @info.
2467 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
2474 g_warning ("Ignore case not yet supported in GetType()");
2479 image = mono_defaults.corlib;
2481 if (info->nest_name) {
2482 klass = mono_class_from_name (image, info->nest_name_space, info->nest_name);
2485 mono_class_init (klass);
2486 nested = klass->nested_classes;
2489 klass = nested->data;
2490 if (strcmp (klass->name, info->nest_name) == 0 &&
2491 strcmp (klass->name_space, info->nest_name_space) == 0)
2494 nested = nested->next;
2498 klass = mono_class_from_name (image, info->name_space, info->name);
2502 mono_class_init (klass);
2503 for (mod = info->modifiers; mod; mod = mod->next) {
2504 modval = GPOINTER_TO_UINT (mod->data);
2505 if (!modval) { /* byref: must be last modifier */
2506 return &klass->this_arg;
2507 } else if (modval == -1) {
2508 klass = mono_ptr_class_get (&klass->byval_arg);
2509 } else { /* array rank */
2510 klass = mono_array_class_get (&klass->byval_arg, modval);
2512 mono_class_init (klass);
2514 return &klass->byval_arg;
2518 * Optimization we could avoid mallocing() an little-endian archs that
2519 * don't crash with unaligned accesses.
2522 fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
2523 int len, i, slen, type;
2524 const char *p = mono_metadata_blob_heap (image, blobidx);
2526 len = mono_metadata_decode_value (p, &p);
2527 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
2532 for (i = 0; i < sig->param_count; ++i) {
2533 type = sig->params [i]->type;
2538 case MONO_TYPE_BOOLEAN: {
2539 MonoBoolean *bval = params [i] = g_malloc (sizeof (MonoBoolean));
2544 case MONO_TYPE_CHAR:
2546 case MONO_TYPE_I2: {
2547 guint16 *val = params [i] = g_malloc (sizeof (guint16));
2552 #if SIZEOF_VOID_P == 4
2558 case MONO_TYPE_I4: {
2559 guint32 *val = params [i] = g_malloc (sizeof (guint32));
2564 #if SIZEOF_VOID_P == 8
2565 case MONO_TYPE_U: /* error out instead? this should probably not happen */
2570 case MONO_TYPE_I8: {
2571 guint64 *val = params [i] = g_malloc (sizeof (guint64));
2576 case MONO_TYPE_VALUETYPE:
2577 if (sig->params [i]->data.klass->enumtype) {
2578 type = sig->params [i]->data.klass->enum_basetype->type;
2581 g_warning ("generic valutype %s not handled in custom attr value decoding", sig->params [i]->data.klass->name);
2584 case MONO_TYPE_STRING: {
2585 slen = mono_metadata_decode_value (p, &p);
2586 params [i] = mono_string_new_len (mono_domain_get (), p, slen);
2591 g_warning ("Type %02x not handled in custom attr value decoding", sig->params [i]->type);
2598 free_param_data (MonoMethodSignature *sig, void **params) {
2600 for (i = 0; i < sig->param_count; ++i) {
2601 switch (sig->params [i]->type) {
2602 case MONO_TYPE_BOOLEAN:
2603 case MONO_TYPE_CHAR:
2616 case MONO_TYPE_VALUETYPE:
2617 g_free (params [i]);
2626 * Find the method index in the metadata methodDef table.
2627 * Later put these three helper methods in metadata and export them.
2630 find_method_index (MonoMethod *method) {
2631 MonoClass *klass = method->klass;
2634 for (i = 0; i < klass->method.count; ++i) {
2635 if (method == klass->methods [i])
2636 return klass->method.first + 1 + i;
2642 * Find the field index in the metadata FieldDef table.
2645 find_field_index (MonoClass *klass, MonoClassField *field) {
2648 for (i = 0; i < klass->field.count; ++i) {
2649 if (field == &klass->fields [i])
2650 return klass->field.first + 1 + i;
2656 * Find the property index in the metadata Property table.
2659 find_property_index (MonoClass *klass, MonoProperty *property) {
2662 for (i = 0; i < klass->property.count; ++i) {
2663 if (property == &klass->properties [i])
2664 return klass->property.first + 1 + i;
2670 * Find the event index in the metadata Event table.
2673 find_event_index (MonoClass *klass, MonoEvent *event) {
2676 for (i = 0; i < klass->event.count; ++i) {
2677 if (event == &klass->events [i])
2678 return klass->event.first + 1 + i;
2684 * mono_reflection_get_custom_attrs:
2685 * @obj: a reflection object handle
2687 * Return an array with all the custom attributes defined of the
2688 * reflection handle @obj. The objects are fully build.
2691 mono_reflection_get_custom_attrs (MonoObject *obj)
2693 guint32 idx, mtoken, i, len;
2694 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
2704 klass = obj->vtable->klass;
2705 /* FIXME: need to handle: Module */
2706 if (klass == mono_defaults.monotype_class) {
2707 MonoReflectionType *rtype = (MonoReflectionType*)obj;
2708 klass = mono_class_from_mono_type (rtype->type);
2709 idx = mono_metadata_token_index (klass->type_token);
2710 idx <<= CUSTOM_ATTR_BITS;
2711 idx |= CUSTOM_ATTR_TYPEDEF;
2712 image = klass->image;
2713 } else if (strcmp ("Assembly", klass->name) == 0) {
2714 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
2715 idx = 1; /* there is only one assembly */
2716 idx <<= CUSTOM_ATTR_BITS;
2717 idx |= CUSTOM_ATTR_ASSEMBLY;
2718 image = rassembly->assembly->image;
2719 } else if (strcmp ("MonoProperty", klass->name) == 0) {
2720 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
2721 idx = find_property_index (rprop->klass, rprop->property);
2722 idx <<= CUSTOM_ATTR_BITS;
2723 idx |= CUSTOM_ATTR_PROPERTY;
2724 image = rprop->klass->image;
2725 } else if (strcmp ("MonoEvent", klass->name) == 0) {
2726 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
2727 idx = find_event_index (revent->klass, revent->event);
2728 idx <<= CUSTOM_ATTR_BITS;
2729 idx |= CUSTOM_ATTR_EVENT;
2730 image = revent->klass->image;
2731 } else if (strcmp ("MonoField", klass->name) == 0) {
2732 MonoReflectionField *rfield = (MonoReflectionField*)obj;
2733 idx = find_field_index (rfield->klass, rfield->field);
2734 idx <<= CUSTOM_ATTR_BITS;
2735 idx |= CUSTOM_ATTR_FIELDDEF;
2736 image = rfield->klass->image;
2737 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
2738 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
2739 idx = find_method_index (rmethod->method);
2740 idx <<= CUSTOM_ATTR_BITS;
2741 idx |= CUSTOM_ATTR_METHODDEF;
2742 image = method->klass->image;
2743 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
2744 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
2745 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
2746 guint32 method_index = find_method_index (rmethod->method);
2747 guint32 param_list, param_last, param_pos, found;
2749 image = rmethod->method->klass->image;
2750 ca = &image->tables [MONO_TABLE_METHOD];
2752 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
2753 if (method_index == ca->rows) {
2754 ca = &image->tables [MONO_TABLE_PARAM];
2755 param_last = ca->rows + 1;
2757 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
2758 ca = &image->tables [MONO_TABLE_PARAM];
2761 for (i = param_list; i < param_last; ++i) {
2762 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
2763 if (param_pos == param->PositionImpl) {
2769 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
2771 idx <<= CUSTOM_ATTR_BITS;
2772 idx |= CUSTOM_ATTR_PARAMDEF;
2773 } else { /* handle other types here... */
2774 g_error ("get custom attrs not yet supported for %s", klass->name);
2777 /* at this point image and index are set correctly for searching the custom attr */
2778 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2779 /* the table is not sorted */
2780 for (i = 0; i < ca->rows; ++i) {
2781 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
2782 if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
2784 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
2785 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
2786 case CUSTOM_ATTR_TYPE_METHODDEF:
2787 mtoken |= MONO_TOKEN_METHOD_DEF;
2789 case CUSTOM_ATTR_TYPE_MEMBERREF:
2790 mtoken |= MONO_TOKEN_MEMBER_REF;
2793 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
2796 method = mono_get_method (image, mtoken, NULL);
2798 g_error ("Can't find custom attr constructor");
2799 mono_class_init (method->klass);
2800 /*g_print ("got attr %s\n", method->klass->name);*/
2801 params = g_new (void*, method->signature->param_count);
2802 fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
2803 attr = mono_object_new (mono_domain_get (), method->klass);
2804 mono_runtime_invoke (method, attr, params);
2805 list = g_list_prepend (list, attr);
2806 free_param_data (method->signature, params);
2810 len = g_list_length (list);
2812 * The return type is really object[], but System/Attribute.cs does a cast
2813 * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
2814 * probably fix that.
2816 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
2817 result = mono_array_new (mono_domain_get (), klass, len);
2818 for (i = 0; i < len; ++i) {
2819 mono_array_set (result, gpointer, i, list->data);
2822 g_list_free (g_list_first (list));
2828 * mono_reflection_get_custom_attrs_blob:
2829 * @ctor: custom attribute constructor
2830 * @ctorArgs: arguments o the constructor
2836 * Creates the blob of data that needs to be saved in the metadata and that represents
2837 * the custom attributed described by @ctor, @ctorArgs etc.
2838 * Returns: a Byte array representing the blob of data.
2841 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) {
2843 MonoMethodSignature *sig;
2845 char *buffer, *p, *argval;
2846 guint32 buflen, i, type;
2848 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
2849 g_warning ("ConstructorBuilder Custom attribute not yet supported");
2851 * maybe we should have a param array to method signature function and
2852 * continue with the normal codepath.
2854 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, 4);
2855 mono_array_set (result, char, 0, 1);
2859 p = buffer = g_malloc (buflen);
2860 /* write the prolog */
2863 sig = ((MonoReflectionMethod*)ctor)->method->signature;
2864 /* FIXME: ENOENDIAN */
2865 for (i = 0; i < sig->param_count; ++i) {
2866 if ((p-buffer) + 10 >= buflen) {
2869 newbuf = g_realloc (buffer, buflen);
2870 p = newbuf + (p-buffer);
2873 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
2874 argval = ((char*)arg + sizeof (MonoObject));
2875 type = sig->params [i]->type;
2878 case MONO_TYPE_BOOLEAN:
2883 case MONO_TYPE_CHAR:
2885 case MONO_TYPE_I2: {
2886 guint16 *val = (guint16*)p;
2887 *val = *(guint16*)argval;
2893 case MONO_TYPE_R4: {
2894 guint32 *val = (guint32*)p;
2895 *val = *(guint32*)argval;
2901 case MONO_TYPE_R8: {
2902 guint64 *val = (guint64*)p;
2903 *val = *(guint64*)argval;
2907 case MONO_TYPE_VALUETYPE:
2908 if (sig->params [i]->data.klass->enumtype) {
2909 type = sig->params [i]->data.klass->enum_basetype->type;
2912 g_warning ("generic valutype %s not handled in custom attr value decoding", sig->params [i]->data.klass->name);
2915 case MONO_TYPE_STRING: {
2916 char *str = mono_string_to_utf8 ((MonoString*)arg);
2917 guint32 slen = strlen (str);
2918 if ((p-buffer) + 10 + slen >= buflen) {
2922 newbuf = g_realloc (buffer, buflen);
2923 p = newbuf + (p-buffer);
2926 mono_metadata_encode_value (slen, p, &p);
2927 memcpy (p, str, slen);
2933 g_error ("type 0x%02x not yet supported in custom attr encoder", type);
2937 * we don't support properties and fields, yet, set to 0.
2941 buflen = p - buffer;
2942 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
2943 p = mono_array_addr (result, char, 0);
2944 memcpy (p, buffer, buflen);
2950 * mono_reflection_setup_internal_class:
2951 * @tb: a TypeBuilder object
2953 * Creates a MonoClass that represents the TypeBuilder.
2954 * This is a trick that lets us simplify a lot of reflection code
2955 * (and will allow us to support Build and Run assemblies easier).
2958 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
2960 MonoClass *klass, *parent;
2962 klass = g_new0 (MonoClass, 1);
2964 klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
2967 parent = mono_class_from_mono_type (tb->parent->type);
2969 klass->inited = 1; /* we lie to the runtime */
2970 klass->name = mono_string_to_utf8 (tb->name);
2971 klass->name_space = mono_string_to_utf8 (tb->nspace);
2972 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
2973 klass->flags = tb->attrs;
2975 klass->element_class = klass;
2976 klass->reflection_info = tb; /* need to pin. */
2978 mono_class_setup_parent (klass, parent);
2979 mono_class_setup_mono_type (klass);
2982 * FIXME: handle interfaces.
2985 tb->type.type = &klass->byval_arg;
2987 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
2991 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
2993 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
2994 guint32 na = mono_array_length (sig->arguments);
2999 p = buf = g_malloc (10 + na * 10);
3001 mono_metadata_encode_value (0x07, p, &p);
3002 mono_metadata_encode_value (na, p, &p);
3003 for (i = 0; i < na; ++i) {
3004 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
3005 encode_reflection_type (assembly, type, p, &p);
3009 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
3010 p = mono_array_addr (result, char, 0);
3011 memcpy (p, buf, buflen);
3018 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
3020 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
3021 guint32 na = mono_array_length (sig->arguments);
3026 p = buf = g_malloc (10 + na * 10);
3028 mono_metadata_encode_value (0x06, p, &p);
3029 for (i = 0; i < na; ++i) {
3030 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
3031 encode_reflection_type (assembly, type, p, &p);
3035 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
3036 p = mono_array_addr (result, char, 0);
3037 memcpy (p, buf, buflen);