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"
23 #include "rawbuffer.h"
24 #include "mono-endian.h"
27 #define TEXT_OFFSET 512
28 #define CLI_H_SIZE 136
29 #define FILE_ALIGN 512
30 #define START_TEXT_RVA 0x00002000
33 MonoReflectionILGen *ilgen;
34 MonoReflectionType *rtype;
35 MonoArray *parameters;
40 guint32 *table_idx; /* note: it's a pointer */
44 } ReflectionMethodBuilder;
46 const unsigned char table_sizes [64] = {
56 MONO_INTERFACEIMPL_SIZE,
57 MONO_MEMBERREF_SIZE, /* 0x0A */
59 MONO_CUSTOM_ATTR_SIZE,
60 MONO_FIELD_MARSHAL_SIZE,
61 MONO_DECL_SECURITY_SIZE,
62 MONO_CLASS_LAYOUT_SIZE,
63 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
64 MONO_STAND_ALONE_SIGNATURE_SIZE,
68 MONO_PROPERTY_MAP_SIZE,
71 MONO_METHOD_SEMA_SIZE,
73 MONO_MODULEREF_SIZE, /* 0x1A */
79 MONO_ASSEMBLY_SIZE, /* 0x20 */
80 MONO_ASSEMBLY_PROCESSOR_SIZE,
82 MONO_ASSEMBLYREF_SIZE,
83 MONO_ASSEMBLYREFPROC_SIZE,
84 MONO_ASSEMBLYREFOS_SIZE,
88 MONO_NESTED_CLASS_SIZE,
92 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
93 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
96 alloc_table (MonoDynamicTable *table, guint nrows)
99 g_assert (table->columns);
100 table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
104 string_heap_insert (MonoStringHeap *sh, const char *str)
108 gpointer oldkey, oldval;
110 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
111 return GPOINTER_TO_UINT (oldval);
113 len = strlen (str) + 1;
115 if (idx + len > sh->alloc_size) {
116 sh->alloc_size += len + 4096;
117 sh->data = g_realloc (sh->data, sh->alloc_size);
120 * We strdup the string even if we already copy them in sh->data
121 * so that the string pointers in the hash remain valid even if
122 * we need to realloc sh->data. We may want to avoid that later.
124 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
125 memcpy (sh->data + idx, str, len);
131 string_heap_init (MonoStringHeap *sh)
134 sh->alloc_size = 4096;
135 sh->data = g_malloc (4096);
136 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
137 string_heap_insert (sh, "");
141 string_heap_free (MonoStringHeap *sh)
144 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
145 g_hash_table_destroy (sh->hash);
149 mono_image_add_stream_data (MonoDynamicStream *stream, char *data, guint32 len)
152 if (stream->alloc_size < stream->index + len) {
153 stream->alloc_size += len + 4096;
154 stream->data = g_realloc (stream->data, stream->alloc_size);
156 memcpy (stream->data + stream->index, data, len);
158 stream->index += len;
160 * align index? Not without adding an additional param that controls it since
161 * we may store a blob value in pieces.
167 stream_data_align (MonoDynamicStream *stream)
170 guint32 count = stream->index % 4;
172 /* we assume the stream data will be aligned */
174 mono_image_add_stream_data (stream, buf, 4 - count);
178 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
181 g_assert_not_reached ();
186 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
190 case MONO_TYPE_BOOLEAN:
204 case MONO_TYPE_STRING:
205 case MONO_TYPE_OBJECT:
206 case MONO_TYPE_TYPEDBYREF:
207 mono_metadata_encode_value (type->type, p, &p);
210 case MONO_TYPE_SZARRAY:
211 mono_metadata_encode_value (type->type, p, &p);
212 encode_type (assembly, type->data.type, p, &p);
214 case MONO_TYPE_VALUETYPE:
215 case MONO_TYPE_CLASS:
216 mono_metadata_encode_value (type->type, p, &p);
217 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
220 g_error ("need to encode type %x", type->type);
226 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
229 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
233 encode_type (assembly, type->type, p, endbuf);
237 g_assert_not_reached ();
242 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
247 guint32 nparams = sig->param_count;
248 guint32 size = 10 + nparams * 10;
253 p = buf = g_malloc (size);
255 * FIXME: vararg, explicit_this, differenc call_conv values...
257 *p = sig->call_convention;
259 *p |= 0x20; /* hasthis */
261 mono_metadata_encode_value (nparams, p, &p);
262 encode_type (assembly, sig->ret, p, &p);
263 for (i = 0; i < nparams; ++i)
264 encode_type (assembly, sig->params [i], p, &p);
266 mono_metadata_encode_value (p-buf, b, &b);
267 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
268 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
274 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
277 * FIXME: reuse code from method_encode_signature().
282 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
283 guint32 size = 10 + nparams * 10;
288 p = buf = g_malloc (size);
289 /* LAMESPEC: all the call conv spec is foobared */
290 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
291 if (mb->call_conv & 2)
292 *p |= 0x5; /* vararg */
293 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
294 *p |= 0x20; /* hasthis */
296 mono_metadata_encode_value (nparams, p, &p);
297 encode_reflection_type (assembly, mb->rtype, p, &p);
298 for (i = 0; i < nparams; ++i) {
299 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
300 encode_reflection_type (assembly, pt, p, &p);
303 mono_metadata_encode_value (p-buf, b, &b);
304 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
305 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
311 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
313 MonoDynamicTable *table;
316 guint32 idx, sig_idx;
317 guint nl = mono_array_length (ilgen->locals);
323 p = buf = g_malloc (10 + nl * 10);
324 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
325 idx = table->next_idx ++;
327 alloc_table (table, table->rows);
328 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
330 mono_metadata_encode_value (0x07, p, &p);
331 mono_metadata_encode_value (nl, p, &p);
332 for (i = 0; i < nl; ++i) {
333 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
334 encode_reflection_type (assembly, lb->type, p, &p);
336 mono_metadata_encode_value (p-buf, b, &b);
337 sig_idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
338 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
341 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
347 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
353 gint32 num_locals = 0;
354 gint32 num_exception = 0;
357 char fat_header [12];
360 guint32 local_sig = 0;
361 guint32 header_size = 12;
364 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
365 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
366 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
367 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
371 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
373 code = mb->ilgen->code;
374 code_size = mb->ilgen->code_len;
375 max_stack = mb->ilgen->max_stack;
376 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
377 if (mb->ilgen->ex_handlers) {
378 MonoILExceptionInfo *ex_info;
379 for (i = 0; i < mono_array_length (mb->ilgen->ex_handlers); ++i) {
380 ex_info = (MonoILExceptionInfo*)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
381 if (ex_info->handlers)
382 num_exception += mono_array_length (ex_info->handlers);
389 code_size = mono_array_length (code);
390 max_stack = 8; /* we probably need to run a verifier on the code... */
393 /* check for exceptions, maxstack, locals */
394 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
396 if (code_size < 64 && !(code_size & 1)) {
397 flags = (code_size << 2) | 0x2;
398 } else if (code_size < 32 && (code_size & 1)) {
399 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
403 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
404 /* add to the fixup todo list */
405 if (mb->ilgen && mb->ilgen->num_token_fixups)
406 g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
407 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
408 return assembly->text_rva + idx + CLI_H_SIZE;
412 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
414 * FIXME: need to set also the header size in fat_flags.
415 * (and more sects and init locals flags)
419 fat_flags |= METHOD_HEADER_MORE_SECTS;
420 fat_header [0] = fat_flags;
421 fat_header [1] = (header_size / 4 ) << 4;
422 shortp = (guint16*)(fat_header + 2);
424 intp = (guint32*)(fat_header + 4);
426 intp = (guint32*)(fat_header + 8);
428 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
429 /* add to the fixup todo list */
430 if (mb->ilgen && mb->ilgen->num_token_fixups)
431 g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
433 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
435 unsigned char sheader [4];
436 MonoExceptionClause clause;
437 MonoILExceptionInfo * ex_info;
438 MonoILExceptionBlock * ex_block;
441 stream_data_align (&assembly->code);
442 /* always use fat format for now */
443 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
444 num_exception *= sizeof (MonoExceptionClause);
445 sheader [1] = num_exception & 0xff;
446 sheader [2] = (num_exception >> 8) & 0xff;
447 sheader [3] = (num_exception >> 16) & 0xff;
448 mono_image_add_stream_data (&assembly->code, sheader, 4);
449 /* fat header, so we are already aligned */
451 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
452 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
453 if (ex_info->handlers) {
454 int finally_start = 0;
455 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
456 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
457 clause.flags = ex_block->type;
458 clause.try_offset = ex_info->start;
459 /* need fault, too, probably */
460 if (clause.flags == MONO_EXCEPTION_CLAUSE_FINALLY)
461 clause.try_len = finally_start - ex_info->start;
463 clause.try_len = ex_info->len;
464 clause.handler_offset = ex_block->start;
465 clause.handler_len = ex_block->len;
466 finally_start = clause.handler_offset + clause.handler_len;
467 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
468 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
469 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d\n",
470 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len);*/
471 /* FIXME: ENOENDIAN */
472 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
475 g_error ("No clauses");
479 return assembly->text_rva + idx + CLI_H_SIZE;
483 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 index)
486 MonoDynamicTable *table;
489 table = &assembly->tables [table_idx];
491 g_assert (col < table->columns);
493 values = table->values + table->columns;
494 for (i = 1; i <= table->rows; ++i) {
495 if (values [col] == index)
502 * index is the table index of the object
503 * type is one of CUSTOM_ATTR_*
506 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 index, guint32 type, MonoArray *cattrs)
508 MonoDynamicTable *table;
509 MonoReflectionCustomAttr *cattr;
511 guint32 count, i, token;
515 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
518 count = mono_array_length (cattrs);
519 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
520 table->rows += count;
521 alloc_table (table, table->rows);
522 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
523 index <<= CUSTOM_ATTR_BITS;
525 for (i = 0; i < count; ++i) {
526 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
527 values [MONO_CUSTOM_ATTR_PARENT] = index;
528 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
529 type = mono_metadata_token_index (token);
530 type <<= CUSTOM_ATTR_TYPE_BITS;
531 switch (mono_metadata_token_table (token)) {
532 case MONO_TABLE_METHOD:
533 type |= CUSTOM_ATTR_TYPE_METHODDEF;
535 case MONO_TABLE_MEMBERREF:
536 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
539 g_error ("got wrong token in custom attr");
541 values [MONO_CUSTOM_ATTR_TYPE] = type;
543 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
544 values [MONO_CUSTOM_ATTR_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, p - blob_size);
545 mono_image_add_stream_data (&assembly->blob,
546 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
547 values += MONO_CUSTOM_ATTR_SIZE;
553 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
555 MonoDynamicTable *table;
560 /* room in this table is already allocated */
561 table = &assembly->tables [MONO_TABLE_METHOD];
562 *mb->table_idx = table->next_idx ++;
563 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
565 name = mono_string_to_utf8 (mb->name);
566 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
568 } else { /* a constructor */
569 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
571 values [MONO_METHOD_FLAGS] = mb->attrs;
572 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
573 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
574 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
576 table = &assembly->tables [MONO_TABLE_PARAM];
577 values [MONO_METHOD_PARAMLIST] = table->next_idx;
581 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
582 if (mono_array_get (mb->pinfo, gpointer, i))
585 table->rows += count;
586 alloc_table (table, table->rows);
587 values = table->values + table->next_idx * MONO_PARAM_SIZE;
588 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
589 MonoReflectionParamBuilder *pb;
590 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
591 values [MONO_PARAM_FLAGS] = pb->attrs;
592 values [MONO_PARAM_SEQUENCE] = i;
593 name = mono_string_to_utf8 (pb->name);
594 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
596 values += MONO_PARAM_SIZE;
598 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
605 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
607 MonoDynamicTable *table;
610 ReflectionMethodBuilder rmb;
612 rmb.ilgen = mb->ilgen;
613 rmb.rtype = mb->rtype;
614 rmb.parameters = mb->parameters;
615 rmb.pinfo = mb->pinfo;
616 rmb.attrs = mb->attrs;
617 rmb.iattrs = mb->iattrs;
618 rmb.call_conv = mb->call_conv;
622 rmb.table_idx = &mb->table_idx;
624 mono_image_basic_method (&rmb, assembly);
626 if (mb->dll) { /* It's a P/Invoke method */
628 table = &assembly->tables [MONO_TABLE_IMPLMAP];
630 alloc_table (table, table->rows);
631 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
632 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
633 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
634 name = mono_string_to_utf8 (mb->dllentry);
635 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
637 name = mono_string_to_utf8 (mb->dll);
638 moduleref = string_heap_insert (&assembly->sheap, name);
640 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
641 table = &assembly->tables [MONO_TABLE_MODULEREF];
643 alloc_table (table, table->rows);
644 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
645 values [MONO_IMPLMAP_SCOPE] = table->rows;
648 if (mb->override_method) {
649 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
650 table = &assembly->tables [MONO_TABLE_METHODIMPL];
652 alloc_table (table, table->rows);
653 values = table->values + table->rows * MONO_MTHODIMPL_SIZE;
654 values [MONO_MTHODIMPL_CLASS] = tb->table_idx;
655 values [MONO_MTHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
656 if (mb->override_method->method)
657 values [MONO_MTHODIMPL_DECLARATION] = mono_image_get_methodref_token (assembly, mb->override_method->method);
659 MonoReflectionMethodBuilder *omb = (MonoReflectionMethodBuilder*)mb->override_method;
660 values [MONO_MTHODIMPL_DECLARATION] = METHODDEFORREF_METHODDEF | (omb->table_idx << METHODDEFORREF_BITS);
663 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
667 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
669 ReflectionMethodBuilder rmb;
671 rmb.ilgen = mb->ilgen;
672 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
673 rmb.parameters = mb->parameters;
674 rmb.pinfo = mb->pinfo;
675 rmb.attrs = mb->attrs;
676 rmb.iattrs = mb->iattrs;
677 rmb.call_conv = mb->call_conv;
681 rmb.table_idx = &mb->table_idx;
683 mono_image_basic_method (&rmb, assembly);
684 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
689 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
697 p = buf = g_malloc (64);
699 /* No start code with field refs...
700 * mono_metadata_encode_value (0x06, p, &p);
702 /* encode custom attributes before the type */
703 encode_type (assembly, field->type, p, &p);
704 g_assert (p-buf < 64);
705 mono_metadata_encode_value (p-buf, b, &b);
706 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
707 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
713 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
721 p = buf = g_malloc (64);
723 mono_metadata_encode_value (0x06, p, &p);
724 /* encode custom attributes before the type */
725 encode_reflection_type (assembly, fb->type, p, &p);
726 g_assert (p-buf < 64);
727 mono_metadata_encode_value (p-buf, b, &b);
728 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
729 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
735 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
742 p = buf = g_malloc (64);
744 box_val = ((char*)val) + sizeof (MonoObject);
745 *ret_type = val->vtable->klass->byval_arg.type;
748 case MONO_TYPE_BOOLEAN:
768 case MONO_TYPE_VALUETYPE:
769 if (val->vtable->klass->enumtype) {
770 *ret_type = val->vtable->klass->enum_basetype->type;
773 g_error ("we can't encode valuetypes");
774 case MONO_TYPE_STRING:
776 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
779 /* there is no signature */
780 mono_metadata_encode_value (len, b, &b);
781 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
782 /* FIXME: ENOENDIAN */
783 mono_image_add_stream_data (&assembly->blob, box_val, len);
790 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
792 MonoDynamicTable *table;
796 table = &assembly->tables [MONO_TABLE_FIELD];
797 fb->table_idx = table->next_idx ++;
798 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
799 name = mono_string_to_utf8 (fb->name);
800 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
802 values [MONO_FIELD_FLAGS] = fb->attrs;
803 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
805 if (fb->offset != -1) {
806 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
808 alloc_table (table, table->rows);
809 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
810 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
811 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
813 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
814 guint32 field_type = 0;
815 table = &assembly->tables [MONO_TABLE_CONSTANT];
817 alloc_table (table, table->rows);
818 values = table->values + table->rows * MONO_CONSTANT_SIZE;
819 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
820 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
821 values [MONO_CONSTANT_TYPE] = field_type;
822 values [MONO_CONSTANT_PADDING] = 0;
826 table = &assembly->tables [MONO_TABLE_FIELDRVA];
828 alloc_table (table, table->rows);
829 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
830 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
832 * We store it in the code section because it's simpler for now.
834 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
835 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva + CLI_H_SIZE;
837 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
841 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
847 MonoReflectionMethodBuilder *mb = fb->get_method;
850 if (mb && mb->parameters)
851 nparams = mono_array_length (mb->parameters);
852 buf = p = g_malloc (24 + nparams * 10);
855 mono_metadata_encode_value (nparams, p, &p);
857 encode_reflection_type (assembly, mb->rtype, p, &p);
858 for (i = 0; i < nparams; ++i) {
859 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
860 encode_reflection_type (assembly, pt, p, &p);
863 *p++ = 1; /* void: a property should probably not be allowed without a getter */
866 mono_metadata_encode_value (p-buf, b, &b);
867 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
868 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
874 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
876 MonoDynamicTable *table;
879 guint num_methods = 0;
883 * we need to set things in the following tables:
884 * PROPERTYMAP (info already filled in _get_type_info ())
885 * PROPERTY (rows already preallocated in _get_type_info ())
886 * METHOD (method info already done with the generic method code)
889 table = &assembly->tables [MONO_TABLE_PROPERTY];
890 pb->table_idx = table->next_idx ++;
891 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
892 name = mono_string_to_utf8 (pb->name);
893 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
895 values [MONO_PROPERTY_FLAGS] = pb->attrs;
896 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
898 /* FIXME: we still don't handle 'other' methods */
899 if (pb->get_method) num_methods ++;
900 if (pb->set_method) num_methods ++;
902 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
903 table->rows += num_methods;
904 alloc_table (table, table->rows);
906 if (pb->get_method) {
907 semaidx = table->next_idx ++;
908 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
909 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
910 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
911 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
913 if (pb->set_method) {
914 semaidx = table->next_idx ++;
915 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
916 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
917 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
918 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
920 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
924 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
926 MonoDynamicTable *table;
929 guint num_methods = 0;
933 * we need to set things in the following tables:
934 * EVENTMAP (info already filled in _get_type_info ())
935 * EVENT (rows already preallocated in _get_type_info ())
936 * METHOD (method info already done with the generic method code)
939 table = &assembly->tables [MONO_TABLE_EVENT];
940 eb->table_idx = table->next_idx ++;
941 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
942 name = mono_string_to_utf8 (eb->name);
943 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
945 values [MONO_EVENT_FLAGS] = eb->attrs;
946 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
949 * FIXME: we still don't handle 'other' methods
951 if (eb->add_method) num_methods ++;
952 if (eb->remove_method) num_methods ++;
953 if (eb->raise_method) num_methods ++;
955 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
956 table->rows += num_methods;
957 alloc_table (table, table->rows);
959 if (eb->add_method) {
960 semaidx = table->next_idx ++;
961 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
962 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
963 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
964 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
966 if (eb->remove_method) {
967 semaidx = table->next_idx ++;
968 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
969 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
970 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
971 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
973 if (eb->raise_method) {
974 semaidx = table->next_idx ++;
975 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
976 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
977 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
978 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
980 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
984 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
986 MonoDynamicTable *table;
989 guint32 cols [MONO_ASSEMBLY_SIZE];
991 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, image))))
994 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
996 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
997 token = table->next_idx ++;
999 alloc_table (table, table->rows);
1000 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1001 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1002 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1003 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1004 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1005 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1006 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1007 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1008 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1009 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1011 token <<= RESOLTION_SCOPE_BITS;
1012 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1013 g_hash_table_insert (assembly->typeref, image, GUINT_TO_POINTER (token));
1018 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1020 MonoDynamicTable *table;
1025 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1028 klass = mono_class_from_mono_type (type);
1030 * If it's in the same module:
1032 if (klass->image == assembly->assembly.image) {
1033 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1034 return TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1037 table = &assembly->tables [MONO_TABLE_TYPEREF];
1038 alloc_table (table, table->rows + 1);
1039 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1040 values [MONO_TYPEREF_SCOPE] = resolution_scope_from_image (assembly, klass->image);
1041 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1042 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1043 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1044 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1050 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoClass *klass, const char *name, guint32 sig)
1052 MonoDynamicTable *table;
1054 guint32 token, pclass;
1057 parent = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1058 switch (parent & TYPEDEFORREF_MASK) {
1059 case TYPEDEFORREF_TYPEREF:
1060 pclass = MEMBERREF_PARENT_TYPEREF;
1062 case TYPEDEFORREF_TYPESPEC:
1063 pclass = MEMBERREF_PARENT_TYPESPEC;
1065 case TYPEDEFORREF_TYPEDEF:
1066 /* should never get here */
1068 g_error ("unknow typeref or def token");
1070 /* extract the index */
1071 parent >>= TYPEDEFORREF_BITS;
1073 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1074 alloc_table (table, table->rows + 1);
1075 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1076 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1077 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1078 values [MONO_MEMBERREF_SIGNATURE] = sig;
1079 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1086 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1090 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, method));
1093 token = mono_image_get_memberref_token (assembly, method->klass,
1094 method->name, method_encode_signature (assembly, method->signature));
1095 g_hash_table_insert (assembly->typeref, method, GUINT_TO_POINTER(token));
1100 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1104 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, field));
1107 token = mono_image_get_memberref_token (assembly, klass,
1108 field->name, fieldref_encode_signature (assembly, field));
1109 g_hash_table_insert (assembly->typeref, field, GUINT_TO_POINTER(token));
1114 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1116 MonoDynamicTable *table;
1121 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1122 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1123 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1124 if (tb->parent) { /* interfaces don't have a parent */
1125 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1127 values [MONO_TYPEDEF_EXTENDS] = 0;
1128 n = mono_string_to_utf8 (tb->name);
1129 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1131 n = mono_string_to_utf8 (tb->nspace);
1132 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1134 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1135 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1138 * if we have explicitlayout or sequentiallayouts, output data in the
1139 * ClassLayout table.
1141 if ((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1142 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1144 alloc_table (table, table->rows);
1145 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1146 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1147 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1148 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1152 * FIXME: constructors and methods need to be output in the same order
1153 * as they are defined (according to table_idx).
1158 table = &assembly->tables [MONO_TABLE_FIELD];
1159 table->rows += mono_array_length (tb->fields);
1160 alloc_table (table, table->rows);
1161 for (i = 0; i < mono_array_length (tb->fields); ++i)
1162 mono_image_get_field_info (
1163 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1166 /* handle constructors */
1168 table = &assembly->tables [MONO_TABLE_METHOD];
1169 table->rows += mono_array_length (tb->ctors);
1170 alloc_table (table, table->rows);
1171 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1172 mono_image_get_ctor_info (domain,
1173 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1176 /* handle methods */
1178 table = &assembly->tables [MONO_TABLE_METHOD];
1179 table->rows += mono_array_length (tb->methods);
1180 alloc_table (table, table->rows);
1181 for (i = 0; i < mono_array_length (tb->methods); ++i)
1182 mono_image_get_method_info (
1183 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1186 /* Do the same with properties etc.. */
1188 * FIXME: note that the methodsemantics table needs to be sorted, so events
1189 * go before properties; not sure if this is enough...
1191 if (tb->events && mono_array_length (tb->events)) {
1192 table = &assembly->tables [MONO_TABLE_EVENT];
1193 table->rows += mono_array_length (tb->events);
1194 alloc_table (table, table->rows);
1195 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1197 alloc_table (table, table->rows);
1198 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1199 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1200 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1201 for (i = 0; i < mono_array_length (tb->events); ++i)
1202 mono_image_get_event_info (
1203 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1205 if (tb->properties && mono_array_length (tb->properties)) {
1206 table = &assembly->tables [MONO_TABLE_PROPERTY];
1207 table->rows += mono_array_length (tb->properties);
1208 alloc_table (table, table->rows);
1209 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1211 alloc_table (table, table->rows);
1212 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1213 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1214 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1215 for (i = 0; i < mono_array_length (tb->properties); ++i)
1216 mono_image_get_property_info (
1217 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1220 MonoDynamicTable *ntable;
1222 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1223 table->rows += mono_array_length (tb->subtypes);
1224 alloc_table (table, table->rows);
1226 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1227 ntable->rows += mono_array_length (tb->subtypes);
1228 alloc_table (ntable, ntable->rows);
1229 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1231 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1232 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1234 mono_image_get_type_info (domain, subtype, assembly);
1235 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1236 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1237 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1238 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1239 mono_string_to_utf8 (tb->name), tb->table_idx,
1240 ntable->next_idx, ntable->rows);*/
1241 values += MONO_NESTED_CLASS_SIZE;
1245 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1249 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1251 MonoDynamicTable *table;
1255 table = &assembly->tables [MONO_TABLE_MODULE];
1256 mb->table_idx = table->next_idx ++;
1257 name = mono_string_to_utf8 (mb->module.name);
1258 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1260 /* need to set mvid? */
1262 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1264 * fill-in info in other tables as well.
1266 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1267 table->rows += mono_array_length (mb->types);
1268 alloc_table (table, table->rows);
1270 * We assign here the typedef indexes to avoid mismatches if a type that
1271 * has not yet been stored in the tables is referenced by another type.
1273 for (i = 0; i < mono_array_length (mb->types); ++i) {
1275 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1276 type->table_idx = table->next_idx ++;
1277 if (!type->subtypes)
1279 for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1280 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1281 subtype->table_idx = table->next_idx ++;
1284 for (i = 0; i < mono_array_length (mb->types); ++i)
1285 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1288 #define align_pointer(base,p)\
1290 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1292 (p) += 4 - (__diff & 3);\
1296 build_compressed_metadata (MonoDynamicAssembly *assembly)
1299 guint64 valid_mask = 0;
1300 guint32 heapt_size = 0;
1301 guint32 meta_size = 256; /* allow for header and other stuff */
1302 guint32 table_offset;
1303 guint32 ntables = 0;
1309 char *version = "mono" VERSION;
1311 /* Compute table sizes */
1312 meta = assembly->assembly.image = g_new0 (MonoImage, 1);
1314 /* Setup the info used by compute_sizes () */
1315 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1316 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1317 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1319 meta_size += assembly->blob.index;
1320 meta_size += assembly->guid.index;
1321 meta_size += assembly->sheap.index;
1322 meta_size += assembly->us.index;
1324 for (i=0; i < 64; ++i)
1325 meta->tables [i].rows = assembly->tables [i].rows;
1327 for (i = 0; i < 64; i++){
1328 if (meta->tables [i].rows == 0)
1330 valid_mask |= (guint64)1 << i;
1332 meta->tables [i].row_size = mono_metadata_compute_size (
1333 meta, i, &meta->tables [i].size_bitfield);
1334 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1336 heapt_size += 24; /* #~ header size */
1337 heapt_size += ntables * 4;
1338 meta_size += heapt_size;
1339 meta->raw_metadata = g_malloc0 (meta_size);
1340 p = meta->raw_metadata;
1341 /* the metadata signature */
1342 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1343 /* version numbers and 4 bytes reserved */
1344 int16val = (guint16*)p;
1348 /* version string */
1349 int32val = (guint32*)p;
1350 *int32val = strlen (version);
1352 memcpy (p, version, *int32val);
1354 align_pointer (meta->raw_metadata, p);
1355 int16val = (guint16*)p;
1356 *int16val++ = 0; /* flags must be 0 */
1357 *int16val = 5; /* number of streams */
1361 * write the stream info.
1363 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1364 table_offset += 3; table_offset &= ~3;
1366 int32val = (guint32*)p;
1367 *int32val++ = assembly->tstream.offset = table_offset;
1368 *int32val = heapt_size;
1369 table_offset += *int32val;
1370 table_offset += 3; table_offset &= ~3;
1374 align_pointer (meta->raw_metadata, p);
1376 int32val = (guint32*)p;
1377 *int32val++ = assembly->sheap.offset = table_offset;
1378 *int32val = assembly->sheap.index;
1379 table_offset += *int32val;
1380 table_offset += 3; table_offset &= ~3;
1382 strcpy (p, "#Strings");
1384 align_pointer (meta->raw_metadata, p);
1386 int32val = (guint32*)p;
1387 *int32val++ = assembly->us.offset = table_offset;
1388 *int32val = assembly->us.index;
1389 table_offset += *int32val;
1390 table_offset += 3; table_offset &= ~3;
1394 align_pointer (meta->raw_metadata, p);
1396 int32val = (guint32*)p;
1397 *int32val++ = assembly->blob.offset = table_offset;
1398 *int32val = assembly->blob.index;
1399 table_offset += *int32val;
1400 table_offset += 3; table_offset &= ~3;
1402 strcpy (p, "#Blob");
1404 align_pointer (meta->raw_metadata, p);
1406 int32val = (guint32*)p;
1407 *int32val++ = assembly->guid.offset = table_offset;
1408 *int32val = assembly->guid.index;
1409 table_offset += *int32val;
1410 table_offset += 3; table_offset &= ~3;
1412 strcpy (p, "#GUID");
1414 align_pointer (meta->raw_metadata, p);
1417 * now copy the data, the table stream header and contents goes first.
1419 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1420 p = meta->raw_metadata + assembly->tstream.offset;
1421 int32val = (guint32*)p;
1422 *int32val = 0; /* reserved */
1424 *p++ = 1; /* version */
1426 if (meta->idx_string_wide)
1428 if (meta->idx_guid_wide)
1430 if (meta->idx_blob_wide)
1433 *p++ = 0; /* reserved */
1434 int64val = (guint64*)p;
1435 *int64val++ = valid_mask;
1436 *int64val++ = 0; /* bitvector of sorted tables, set to 0 for now */
1438 int32val = (guint32*)p;
1439 for (i = 0; i < 64; i++){
1440 if (meta->tables [i].rows == 0)
1442 *int32val++ = meta->tables [i].rows;
1444 p = (unsigned char*)int32val;
1445 /* compress the tables */
1446 for (i = 0; i < 64; i++){
1449 guint32 bitfield = meta->tables [i].size_bitfield;
1450 if (!meta->tables [i].rows)
1452 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1453 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1454 meta->tables [i].base = p;
1455 for (row = 1; row <= meta->tables [i].rows; ++row) {
1456 values = assembly->tables [i].values + row * assembly->tables [i].columns;
1457 for (col = 0; col < assembly->tables [i].columns; ++col) {
1458 switch (mono_metadata_table_size (bitfield, col)) {
1460 *p++ = values [col];
1463 int16val = (guint16*)p;
1464 *int16val = values [col];
1468 int32val = (guint32*)p;
1469 *int32val = values [col];
1473 g_assert_not_reached ();
1477 g_assert ((p - (unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1480 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1481 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1482 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1483 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1484 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1486 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1490 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
1491 guint32 code_idx = GPOINTER_TO_UINT (value);
1492 MonoReflectionILTokenInfo *iltoken;
1493 MonoReflectionFieldBuilder *field;
1494 MonoReflectionCtorBuilder *ctor;
1495 MonoReflectionMethodBuilder *method;
1497 unsigned char *target;
1499 for (i = 0; i < ilgen->num_token_fixups; ++i) {
1500 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
1501 target = assembly->code.data + code_idx + iltoken->code_pos;
1502 switch (target [3]) {
1503 case MONO_TABLE_FIELD:
1504 if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
1505 g_assert_not_reached ();
1506 field = (MonoReflectionFieldBuilder *)iltoken->member;
1507 index = field->table_idx;
1509 case MONO_TABLE_METHOD:
1510 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1511 method = (MonoReflectionMethodBuilder *)iltoken->member;
1512 index = method->table_idx;
1513 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1514 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
1515 index = ctor->table_idx;
1517 g_assert_not_reached ();
1521 g_error ("got unexpected table 0x%02x in fixup", target [3]);
1523 target [0] = index & 0xff;
1524 target [1] = (index >> 8) & 0xff;
1525 target [2] = (index >> 16) & 0xff;
1530 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
1532 MonoDynamicTable *table;
1533 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
1534 MonoDomain *domain = ((MonoObject *)assemblyb)->vtable->domain;
1540 assembly->text_rva = START_TEXT_RVA;
1542 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
1543 alloc_table (table, 1);
1544 values = table->values + MONO_ASSEMBLY_SIZE;
1545 values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
1546 name = mono_string_to_utf8 (assemblyb->name);
1547 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
1549 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
1550 values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
1551 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1552 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1553 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1554 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1556 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
1558 assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
1559 assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
1561 if (assemblyb->modules) {
1562 len = mono_array_length (assemblyb->modules);
1563 table = &assembly->tables [MONO_TABLE_MODULE];
1564 alloc_table (table, len);
1565 for (i = 0; i < len; ++i)
1566 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
1568 table = &assembly->tables [MONO_TABLE_MODULE];
1570 alloc_table (table, table->rows);
1571 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
1575 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1577 * table->rows is already set above and in mono_image_fill_module_table.
1579 alloc_table (table, table->rows);
1581 * Set the first entry.
1583 values = table->values + table->columns;
1584 values [MONO_TYPEDEF_FLAGS] = 0;
1585 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
1586 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
1587 values [MONO_TYPEDEF_EXTENDS] = 0;
1588 values [MONO_TYPEDEF_FIELD_LIST] = 1;
1589 values [MONO_TYPEDEF_METHOD_LIST] = 1;
1592 g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
1594 build_compressed_metadata (assembly);
1598 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
1604 if (!assembly->dynamic_assembly)
1605 mono_image_basic_init (assembly);
1606 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
1607 index = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
1608 /* FIXME: ENOENDIAN */
1609 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (char*)mono_string_chars (str), str->length * 2);
1610 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
1611 return MONO_TOKEN_STRING | index;
1615 * Get a token to insert in the IL code stream for the given MemberInfo.
1617 * ConstructorBuilder
1627 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
1629 MonoClass *klass = obj->vtable->klass;
1632 if (strcmp (klass->name, "MethodBuilder") == 0) {
1633 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
1634 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1635 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1638 if (strcmp (klass->name, "ConstructorBuilder") == 0) {
1639 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
1640 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1641 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1644 if (strcmp (klass->name, "FieldBuilder") == 0) {
1645 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
1646 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
1648 if (strcmp (klass->name, "TypeBuilder") == 0) {
1649 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
1650 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
1652 if (strcmp (klass->name, "MonoType") == 0) {
1653 MonoReflectionType *tb = (MonoReflectionType *)obj;
1654 return mono_metadata_token_from_dor (
1655 mono_image_typedef_or_ref (assembly, tb->type));
1657 if (strcmp (klass->name, "MonoCMethod") == 0 ||
1658 strcmp (klass->name, "MonoMethod") == 0) {
1659 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
1660 token = mono_image_get_methodref_token (assembly, m->method);
1661 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1664 if (strcmp (klass->name, "MonoField") == 0) {
1665 MonoReflectionField *f = (MonoReflectionField *)obj;
1666 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
1667 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1670 g_print ("requested token for %s\n", klass->name);
1675 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1677 MonoDynamicAssembly *assembly;
1681 if (assemblyb->dynamic_assembly)
1684 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1686 assembly->token_fixups = g_hash_table_new (g_direct_hash, g_direct_equal);
1687 assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
1689 string_heap_init (&assembly->sheap);
1690 mono_image_add_stream_data (&assembly->us, "", 1);
1691 mono_image_add_stream_data (&assembly->blob, "", 1);
1693 for (i=0; i < 64; ++i) {
1694 assembly->tables [i].next_idx = 1;
1695 assembly->tables [i].columns = table_sizes [i];
1698 image = g_new0 (MonoImage, 1);
1700 /* keep in sync with image.c */
1701 image->name = mono_string_to_utf8 (assemblyb->name);
1702 image->assembly_name = image->name; /* they may be different */
1704 image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
1705 image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
1706 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
1707 image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
1709 assembly->assembly.image = image;
1714 mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, int maxsize)
1716 MonoMSDOSHeader *msdos;
1717 MonoDotNetHeader *header;
1718 MonoSectionTable *section;
1719 MonoCLIHeader *cli_header;
1720 guint32 header_size = TEXT_OFFSET + CLI_H_SIZE;
1721 MonoDynamicAssembly *assembly;
1723 static const unsigned char msheader[] = {
1724 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
1725 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
1728 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
1729 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
1730 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
1731 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1734 if (maxsize < header_size)
1737 mono_image_basic_init (assemblyb);
1738 assembly = assemblyb->dynamic_assembly;
1740 mono_image_build_metadata (assemblyb);
1742 memset (buffer, 0, header_size);
1743 memcpy (buffer, msheader, sizeof (MonoMSDOSHeader));
1745 msdos = (MonoMSDOSHeader *)buffer;
1746 header = (MonoDotNetHeader *)(buffer + sizeof (MonoMSDOSHeader));
1747 section = (MonoSectionTable*) (buffer + sizeof (MonoMSDOSHeader) + sizeof (MonoDotNetHeader));
1749 /* FIXME: ENDIAN problem: byteswap as needed */
1750 msdos->pe_offset = sizeof (MonoMSDOSHeader);
1752 header->pesig [0] = 'P';
1753 header->pesig [1] = 'E';
1754 header->pesig [2] = header->pesig [3] = 0;
1756 header->coff.coff_machine = 0x14c;
1757 header->coff.coff_sections = 1; /* only .text supported now */
1758 header->coff.coff_time = time (NULL);
1759 header->coff.coff_opt_header_size = sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4;
1761 header->coff.coff_attributes = 0x010e;
1763 //header->coff.coff_attributes = 0x210e;
1764 header->pe.pe_magic = 0x10B;
1765 header->pe.pe_major = 6;
1766 header->pe.pe_minor = 0;
1767 /* need to set: pe_code_size pe_data_size pe_rva_entry_point pe_rva_code_base pe_rva_data_base */
1769 header->nt.pe_image_base = 0x400000;
1770 header->nt.pe_section_align = 8192;
1771 header->nt.pe_file_alignment = FILE_ALIGN;
1772 header->nt.pe_os_major = 4;
1773 header->nt.pe_os_minor = 0;
1774 header->nt.pe_subsys_major = 4;
1775 /* need to set pe_image_size, pe_header_size */
1776 header->nt.pe_subsys_required = 3; /* 3 -> cmdline app, 2 -> GUI app */
1777 header->nt.pe_stack_reserve = 0x00100000;
1778 header->nt.pe_stack_commit = 0x00001000;
1779 header->nt.pe_heap_reserve = 0x00100000;
1780 header->nt.pe_heap_commit = 0x00001000;
1781 header->nt.pe_loader_flags = 1;
1782 header->nt.pe_data_dir_count = 16;
1786 header->datadir.pe_import_table
1791 header->datadir.pe_cli_header.size = CLI_H_SIZE;
1792 header->datadir.pe_cli_header.rva = assembly->text_rva; /* we put it always at the beginning */
1794 /* Write section tables */
1795 strcpy (section->st_name, ".text");
1796 section->st_virtual_address = START_TEXT_RVA;
1797 section->st_virtual_size = assembly->meta_size + assembly->code.index;
1798 section->st_raw_data_size = section->st_virtual_size + (FILE_ALIGN - 1);
1799 section->st_raw_data_size &= ~(FILE_ALIGN - 1);
1800 section->st_raw_data_ptr = TEXT_OFFSET;
1801 section->st_flags = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
1804 * align: build_compressed_metadata () assumes metadata is aligned
1806 * cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1808 assembly->code.index += 3;
1809 assembly->code.index &= ~3;
1812 * Write the MonoCLIHeader header
1814 cli_header = (MonoCLIHeader*)(buffer + TEXT_OFFSET);
1815 cli_header->ch_size = CLI_H_SIZE;
1816 cli_header->ch_runtime_major = 2;
1817 cli_header->ch_flags = CLI_FLAGS_ILONLY;
1818 if (assemblyb->entry_point)
1819 cli_header->ch_entry_point = assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF;
1821 cli_header->ch_entry_point = 0;
1822 cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1823 cli_header->ch_metadata.size = assembly->meta_size;
1829 * We need to return always the same object for MethodInfo, FieldInfo etc..
1830 * type uses a different hash, since it uses custom hash/equal functions.
1832 static GHashTable *object_cache = NULL;
1833 static GHashTable *type_cache = NULL;
1835 #define CHECK_OBJECT(t,p) \
1838 if (!object_cache) \
1839 object_cache = g_hash_table_new (g_direct_hash, g_direct_equal); \
1840 if ((_obj = g_hash_table_lookup (object_cache, (p)))) \
1844 #define CACHE_OBJECT(p,o) \
1846 g_hash_table_insert (object_cache, p,o); \
1849 MonoReflectionAssembly*
1850 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
1852 static MonoClass *System_Reflection_Assembly;
1853 MonoReflectionAssembly *res;
1855 CHECK_OBJECT (MonoReflectionAssembly *, assembly);
1856 if (!System_Reflection_Assembly)
1857 System_Reflection_Assembly = mono_class_from_name (
1858 mono_defaults.corlib, "System.Reflection", "Assembly");
1859 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
1860 res->assembly = assembly;
1861 CACHE_OBJECT (assembly, res);
1866 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
1868 if ((t1->type != t2->type) ||
1869 (t1->byref != t2->byref))
1873 case MONO_TYPE_VOID:
1874 case MONO_TYPE_BOOLEAN:
1875 case MONO_TYPE_CHAR:
1886 case MONO_TYPE_STRING:
1889 case MONO_TYPE_OBJECT:
1891 case MONO_TYPE_VALUETYPE:
1892 case MONO_TYPE_CLASS:
1893 return t1->data.klass == t2->data.klass;
1895 case MONO_TYPE_SZARRAY:
1896 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
1898 g_error ("implement type compare for %0x!", t1->type);
1906 mymono_metadata_type_hash (MonoType *t1)
1912 hash |= t1->byref << 6; /* do not collide with t1->type values */
1914 case MONO_TYPE_VALUETYPE:
1915 case MONO_TYPE_CLASS:
1916 /* check if the distribution is good enough */
1917 return hash << 7 | g_str_hash (t1->data.klass->name);
1919 case MONO_TYPE_SZARRAY:
1920 return hash << 7 | mymono_metadata_type_hash (t1->data.type);
1926 mono_type_get_object (MonoDomain *domain, MonoType *type)
1928 MonoReflectionType *res;
1929 MonoClass *klass = mono_class_from_mono_type (type);
1932 type_cache = g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
1933 (GCompareFunc)mymono_metadata_type_equal);
1934 if ((res = g_hash_table_lookup (type_cache, type)))
1936 if (klass->reflection_info) {
1937 /* should this be considered an error condition? */
1939 return klass->reflection_info;
1941 mono_class_init (klass);
1942 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
1944 g_hash_table_insert (type_cache, type, res);
1948 MonoReflectionMethod*
1949 mono_method_get_object (MonoDomain *domain, MonoMethod *method)
1952 * We use the same C representation for methods and constructors, but the type
1953 * name in C# is different.
1957 MonoReflectionMethod *ret;
1959 CHECK_OBJECT (MonoReflectionMethod *, method);
1960 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
1961 cname = "MonoCMethod";
1963 cname = "MonoMethod";
1964 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
1966 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
1967 ret->method = method;
1968 CACHE_OBJECT (method, ret);
1972 MonoReflectionField*
1973 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
1975 MonoReflectionField *res;
1978 CHECK_OBJECT (MonoReflectionField *, field);
1979 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
1980 res = (MonoReflectionField *)mono_object_new (domain, oklass);
1983 CACHE_OBJECT (field, res);
1987 MonoReflectionProperty*
1988 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
1990 MonoReflectionProperty *res;
1993 CHECK_OBJECT (MonoReflectionProperty *, property);
1994 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
1995 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
1997 res->property = property;
1998 CACHE_OBJECT (property, res);
2002 MonoReflectionEvent*
2003 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
2005 MonoReflectionEvent *res;
2008 CHECK_OBJECT (MonoReflectionEvent *, event);
2009 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
2010 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
2013 CACHE_OBJECT (event, res);
2017 MonoReflectionParameter**
2018 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
2020 MonoReflectionParameter **res;
2021 MonoReflectionMethod *member;
2026 if (!method->signature->param_count)
2029 member = mono_method_get_object (domain, method);
2030 names = g_new (char *, method->signature->param_count);
2031 mono_method_get_param_names (method, (const char **) names);
2033 /* Note: the cache is based on the address of the signature into the method
2034 * since we already cache MethodInfos with the method as keys.
2036 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature));
2037 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
2038 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
2039 for (i = 0; i < method->signature->param_count; ++i) {
2040 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
2041 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
2042 res [i]->DefaultValueImpl = NULL; /* FIXME */
2043 res [i]->MemberImpl = (MonoObject*)member;
2044 res [i]->NameImpl = mono_string_new (domain, names [i]);
2045 res [i]->PositionImpl = i + 1;
2046 res [i]->AttrsImpl = method->signature->params [i]->attrs;
2049 CACHE_OBJECT (&(method->signature), res);
2054 * Parse a type name as accepted by the GetType () method and output the info
2055 * extracted in the info structure.
2056 * the name param will be mangled, so, make a copy before passing it to this function.
2057 * The fields in info will be valid until the memory pointed to by name is valid.
2058 * Returns 0 on parse error.
2061 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
2063 char *start, *p, *w, *last_point;
2064 int in_modifiers = 0;
2066 start = p = w = name;
2068 info->name = info->name_space = info->assembly = NULL;
2069 info->nest_name = info->nest_name_space = NULL;
2070 info->rank = info->isbyref = info->ispointer = 0;
2077 /* we have parsed the nesting namespace + name */
2079 info->nest_name_space = start;
2081 info->nest_name = last_point + 1;
2083 info->nest_name_space = "";
2084 info->nest_name = start;
2086 *p = 0; /* NULL terminate */
2111 info->name_space = start;
2113 info->name = last_point + 1;
2115 info->name_space = "";
2118 /* FIXME: we don't mainatin an order for byref, pointer and array... */
2126 info->ispointer = 1;
2152 return 0; /* missing assembly name */
2159 *w = 0; /* terminate class name */
2160 if (!info->name || !*info->name)
2162 if (info->nest_name && !*info->nest_name)
2164 /* add other consistency checks */
2169 dummy_runtime_invoke (MonoMethod *method, void *obj, void **params)
2171 g_error ("runtime invoke called on uninitialized runtime");
2175 MonoInvokeFunc mono_default_runtime_invoke = dummy_runtime_invoke;
2178 mono_install_runtime_invoke (MonoInvokeFunc func) {
2180 mono_default_runtime_invoke = func;
2182 mono_default_runtime_invoke = dummy_runtime_invoke;
2186 mono_runtime_invoke (MonoMethod *method, void *obj, void **params)
2188 return mono_default_runtime_invoke (method, obj, params);;
2192 * Optimization we could avoid mallocing() an little-endian archs that
2193 * don't crash with unaligned accesses.
2196 fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
2197 int len, i, slen, type;
2198 const char *p = mono_metadata_blob_heap (image, blobidx);
2200 len = mono_metadata_decode_value (p, &p);
2201 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
2206 for (i = 0; i < sig->param_count; ++i) {
2207 type = sig->params [i]->type;
2212 case MONO_TYPE_BOOLEAN: {
2213 MonoBoolean *bval = params [i] = g_malloc (sizeof (MonoBoolean));
2218 case MONO_TYPE_CHAR:
2220 case MONO_TYPE_I2: {
2221 guint16 *val = params [i] = g_malloc (sizeof (guint16));
2226 #if SIZEOF_VOID_P == 4
2232 case MONO_TYPE_I4: {
2233 guint32 *val = params [i] = g_malloc (sizeof (guint32));
2238 #if SIZEOF_VOID_P == 8
2239 case MONO_TYPE_U: /* error out instead? this should probably not happen */
2244 case MONO_TYPE_I8: {
2245 guint64 *val = params [i] = g_malloc (sizeof (guint64));
2250 case MONO_TYPE_VALUETYPE:
2251 if (sig->params [i]->data.klass->enumtype) {
2252 type = sig->params [i]->data.klass->enum_basetype->type;
2255 g_warning ("generic valutype %s not handled in custom attr value decoding", sig->params [i]->data.klass->name);
2258 case MONO_TYPE_STRING: {
2259 slen = mono_metadata_decode_value (p, &p);
2260 params [i] = mono_string_new_len (mono_domain_get (), p, slen);
2265 g_warning ("Type %02x not handled in custom attr value decoding", sig->params [i]->type);
2272 free_param_data (MonoMethodSignature *sig, void **params) {
2274 for (i = 0; i < sig->param_count; ++i) {
2275 switch (sig->params [i]->type) {
2276 case MONO_TYPE_BOOLEAN:
2277 case MONO_TYPE_CHAR:
2290 case MONO_TYPE_VALUETYPE:
2291 g_free (params [i]);
2300 * Find the method index in the metadata methodDef table.
2301 * Later put these three helper methods in metadata and export them.
2304 find_method_index (MonoMethod *method) {
2305 MonoClass *klass = method->klass;
2308 for (i = 0; i < klass->method.count; ++i) {
2309 if (method == klass->methods [i])
2310 return klass->method.first + 1 + i;
2316 * Find the field index in the metadata FieldDef table.
2319 find_field_index (MonoClass *klass, MonoClassField *field) {
2322 for (i = 0; i < klass->field.count; ++i) {
2323 if (field == &klass->fields [i])
2324 return klass->field.first + 1 + i;
2330 * Find the property index in the metadata Property table.
2333 find_property_index (MonoClass *klass, MonoProperty *property) {
2336 for (i = 0; i < klass->property.count; ++i) {
2337 if (property == &klass->properties [i])
2338 return klass->property.first + 1 + i;
2344 * Find the event index in the metadata Event table.
2347 find_event_index (MonoClass *klass, MonoEvent *event) {
2350 for (i = 0; i < klass->event.count; ++i) {
2351 if (event == &klass->events [i])
2352 return klass->event.first + 1 + i;
2358 mono_reflection_get_custom_attrs (MonoObject *obj)
2360 guint32 index, mtoken, i;
2361 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
2371 klass = obj->vtable->klass;
2372 /* FIXME: need to handle: Module */
2373 if (klass == mono_defaults.monotype_class) {
2374 MonoReflectionType *rtype = (MonoReflectionType*)obj;
2375 klass = mono_class_from_mono_type (rtype->type);
2376 index = mono_metadata_token_index (klass->type_token);
2377 index <<= CUSTOM_ATTR_BITS;
2378 index |= CUSTOM_ATTR_TYPEDEF;
2379 image = klass->image;
2380 } else if (strcmp ("Assembly", klass->name) == 0) {
2381 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
2382 index = 1; /* there is only one assembly */
2383 index <<= CUSTOM_ATTR_BITS;
2384 index |= CUSTOM_ATTR_ASSEMBLY;
2385 image = rassembly->assembly->image;
2386 } else if (strcmp ("MonoProperty", klass->name) == 0) {
2387 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
2388 index = find_property_index (rprop->klass, rprop->property);
2389 index <<= CUSTOM_ATTR_BITS;
2390 index |= CUSTOM_ATTR_PROPERTY;
2391 image = rprop->klass->image;
2392 } else if (strcmp ("MonoEvent", klass->name) == 0) {
2393 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
2394 index = find_event_index (revent->klass, revent->event);
2395 index <<= CUSTOM_ATTR_BITS;
2396 index |= CUSTOM_ATTR_EVENT;
2397 image = revent->klass->image;
2398 } else if (strcmp ("MonoField", klass->name) == 0) {
2399 MonoReflectionField *rfield = (MonoReflectionField*)obj;
2400 index = find_field_index (rfield->klass, rfield->field);
2401 index <<= CUSTOM_ATTR_BITS;
2402 index |= CUSTOM_ATTR_FIELDDEF;
2403 image = rfield->klass->image;
2404 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
2405 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
2406 index = find_method_index (rmethod->method);
2407 index <<= CUSTOM_ATTR_BITS;
2408 index |= CUSTOM_ATTR_METHODDEF;
2409 image = method->klass->image;
2410 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
2411 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
2412 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
2413 guint32 method_index = find_method_index (rmethod->method);
2414 guint32 param_list, param_last, param_pos, found;
2416 image = rmethod->method->klass->image;
2417 ca = &image->tables [MONO_TABLE_METHOD];
2419 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
2420 if (method_index == ca->rows) {
2421 ca = &image->tables [MONO_TABLE_PARAM];
2422 param_last = ca->rows + 1;
2424 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
2425 ca = &image->tables [MONO_TABLE_PARAM];
2428 for (i = param_list; i < param_last; ++i) {
2429 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
2430 if (param_pos == param->PositionImpl) {
2436 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
2438 index <<= CUSTOM_ATTR_BITS;
2439 index |= CUSTOM_ATTR_PARAMDEF;
2440 } else { /* handle other types here... */
2441 g_error ("get custom attrs not yet supported for %s", klass->name);
2444 /* at this point image and index are set correctly for searching the custom attr */
2445 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2446 /* the table is not sorted */
2447 for (i = 0; i < ca->rows; ++i) {
2448 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
2449 if (cols [MONO_CUSTOM_ATTR_PARENT] != index)
2451 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
2452 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
2453 case CUSTOM_ATTR_TYPE_METHODDEF:
2454 mtoken |= MONO_TOKEN_METHOD_DEF;
2456 case CUSTOM_ATTR_TYPE_MEMBERREF:
2457 mtoken |= MONO_TOKEN_MEMBER_REF;
2460 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
2463 method = mono_get_method (image, mtoken, NULL);
2465 g_error ("Can't find custom attr constructor");
2466 mono_class_init (method->klass);
2467 /*g_print ("got attr %s\n", method->klass->name);*/
2468 params = g_new (void*, method->signature->param_count);
2469 fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
2470 attr = mono_object_new (mono_domain_get (), method->klass);
2471 mono_runtime_invoke (method, attr, params);
2472 list = g_list_prepend (list, attr);
2473 free_param_data (method->signature, params);
2477 index = g_list_length (list);
2479 * The return type is really object[], but System/Attribute.cs does a cast
2480 * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
2481 * probably fix that.
2483 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
2484 result = mono_array_new (mono_domain_get (), klass, index);
2485 for (i = 0; i < index; ++i) {
2486 mono_array_set (result, gpointer, i, list->data);
2489 g_list_free (g_list_first (list));
2495 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *porpValues, MonoArray *fields, MonoArray* fieldValues) {
2497 MonoMethodSignature *sig;
2499 char *buffer, *p, *argval;
2500 guint32 buflen, i, type;
2502 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
2503 g_warning ("ConstructorBuilder Custom attribute not yet supported");
2505 * maybe we should have a param array to method signature function and
2506 * continue with the normal codepath.
2508 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, 4);
2509 mono_array_set (result, char, 0, 1);
2513 p = buffer = g_malloc (buflen);
2514 /* write the prolog */
2517 sig = ((MonoReflectionMethod*)ctor)->method->signature;
2518 /* FIXME: ENOENDIAN */
2519 for (i = 0; i < sig->param_count; ++i) {
2520 if ((p-buffer) + 10 >= buflen) {
2523 newbuf = g_realloc (buffer, buflen);
2524 p = newbuf + (p-buffer);
2527 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
2528 argval = ((char*)arg + sizeof (MonoObject));
2529 type = sig->params [i]->type;
2532 case MONO_TYPE_BOOLEAN:
2537 case MONO_TYPE_CHAR:
2539 case MONO_TYPE_I2: {
2540 guint16 *val = (guint16*)p;
2541 *val = *(guint16*)argval;
2547 case MONO_TYPE_R4: {
2548 guint32 *val = (guint32*)p;
2549 *val = *(guint32*)argval;
2555 case MONO_TYPE_R8: {
2556 guint64 *val = (guint64*)p;
2557 *val = *(guint64*)argval;
2561 case MONO_TYPE_VALUETYPE:
2562 if (sig->params [i]->data.klass->enumtype) {
2563 type = sig->params [i]->data.klass->enum_basetype->type;
2566 g_warning ("generic valutype %s not handled in custom attr value decoding", sig->params [i]->data.klass->name);
2569 case MONO_TYPE_STRING: {
2570 char *str = mono_string_to_utf8 ((MonoString*)arg);
2571 guint32 slen = strlen (str);
2572 if ((p-buffer) + 10 + slen >= buflen) {
2576 newbuf = g_realloc (buffer, buflen);
2577 p = newbuf + (p-buffer);
2580 mono_metadata_encode_value (slen, p, &p);
2581 memcpy (p, str, slen);
2587 g_error ("type 0x%02x not yet supported in custom attr encoder", type);
2591 * we don't support properties and fields, yet, set to 0.
2595 buflen = p - buffer;
2596 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
2597 p = mono_array_addr (result, char, 0);
2598 memcpy (p, buffer, buflen);
2604 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
2606 MonoClass *klass, *parent;
2608 klass = g_new0 (MonoClass, 1);
2610 klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
2613 parent = mono_class_from_mono_type (tb->parent->type);
2615 klass->inited = 1; /* we lie to the runtime */
2616 klass->name = mono_string_to_utf8 (tb->name);
2617 klass->name_space = mono_string_to_utf8 (tb->nspace);
2618 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
2619 klass->flags = tb->attrs;
2621 klass->element_class = klass;
2622 klass->reflection_info = tb; /* need to pin. */
2624 mono_class_setup_parent (klass, parent);
2625 mono_class_setup_mono_type (klass);
2628 * FIXME: handle interfaces.
2631 tb->type.type = &klass->byval_arg;
2633 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/