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)
228 MonoReflectionTypeBuilder *tb;
232 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
236 encode_type (assembly, type->type, p, endbuf);
240 tb = (MonoReflectionTypeBuilder*) type;
241 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS); /* typedef */
243 /* FIXME: handle other base types (need to have also some hacks to compile corlib) ... */
244 /* FIXME: handle byref ... */
245 mono_metadata_encode_value (MONO_TYPE_CLASS, p, &p);
246 mono_metadata_encode_value (token, p, endbuf);
247 /*g_print ("encoding type %s to 0x%08x\n", mono_string_to_utf8 (tb->name), token);*/
251 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
256 guint32 nparams = sig->param_count;
257 guint32 size = 10 + nparams * 10;
262 p = buf = g_malloc (size);
264 * FIXME: vararg, explicit_this, differenc call_conv values...
266 *p = sig->call_convention;
268 *p |= 0x20; /* hasthis */
270 mono_metadata_encode_value (nparams, p, &p);
271 encode_type (assembly, sig->ret, p, &p);
272 for (i = 0; i < nparams; ++i)
273 encode_type (assembly, sig->params [i], p, &p);
275 mono_metadata_encode_value (p-buf, b, &b);
276 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
277 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
283 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
286 * FIXME: reuse code from method_encode_signature().
291 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
292 guint32 size = 10 + nparams * 10;
297 p = buf = g_malloc (size);
298 /* LAMESPEC: all the call conv spec is foobared */
299 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
300 if (mb->call_conv & 2)
301 *p |= 0x5; /* vararg */
302 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
303 *p |= 0x20; /* hasthis */
305 mono_metadata_encode_value (nparams, p, &p);
306 encode_reflection_type (assembly, mb->rtype, p, &p);
307 for (i = 0; i < nparams; ++i) {
308 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
309 encode_reflection_type (assembly, pt, p, &p);
312 mono_metadata_encode_value (p-buf, b, &b);
313 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
314 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
320 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
322 MonoDynamicTable *table;
325 guint32 idx, sig_idx;
326 guint nl = mono_array_length (ilgen->locals);
332 p = buf = g_malloc (10 + nl * 10);
333 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
334 idx = table->next_idx ++;
336 alloc_table (table, table->rows);
337 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
339 mono_metadata_encode_value (0x07, p, &p);
340 mono_metadata_encode_value (nl, p, &p);
341 for (i = 0; i < nl; ++i) {
342 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
343 encode_reflection_type (assembly, lb->type, p, &p);
345 mono_metadata_encode_value (p-buf, b, &b);
346 sig_idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
347 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
350 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
356 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
358 /* we use only tiny formats now: need to implement ILGenerator */
363 gint32 num_locals = 0;
364 gint32 num_exception = 0;
367 char fat_header [12];
370 guint32 local_sig = 0;
371 guint32 header_size = 12;
374 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
375 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
376 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
377 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
381 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
383 code = mb->ilgen->code;
384 code_size = mb->ilgen->code_len;
385 max_stack = mb->ilgen->max_stack;
386 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
387 if (mb->ilgen->ex_handlers) {
388 MonoILExceptionInfo *ex_info;
389 for (i = 0; i < mono_array_length (mb->ilgen->ex_handlers); ++i) {
390 ex_info = (MonoILExceptionInfo*)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
391 if (ex_info->handlers)
392 num_exception += mono_array_length (ex_info->handlers);
399 code_size = mono_array_length (code);
400 max_stack = 8; /* we probably need to run a verifier on the code... */
403 /* check for exceptions, maxstack, locals */
404 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
406 if (code_size < 64 && !(code_size & 1)) {
407 flags = (code_size << 2) | 0x2;
408 } else if (code_size < 32 && (code_size & 1)) {
409 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
413 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
414 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
415 return assembly->text_rva + idx + CLI_H_SIZE;
419 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
421 * FIXME: need to set also the header size in fat_flags.
422 * (and more sects and init locals flags)
426 fat_flags |= METHOD_HEADER_MORE_SECTS;
427 fat_header [0] = fat_flags;
428 fat_header [1] = (header_size / 4 ) << 4;
429 shortp = (guint16*)(fat_header + 2);
431 intp = (guint32*)(fat_header + 4);
433 intp = (guint32*)(fat_header + 8);
435 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
436 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
438 unsigned char sheader [4];
439 MonoExceptionClause clause;
440 MonoILExceptionInfo * ex_info;
441 MonoILExceptionBlock * ex_block;
444 stream_data_align (&assembly->code);
445 /* always use fat format for now */
446 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
447 num_exception *= sizeof (MonoExceptionClause);
448 sheader [1] = num_exception & 0xff;
449 sheader [2] = (num_exception >> 8) & 0xff;
450 sheader [3] = (num_exception >> 16) & 0xff;
451 mono_image_add_stream_data (&assembly->code, sheader, 4);
452 /* fat header, so we are already aligned */
454 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
455 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
456 if (ex_info->handlers) {
457 int finally_start = 0;
458 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
459 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
460 clause.flags = ex_block->type;
461 clause.try_offset = ex_info->start;
462 /* need fault, too, probably */
463 if (clause.flags == MONO_EXCEPTION_CLAUSE_FINALLY)
464 clause.try_len = finally_start - ex_info->start;
466 clause.try_len = ex_info->len;
467 clause.handler_offset = ex_block->start;
468 clause.handler_len = ex_block->len;
469 finally_start = clause.handler_offset + clause.handler_len;
470 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
471 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
472 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d\n",
473 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len);*/
474 /* FIXME: ENOENDIAN */
475 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
478 g_error ("No clauses");
482 return assembly->text_rva + idx + CLI_H_SIZE;
486 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 index)
489 MonoDynamicTable *table;
492 table = &assembly->tables [table_idx];
494 g_assert (col < table->columns);
496 values = table->values + table->columns;
497 for (i = 1; i <= table->rows; ++i) {
498 if (values [col] == index)
505 * index is the table index of the object
506 * type is one of CUSTOM_ATTR_*
509 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 index, guint32 type, MonoArray *cattrs)
511 MonoDynamicTable *table;
512 MonoReflectionCustomAttr *cattr;
514 guint32 count, i, token;
518 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
521 count = mono_array_length (cattrs);
522 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
523 table->rows += count;
524 alloc_table (table, table->rows);
525 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
526 index <<= CUSTOM_ATTR_BITS;
528 for (i = 0; i < count; ++i) {
529 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
530 values [MONO_CUSTOM_ATTR_PARENT] = index;
531 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
532 type = mono_metadata_token_index (token);
533 type <<= CUSTOM_ATTR_TYPE_BITS;
534 switch (mono_metadata_token_table (token)) {
535 case MONO_TABLE_METHOD:
536 type |= CUSTOM_ATTR_TYPE_METHODDEF;
538 case MONO_TABLE_MEMBERREF:
539 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
542 g_error ("got wrong token in custom attr");
544 values [MONO_CUSTOM_ATTR_TYPE] = type;
546 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
547 values [MONO_CUSTOM_ATTR_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, p - blob_size);
548 mono_image_add_stream_data (&assembly->blob,
549 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
550 values += MONO_CUSTOM_ATTR_SIZE;
556 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
558 MonoDynamicTable *table;
563 /* room in this table is already allocated */
564 table = &assembly->tables [MONO_TABLE_METHOD];
565 *mb->table_idx = table->next_idx ++;
566 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
568 name = mono_string_to_utf8 (mb->name);
569 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
571 } else { /* a constructor */
572 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
574 values [MONO_METHOD_FLAGS] = mb->attrs;
575 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
576 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
577 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
579 table = &assembly->tables [MONO_TABLE_PARAM];
580 values [MONO_METHOD_PARAMLIST] = table->next_idx;
584 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
585 if (mono_array_get (mb->pinfo, gpointer, i))
588 table->rows += count;
589 alloc_table (table, table->rows);
590 values = table->values + table->next_idx * MONO_PARAM_SIZE;
591 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
592 MonoReflectionParamBuilder *pb;
593 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
594 values [MONO_PARAM_FLAGS] = pb->attrs;
595 values [MONO_PARAM_SEQUENCE] = i;
596 name = mono_string_to_utf8 (pb->name);
597 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
599 values += MONO_PARAM_SIZE;
601 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
608 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
610 MonoDynamicTable *table;
613 ReflectionMethodBuilder rmb;
615 rmb.ilgen = mb->ilgen;
616 rmb.rtype = mb->rtype;
617 rmb.parameters = mb->parameters;
618 rmb.pinfo = mb->pinfo;
619 rmb.attrs = mb->attrs;
620 rmb.iattrs = mb->iattrs;
621 rmb.call_conv = mb->call_conv;
625 rmb.table_idx = &mb->table_idx;
627 mono_image_basic_method (&rmb, assembly);
629 if (mb->dll) { /* It's a P/Invoke method */
631 table = &assembly->tables [MONO_TABLE_IMPLMAP];
633 alloc_table (table, table->rows);
634 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
635 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
636 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
637 name = mono_string_to_utf8 (mb->dllentry);
638 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
640 name = mono_string_to_utf8 (mb->dll);
641 moduleref = string_heap_insert (&assembly->sheap, name);
643 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
644 table = &assembly->tables [MONO_TABLE_MODULEREF];
646 alloc_table (table, table->rows);
647 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
648 values [MONO_IMPLMAP_SCOPE] = table->rows;
651 if (mb->override_method) {
652 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
653 table = &assembly->tables [MONO_TABLE_METHODIMPL];
655 alloc_table (table, table->rows);
656 values = table->values + table->rows * MONO_MTHODIMPL_SIZE;
657 values [MONO_MTHODIMPL_CLASS] = tb->table_idx;
658 values [MONO_MTHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
659 if (mb->override_method->method)
660 values [MONO_MTHODIMPL_DECLARATION] = mono_image_get_methodref_token (assembly, mb->override_method->method);
662 MonoReflectionMethodBuilder *omb = (MonoReflectionMethodBuilder*)mb->override_method;
663 values [MONO_MTHODIMPL_DECLARATION] = METHODDEFORREF_METHODDEF | (omb->table_idx << METHODDEFORREF_BITS);
666 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
670 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
672 ReflectionMethodBuilder rmb;
674 rmb.ilgen = mb->ilgen;
675 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
676 rmb.parameters = mb->parameters;
677 rmb.pinfo = mb->pinfo;
678 rmb.attrs = mb->attrs;
679 rmb.iattrs = mb->iattrs;
680 rmb.call_conv = mb->call_conv;
684 rmb.table_idx = &mb->table_idx;
686 mono_image_basic_method (&rmb, assembly);
687 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
692 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
700 p = buf = g_malloc (64);
702 /* No start code with field refs...
703 * mono_metadata_encode_value (0x06, p, &p);
705 /* encode custom attributes before the type */
706 encode_type (assembly, field->type, p, &p);
707 g_assert (p-buf < 64);
708 mono_metadata_encode_value (p-buf, b, &b);
709 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
710 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
716 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
724 p = buf = g_malloc (64);
726 mono_metadata_encode_value (0x06, p, &p);
727 /* encode custom attributes before the type */
728 encode_reflection_type (assembly, fb->type, p, &p);
729 g_assert (p-buf < 64);
730 mono_metadata_encode_value (p-buf, b, &b);
731 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
732 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
738 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
745 p = buf = g_malloc (64);
747 box_val = ((char*)val) + sizeof (MonoObject);
748 *ret_type = val->vtable->klass->byval_arg.type;
750 case MONO_TYPE_BOOLEAN:
770 case MONO_TYPE_STRING:
772 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
775 /* there is no signature */
776 mono_metadata_encode_value (len, b, &b);
777 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
778 /* FIXME: ENOENDIAN */
779 mono_image_add_stream_data (&assembly->blob, box_val, len);
786 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
788 MonoDynamicTable *table;
792 table = &assembly->tables [MONO_TABLE_FIELD];
793 fb->table_idx = table->next_idx ++;
794 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
795 name = mono_string_to_utf8 (fb->name);
796 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
798 values [MONO_FIELD_FLAGS] = fb->attrs;
799 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
801 if (fb->offset != -1) {
802 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
804 alloc_table (table, table->rows);
805 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
806 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
807 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
809 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
810 guint32 field_type = 0;
811 table = &assembly->tables [MONO_TABLE_CONSTANT];
813 alloc_table (table, table->rows);
814 values = table->values + table->rows * MONO_CONSTANT_SIZE;
815 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
816 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
817 values [MONO_CONSTANT_TYPE] = field_type;
818 values [MONO_CONSTANT_PADDING] = 0;
822 table = &assembly->tables [MONO_TABLE_FIELDRVA];
824 alloc_table (table, table->rows);
825 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
826 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
828 * We store it in the code section because it's simpler for now.
830 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
831 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva + CLI_H_SIZE;
833 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
837 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
843 MonoReflectionMethodBuilder *mb = fb->get_method;
846 if (mb && mb->parameters)
847 nparams = mono_array_length (mb->parameters);
848 buf = p = g_malloc (24 + nparams * 10);
851 mono_metadata_encode_value (nparams, p, &p);
853 encode_reflection_type (assembly, mb->rtype, p, &p);
854 for (i = 0; i < nparams; ++i) {
855 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
856 encode_reflection_type (assembly, pt, p, &p);
859 *p++ = 1; /* void: a property should probably not be allowed without a getter */
862 mono_metadata_encode_value (p-buf, b, &b);
863 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
864 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
870 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
872 MonoDynamicTable *table;
875 guint num_methods = 0;
879 * we need to set things in the following tables:
880 * PROPERTYMAP (info already filled in _get_type_info ())
881 * PROPERTY (rows already preallocated in _get_type_info ())
882 * METHOD (method info already done with the generic method code)
885 table = &assembly->tables [MONO_TABLE_PROPERTY];
886 pb->table_idx = table->next_idx ++;
887 values = table->values + pb->table_idx * MONO_FIELD_SIZE;
888 name = mono_string_to_utf8 (pb->name);
889 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
891 values [MONO_PROPERTY_FLAGS] = pb->attrs;
892 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
894 /* FIXME: we still don't handle 'other' methods */
895 if (pb->get_method) num_methods ++;
896 if (pb->set_method) num_methods ++;
898 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
899 table->rows += num_methods;
900 alloc_table (table, table->rows);
902 if (pb->get_method) {
903 semaidx = table->next_idx ++;
904 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
905 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
906 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
907 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
909 if (pb->set_method) {
910 semaidx = table->next_idx ++;
911 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
912 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
913 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
914 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
916 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
920 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
922 if (image != mono_defaults.corlib)
923 g_error ("multiple assemblyref not yet supported");
924 /* first row in assemblyref */
925 return (1 << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_ASSEMBLYREF;
929 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
931 MonoDynamicTable *table;
936 if (!assembly->typeref)
937 assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
939 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
942 klass = type->data.klass;
944 * If it's in the same module:
945 * return TYPEDEFORREF_TYPEDEF | ((klass->token & 0xffffff) << TYPEDEFORREF_BITS)
948 table = &assembly->tables [MONO_TABLE_TYPEREF];
949 alloc_table (table, table->rows + 1);
950 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
951 values [MONO_TYPEREF_SCOPE] = resolution_scope_from_image (assembly, klass->image);
952 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
953 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
954 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
955 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
961 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoClass *klass, const char *name, guint32 sig)
963 MonoDynamicTable *table;
965 guint32 token, pclass;
968 parent = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
969 switch (parent & TYPEDEFORREF_MASK) {
970 case TYPEDEFORREF_TYPEREF:
971 pclass = MEMBERREF_PARENT_TYPEREF;
973 case TYPEDEFORREF_TYPESPEC:
974 pclass = MEMBERREF_PARENT_TYPESPEC;
976 case TYPEDEFORREF_TYPEDEF:
977 /* should never get here */
979 g_error ("unknow typeref or def token");
981 /* extract the index */
982 parent >>= TYPEDEFORREF_BITS;
984 table = &assembly->tables [MONO_TABLE_MEMBERREF];
985 alloc_table (table, table->rows + 1);
986 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
987 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
988 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
989 values [MONO_MEMBERREF_SIGNATURE] = sig;
990 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
997 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1000 if (!assembly->typeref)
1001 assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
1003 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, method));
1006 token = mono_image_get_memberref_token (assembly, method->klass,
1007 method->name, method_encode_signature (assembly, method->signature));
1008 g_hash_table_insert (assembly->typeref, method, GUINT_TO_POINTER(token));
1013 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1016 if (!assembly->typeref)
1017 assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
1019 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, field));
1022 token = mono_image_get_memberref_token (assembly, klass,
1023 field->name, fieldref_encode_signature (assembly, field));
1024 g_hash_table_insert (assembly->typeref, field, GUINT_TO_POINTER(token));
1029 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1031 MonoDynamicTable *table;
1036 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1037 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1038 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1039 if (tb->parent) { /* interfaces don't have a parent */
1040 if (tb->parent->type)
1041 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1043 MonoReflectionTypeBuilder *ptb = (MonoReflectionTypeBuilder *)tb->parent;
1044 values [MONO_TYPEDEF_EXTENDS] = TYPEDEFORREF_TYPEDEF | (ptb->table_idx << TYPEDEFORREF_BITS);
1047 values [MONO_TYPEDEF_EXTENDS] = 0;
1048 n = mono_string_to_utf8 (tb->name);
1049 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1051 n = mono_string_to_utf8 (tb->nspace);
1052 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1054 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1055 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1058 * if we have explicitlayout or sequentiallayouts, output data in the
1059 * ClassLayout table.
1061 if ((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1062 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1064 alloc_table (table, table->rows);
1065 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1066 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1067 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1068 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1072 * FIXME: constructors and methods need to be output in the same order
1073 * as they are defined (according to table_idx).
1076 /* handle constructors */
1078 table = &assembly->tables [MONO_TABLE_METHOD];
1079 table->rows += mono_array_length (tb->ctors);
1080 alloc_table (table, table->rows);
1081 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1082 mono_image_get_ctor_info (domain,
1083 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1086 /* handle methods */
1088 table = &assembly->tables [MONO_TABLE_METHOD];
1089 table->rows += mono_array_length (tb->methods);
1090 alloc_table (table, table->rows);
1091 for (i = 0; i < mono_array_length (tb->methods); ++i)
1092 mono_image_get_method_info (
1093 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1098 table = &assembly->tables [MONO_TABLE_FIELD];
1099 table->rows += mono_array_length (tb->fields);
1100 alloc_table (table, table->rows);
1101 for (i = 0; i < mono_array_length (tb->fields); ++i)
1102 mono_image_get_field_info (
1103 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1106 /* Do the same with properties etc.. */
1107 if (tb->properties && mono_array_length (tb->properties)) {
1108 table = &assembly->tables [MONO_TABLE_PROPERTY];
1109 table->rows += mono_array_length (tb->properties);
1110 alloc_table (table, table->rows);
1111 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1113 alloc_table (table, table->rows);
1114 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1115 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1116 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1117 for (i = 0; i < mono_array_length (tb->properties); ++i)
1118 mono_image_get_property_info (
1119 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1122 MonoDynamicTable *ntable;
1124 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1125 table->rows += mono_array_length (tb->subtypes);
1126 alloc_table (table, table->rows);
1128 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1129 ntable->rows += mono_array_length (tb->subtypes);
1130 alloc_table (ntable, ntable->rows);
1131 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1133 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1134 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1136 mono_image_get_type_info (domain, subtype, assembly);
1137 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1138 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1139 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1140 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1141 mono_string_to_utf8 (tb->name), tb->table_idx,
1142 ntable->next_idx, ntable->rows);*/
1143 values += MONO_NESTED_CLASS_SIZE;
1147 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1151 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1153 MonoDynamicTable *table;
1157 table = &assembly->tables [MONO_TABLE_MODULE];
1158 mb->table_idx = table->next_idx ++;
1159 name = mono_string_to_utf8 (mb->module.name);
1160 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1162 /* need to set mvid? */
1164 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1166 * fill-in info in other tables as well.
1168 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1169 table->rows += mono_array_length (mb->types);
1170 alloc_table (table, table->rows);
1172 * We assign here the typedef indexes to avoid mismatches if a type that
1173 * has not yet been stored in the tables is referenced by another type.
1175 for (i = 0; i < mono_array_length (mb->types); ++i) {
1177 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1178 type->table_idx = table->next_idx ++;
1179 if (!type->subtypes)
1181 for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1182 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1183 subtype->table_idx = table->next_idx ++;
1186 for (i = 0; i < mono_array_length (mb->types); ++i)
1187 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1190 #define align_pointer(base,p)\
1192 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1194 (p) += 4 - (__diff & 3);\
1198 build_compressed_metadata (MonoDynamicAssembly *assembly)
1201 guint64 valid_mask = 0;
1202 guint32 heapt_size = 0;
1203 guint32 meta_size = 256; /* allow for header and other stuff */
1204 guint32 table_offset;
1205 guint32 ntables = 0;
1211 char *version = "mono" VERSION;
1213 /* Compute table sizes */
1214 meta = assembly->assembly.image = g_new0 (MonoImage, 1);
1216 /* Setup the info used by compute_sizes () */
1217 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1218 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1219 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1221 meta_size += assembly->blob.index;
1222 meta_size += assembly->guid.index;
1223 meta_size += assembly->sheap.index;
1224 meta_size += assembly->us.index;
1226 for (i=0; i < 64; ++i)
1227 meta->tables [i].rows = assembly->tables [i].rows;
1229 for (i = 0; i < 64; i++){
1230 if (meta->tables [i].rows == 0)
1232 valid_mask |= (guint64)1 << i;
1234 meta->tables [i].row_size = mono_metadata_compute_size (
1235 meta, i, &meta->tables [i].size_bitfield);
1236 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1238 heapt_size += 24; /* #~ header size */
1239 heapt_size += ntables * 4;
1240 meta_size += heapt_size;
1241 meta->raw_metadata = g_malloc0 (meta_size);
1242 p = meta->raw_metadata;
1243 /* the metadata signature */
1244 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1245 /* version numbers and 4 bytes reserved */
1246 int16val = (guint16*)p;
1250 /* version string */
1251 int32val = (guint32*)p;
1252 *int32val = strlen (version);
1254 memcpy (p, version, *int32val);
1256 align_pointer (meta->raw_metadata, p);
1257 int16val = (guint16*)p;
1258 *int16val++ = 0; /* flags must be 0 */
1259 *int16val = 5; /* number of streams */
1263 * write the stream info.
1265 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1266 table_offset += 3; table_offset &= ~3;
1268 int32val = (guint32*)p;
1269 *int32val++ = assembly->tstream.offset = table_offset;
1270 *int32val = heapt_size;
1271 table_offset += *int32val;
1272 table_offset += 3; table_offset &= ~3;
1276 align_pointer (meta->raw_metadata, p);
1278 int32val = (guint32*)p;
1279 *int32val++ = assembly->sheap.offset = table_offset;
1280 *int32val = assembly->sheap.index;
1281 table_offset += *int32val;
1282 table_offset += 3; table_offset &= ~3;
1284 strcpy (p, "#Strings");
1286 align_pointer (meta->raw_metadata, p);
1288 int32val = (guint32*)p;
1289 *int32val++ = assembly->us.offset = table_offset;
1290 *int32val = assembly->us.index;
1291 table_offset += *int32val;
1292 table_offset += 3; table_offset &= ~3;
1296 align_pointer (meta->raw_metadata, p);
1298 int32val = (guint32*)p;
1299 *int32val++ = assembly->blob.offset = table_offset;
1300 *int32val = assembly->blob.index;
1301 table_offset += *int32val;
1302 table_offset += 3; table_offset &= ~3;
1304 strcpy (p, "#Blob");
1306 align_pointer (meta->raw_metadata, p);
1308 int32val = (guint32*)p;
1309 *int32val++ = assembly->guid.offset = table_offset;
1310 *int32val = assembly->guid.index;
1311 table_offset += *int32val;
1312 table_offset += 3; table_offset &= ~3;
1314 strcpy (p, "#GUID");
1316 align_pointer (meta->raw_metadata, p);
1319 * now copy the data, the table stream header and contents goes first.
1321 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1322 p = meta->raw_metadata + assembly->tstream.offset;
1323 int32val = (guint32*)p;
1324 *int32val = 0; /* reserved */
1326 *p++ = 1; /* version */
1328 if (meta->idx_string_wide)
1330 if (meta->idx_guid_wide)
1332 if (meta->idx_blob_wide)
1335 *p++ = 0; /* reserved */
1336 int64val = (guint64*)p;
1337 *int64val++ = valid_mask;
1338 *int64val++ = 0; /* bitvector of sorted tables, set to 0 for now */
1340 int32val = (guint32*)p;
1341 for (i = 0; i < 64; i++){
1342 if (meta->tables [i].rows == 0)
1344 *int32val++ = meta->tables [i].rows;
1346 p = (unsigned char*)int32val;
1347 /* compress the tables */
1348 for (i = 0; i < 64; i++){
1351 guint32 bitfield = meta->tables [i].size_bitfield;
1352 if (!meta->tables [i].rows)
1354 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1355 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1356 meta->tables [i].base = p;
1357 for (row = 1; row <= meta->tables [i].rows; ++row) {
1358 values = assembly->tables [i].values + row * assembly->tables [i].columns;
1359 for (col = 0; col < assembly->tables [i].columns; ++col) {
1360 switch (mono_metadata_table_size (bitfield, col)) {
1362 *p++ = values [col];
1365 int16val = (guint16*)p;
1366 *int16val = values [col];
1370 int32val = (guint32*)p;
1371 *int32val = values [col];
1375 g_assert_not_reached ();
1379 g_assert ((p - (unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1382 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1383 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1384 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1385 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1386 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1388 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1392 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
1394 MonoDynamicTable *table;
1395 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
1396 MonoDomain *domain = ((MonoObject *)assemblyb)->vtable->domain;
1402 assembly->text_rva = START_TEXT_RVA;
1404 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
1405 alloc_table (table, 1);
1406 values = table->values + MONO_ASSEMBLY_SIZE;
1407 values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
1408 name = mono_string_to_utf8 (assemblyb->name);
1409 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
1411 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
1412 values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
1413 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1414 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1415 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1416 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1418 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
1420 assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
1421 assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
1423 len = mono_array_length (assemblyb->modules);
1424 table = &assembly->tables [MONO_TABLE_MODULE];
1425 alloc_table (table, len);
1426 for (i = 0; i < len; ++i)
1427 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
1429 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1431 * table->rows is already set above and in mono_image_fill_module_table.
1433 alloc_table (table, table->rows);
1435 * Set the first entry.
1437 values = table->values + table->columns;
1438 values [MONO_TYPEDEF_FLAGS] = 0;
1439 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
1440 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
1441 values [MONO_TYPEDEF_EXTENDS] = 0;
1442 values [MONO_TYPEDEF_FIELD_LIST] = 1;
1443 values [MONO_TYPEDEF_METHOD_LIST] = 1;
1445 /* later include all the assemblies referenced */
1446 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1447 alloc_table (table, 1);
1448 values = table->values + table->columns;
1449 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "corlib");
1450 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 0;
1451 values [MONO_ASSEMBLYREF_MINOR_VERSION] = 0;
1452 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 0;
1453 values [MONO_ASSEMBLYREF_REV_NUMBER] = 0;
1454 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1455 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1456 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1457 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1459 build_compressed_metadata (assembly);
1463 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
1469 if (!assembly->dynamic_assembly)
1470 mono_image_basic_init (assembly);
1471 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
1472 index = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
1473 /* FIXME: ENOENDIAN */
1474 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (char*)mono_string_chars (str), str->length * 2);
1475 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
1476 return MONO_TOKEN_STRING | index;
1480 * Get a token to insert in the IL code stream for the given MemberInfo.
1482 * ConstructorBuilder
1492 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
1494 MonoClass *klass = obj->vtable->klass;
1497 if (strcmp (klass->name, "MethodBuilder") == 0) {
1498 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
1499 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1500 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1503 if (strcmp (klass->name, "ConstructorBuilder") == 0) {
1504 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
1505 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1506 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1509 if (strcmp (klass->name, "FieldBuilder") == 0) {
1510 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
1511 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
1513 if (strcmp (klass->name, "TypeBuilder") == 0) {
1514 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
1515 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
1517 if (strcmp (klass->name, "MonoType") == 0) {
1518 MonoReflectionType *tb = (MonoReflectionType *)obj;
1519 return mono_metadata_token_from_dor (
1520 mono_image_typedef_or_ref (assembly, tb->type));
1522 if (strcmp (klass->name, "MonoCMethod") == 0 ||
1523 strcmp (klass->name, "MonoMethod") == 0) {
1524 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
1525 token = mono_image_get_methodref_token (assembly, m->method);
1526 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1529 if (strcmp (klass->name, "MonoField") == 0) {
1530 MonoReflectionField *f = (MonoReflectionField *)obj;
1531 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
1532 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1535 g_print ("requested token for %s\n", klass->name);
1540 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1542 MonoDynamicAssembly *assembly;
1545 if (assemblyb->dynamic_assembly)
1548 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1550 string_heap_init (&assembly->sheap);
1551 mono_image_add_stream_data (&assembly->us, "", 1);
1552 mono_image_add_stream_data (&assembly->blob, "", 1);
1554 for (i=0; i < 64; ++i) {
1555 assembly->tables [i].next_idx = 1;
1556 assembly->tables [i].columns = table_sizes [i];
1562 mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, int maxsize)
1564 MonoMSDOSHeader *msdos;
1565 MonoDotNetHeader *header;
1566 MonoSectionTable *section;
1567 MonoCLIHeader *cli_header;
1568 guint32 header_size = TEXT_OFFSET + CLI_H_SIZE;
1569 MonoDynamicAssembly *assembly;
1571 static const unsigned char msheader[] = {
1572 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
1573 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
1576 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
1577 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
1578 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
1579 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1582 if (maxsize < header_size)
1585 mono_image_basic_init (assemblyb);
1586 assembly = assemblyb->dynamic_assembly;
1588 mono_image_build_metadata (assemblyb);
1590 memset (buffer, 0, header_size);
1591 memcpy (buffer, msheader, sizeof (MonoMSDOSHeader));
1593 msdos = (MonoMSDOSHeader *)buffer;
1594 header = (MonoDotNetHeader *)(buffer + sizeof (MonoMSDOSHeader));
1595 section = (MonoSectionTable*) (buffer + sizeof (MonoMSDOSHeader) + sizeof (MonoDotNetHeader));
1597 /* FIXME: ENDIAN problem: byteswap as needed */
1598 msdos->pe_offset = sizeof (MonoMSDOSHeader);
1600 header->pesig [0] = 'P';
1601 header->pesig [1] = 'E';
1602 header->pesig [2] = header->pesig [3] = 0;
1604 header->coff.coff_machine = 0x14c;
1605 header->coff.coff_sections = 1; /* only .text supported now */
1606 header->coff.coff_time = time (NULL);
1607 header->coff.coff_opt_header_size = sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4;
1609 header->coff.coff_attributes = 0x010e;
1611 //header->coff.coff_attributes = 0x210e;
1612 header->pe.pe_magic = 0x10B;
1613 header->pe.pe_major = 6;
1614 header->pe.pe_minor = 0;
1615 /* need to set: pe_code_size pe_data_size pe_rva_entry_point pe_rva_code_base pe_rva_data_base */
1617 header->nt.pe_image_base = 0x400000;
1618 header->nt.pe_section_align = 8192;
1619 header->nt.pe_file_alignment = FILE_ALIGN;
1620 header->nt.pe_os_major = 4;
1621 header->nt.pe_os_minor = 0;
1622 header->nt.pe_subsys_major = 4;
1623 /* need to set pe_image_size, pe_header_size */
1624 header->nt.pe_subsys_required = 3; /* 3 -> cmdline app, 2 -> GUI app */
1625 header->nt.pe_stack_reserve = 0x00100000;
1626 header->nt.pe_stack_commit = 0x00001000;
1627 header->nt.pe_heap_reserve = 0x00100000;
1628 header->nt.pe_heap_commit = 0x00001000;
1629 header->nt.pe_loader_flags = 1;
1630 header->nt.pe_data_dir_count = 16;
1634 header->datadir.pe_import_table
1639 header->datadir.pe_cli_header.size = CLI_H_SIZE;
1640 header->datadir.pe_cli_header.rva = assembly->text_rva; /* we put it always at the beginning */
1642 /* Write section tables */
1643 strcpy (section->st_name, ".text");
1644 section->st_virtual_size = 1024; /* FIXME */
1645 section->st_virtual_address = START_TEXT_RVA;
1646 section->st_raw_data_size = 1024; /* FIXME */
1647 section->st_raw_data_ptr = TEXT_OFFSET;
1648 section->st_flags = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
1651 * align: build_compressed_metadata () assumes metadata is aligned
1653 * cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1655 assembly->code.index += 3;
1656 assembly->code.index &= ~3;
1659 * Write the MonoCLIHeader header
1661 cli_header = (MonoCLIHeader*)(buffer + TEXT_OFFSET);
1662 cli_header->ch_size = CLI_H_SIZE;
1663 cli_header->ch_runtime_major = 2;
1664 cli_header->ch_flags = CLI_FLAGS_ILONLY;
1665 if (assemblyb->entry_point)
1666 cli_header->ch_entry_point = assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF;
1668 cli_header->ch_entry_point = 0;
1669 cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1670 cli_header->ch_metadata.size = assembly->meta_size;
1676 * We need to return always the same object for Type, MethodInfo, FieldInfo etc..
1678 static GHashTable *object_cache = NULL;
1680 #define CHECK_OBJECT(t,p) \
1683 if (!object_cache) \
1684 object_cache = g_hash_table_new (g_direct_hash, g_direct_equal); \
1685 if ((_obj = g_hash_table_lookup (object_cache, (p)))) \
1689 #define CACHE_OBJECT(p,o) \
1691 g_hash_table_insert (object_cache, p,o); \
1694 MonoReflectionAssembly*
1695 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
1697 static MonoClass *System_Reflection_Assembly;
1698 MonoReflectionAssembly *res;
1700 CHECK_OBJECT (MonoReflectionAssembly *, assembly);
1701 if (!System_Reflection_Assembly)
1702 System_Reflection_Assembly = mono_class_from_name (
1703 mono_defaults.corlib, "System.Reflection", "Assembly");
1704 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
1705 res->assembly = assembly;
1706 CACHE_OBJECT (assembly, res);
1711 mono_type_get_object (MonoDomain *domain, MonoType *type)
1713 MonoReflectionType *res;
1717 * FIXME: type may come from the cache in metadata.c, we hand out only
1718 * the types from a MonoClass structure: the long term fix is to just
1719 * load corlib always and remove the cache in metadata.c altogether.
1720 * Or we may still handle it this way so we can store in MonoType additional info
1723 klass = mono_class_from_mono_type (type);
1724 if ((type != &klass->byval_arg) && (type != &klass->this_arg)) {
1726 type = &klass->this_arg;
1728 type = &klass->byval_arg;
1730 CHECK_OBJECT (MonoReflectionType *, type);
1731 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
1733 CACHE_OBJECT (type, res);
1737 MonoReflectionMethod*
1738 mono_method_get_object (MonoDomain *domain, MonoMethod *method)
1741 * We use the same C representation for methods and constructors, but the type
1742 * name in C# is different.
1746 MonoReflectionMethod *ret;
1748 CHECK_OBJECT (MonoReflectionMethod *, method);
1749 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
1750 cname = "MonoCMethod";
1752 cname = "MonoMethod";
1753 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
1755 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
1756 ret->method = method;
1757 CACHE_OBJECT (method, ret);
1761 MonoReflectionField*
1762 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
1764 MonoReflectionField *res;
1767 CHECK_OBJECT (MonoReflectionField *, field);
1768 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
1769 res = (MonoReflectionField *)mono_object_new (domain, oklass);
1772 CACHE_OBJECT (field, res);
1776 MonoReflectionProperty*
1777 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
1779 MonoReflectionProperty *res;
1782 CHECK_OBJECT (MonoReflectionProperty *, property);
1783 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
1784 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
1786 res->property = property;
1787 CACHE_OBJECT (property, res);
1791 MonoReflectionParameter**
1792 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
1794 MonoReflectionParameter **res;
1795 MonoReflectionMethod *member;
1800 if (!method->signature->param_count)
1803 member = mono_method_get_object (domain, method);
1804 names = g_new (char *, method->signature->param_count);
1805 mono_method_get_param_names (method, (const char **) names);
1807 /* Note: the cache is based on the address of the signature into the method
1808 * since we already cache MethodInfos with the method as keys.
1810 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature));
1811 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
1812 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
1813 for (i = 0; i < method->signature->param_count; ++i) {
1814 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
1815 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
1816 res [i]->DefaultValueImpl = NULL; /* FIXME */
1817 res [i]->MemberImpl = (MonoObject*)member;
1818 res [i]->NameImpl = mono_string_new (domain, names [i]);
1819 res [i]->PositionImpl = i + 1;
1820 res [i]->AttrsImpl = method->signature->params [i]->attrs;
1823 CACHE_OBJECT (&(method->signature), res);
1828 * Parse a type name as accepted by the GetType () method and output the info
1829 * extracted in the info structure.
1830 * the name param will be mangled, so, make a copy before passing it to this function.
1831 * The fields in info will be valid until the memory pointed to by name is valid.
1832 * Returns 0 on parse error.
1835 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
1837 char *start, *p, *w, *last_point;
1838 int in_modifiers = 0;
1840 start = p = w = name;
1842 info->name = info->name_space = info->assembly = NULL;
1843 info->nest_name = info->nest_name_space = NULL;
1844 info->rank = info->isbyref = info->ispointer = 0;
1851 /* we have parsed the nesting namespace + name */
1853 info->nest_name_space = start;
1855 info->nest_name = last_point + 1;
1857 info->nest_name_space = "";
1858 info->nest_name = start;
1860 *p = 0; /* NULL terminate */
1885 info->name_space = start;
1887 info->name = last_point + 1;
1889 info->name_space = "";
1892 /* FIXME: we don't mainatin an order for byref, pointer and array... */
1900 info->ispointer = 1;
1926 return 0; /* missing assembly name */
1933 *w = 0; /* terminate class name */
1934 if (!info->name || !*info->name)
1936 if (info->nest_name && !*info->nest_name)
1938 /* add other consistency checks */
1943 dummy_runtime_invoke (MonoMethod *method, void *obj, void **params)
1945 g_error ("runtime invoke called on uninitialized runtime");
1949 MonoInvokeFunc mono_default_runtime_invoke = dummy_runtime_invoke;
1952 mono_install_runtime_invoke (MonoInvokeFunc func) {
1954 mono_default_runtime_invoke = func;
1956 mono_default_runtime_invoke = dummy_runtime_invoke;
1960 mono_runtime_invoke (MonoMethod *method, void *obj, void **params)
1962 return mono_default_runtime_invoke (method, obj, params);;
1966 * Optimization we could avoid mallocing() an little-endian archs that
1967 * don't crash with unaligned accesses.
1970 fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
1971 int len, i, slen, type;
1972 const char *p = mono_metadata_blob_heap (image, blobidx);
1974 len = mono_metadata_decode_value (p, &p);
1975 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
1980 for (i = 0; i < sig->param_count; ++i) {
1981 type = sig->params [i]->type;
1986 case MONO_TYPE_BOOLEAN: {
1987 MonoBoolean *bval = params [i] = g_malloc (sizeof (MonoBoolean));
1992 case MONO_TYPE_CHAR:
1994 case MONO_TYPE_I2: {
1995 guint16 *val = params [i] = g_malloc (sizeof (guint16));
2000 #if SIZEOF_VOID_P == 4
2006 case MONO_TYPE_I4: {
2007 guint32 *val = params [i] = g_malloc (sizeof (guint32));
2012 #if SIZEOF_VOID_P == 8
2013 case MONO_TYPE_U: /* error out instead? this should probably not happen */
2018 case MONO_TYPE_I8: {
2019 guint64 *val = params [i] = g_malloc (sizeof (guint64));
2024 case MONO_TYPE_VALUETYPE:
2025 if (sig->params [i]->data.klass->enumtype) {
2026 type = sig->params [i]->data.klass->enum_basetype->type;
2029 g_warning ("generic valutype not handled in custom attr value decoding");
2032 case MONO_TYPE_STRING: {
2033 slen = mono_metadata_decode_value (p, &p);
2034 params [i] = mono_string_new_len (mono_domain_get (), p, slen);
2039 g_warning ("Type %02x not handled in custom attr value decoding", sig->params [i]->type);
2046 free_param_data (MonoMethodSignature *sig, void **params) {
2048 for (i = 0; i < sig->param_count; ++i) {
2049 switch (sig->params [i]->type) {
2050 case MONO_TYPE_BOOLEAN:
2051 case MONO_TYPE_CHAR:
2064 case MONO_TYPE_VALUETYPE:
2065 g_free (params [i]);
2074 * Find the method index in the metadata methodDef table.
2075 * Later put these three helper methods in metadata and export them.
2078 find_method_index (MonoMethod *method) {
2079 MonoClass *klass = method->klass;
2082 for (i = 0; i < klass->method.count; ++i) {
2083 if (method == klass->methods [i])
2084 return klass->method.first + 1 + i;
2090 * Find the field index in the metadata FieldDef table.
2093 find_field_index (MonoClass *klass, MonoClassField *field) {
2096 for (i = 0; i < klass->field.count; ++i) {
2097 if (field == &klass->fields [i])
2098 return klass->field.first + 1 + i;
2104 * Find the property index in the metadata FieldDef table.
2107 find_property_index (MonoClass *klass, MonoProperty *property) {
2110 for (i = 0; i < klass->property.count; ++i) {
2111 if (property == &klass->properties [i])
2112 return klass->property.first + 1 + i;
2118 mono_reflection_get_custom_attrs (MonoObject *obj)
2120 guint32 index, mtoken, i;
2121 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
2131 klass = obj->vtable->klass;
2132 /* FIXME: need to handle: Module, MonoProperty */
2133 if (klass == mono_defaults.monotype_class) {
2134 MonoReflectionType *rtype = (MonoReflectionType*)obj;
2135 klass = mono_class_from_mono_type (rtype->type);
2136 index = mono_metadata_token_index (klass->type_token);
2137 index <<= CUSTOM_ATTR_BITS;
2138 index |= CUSTOM_ATTR_TYPEDEF;
2139 image = klass->image;
2140 } else if (strcmp ("Assembly", klass->name) == 0) {
2141 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
2142 index = 1; /* there is only one assembly */
2143 index <<= CUSTOM_ATTR_BITS;
2144 index |= CUSTOM_ATTR_ASSEMBLY;
2145 image = rassembly->assembly->image;
2146 } else if (strcmp ("MonoProperty", klass->name) == 0) {
2147 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
2148 index = find_property_index (rprop->klass, rprop->property);
2149 index <<= CUSTOM_ATTR_BITS;
2150 index |= CUSTOM_ATTR_PROPERTY;
2151 image = rprop->klass->image;
2152 } else if (strcmp ("MonoField", klass->name) == 0) {
2153 MonoReflectionField *rfield = (MonoReflectionField*)obj;
2154 index = find_field_index (rfield->klass, rfield->field);
2155 index <<= CUSTOM_ATTR_BITS;
2156 index |= CUSTOM_ATTR_FIELDDEF;
2157 image = rfield->klass->image;
2158 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
2159 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
2160 index = find_method_index (rmethod->method);
2161 index <<= CUSTOM_ATTR_BITS;
2162 index |= CUSTOM_ATTR_METHODDEF;
2163 image = method->klass->image;
2164 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
2165 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
2166 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
2167 guint32 method_index = find_method_index (rmethod->method);
2168 guint32 param_list, param_last, param_pos, found;
2170 image = rmethod->method->klass->image;
2171 ca = &image->tables [MONO_TABLE_METHOD];
2173 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
2174 if (method_index == ca->rows) {
2175 ca = &image->tables [MONO_TABLE_PARAM];
2176 param_last = ca->rows + 1;
2178 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
2179 ca = &image->tables [MONO_TABLE_PARAM];
2182 for (i = param_list; i < param_list; ++i) {
2183 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
2184 if (param_pos == param->PositionImpl) {
2190 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
2192 index <<= CUSTOM_ATTR_BITS;
2193 index |= CUSTOM_ATTR_PARAMDEF;
2194 } else { /* handle other types here... */
2195 g_error ("get custom attrs not yet supported for %s", klass->name);
2198 /* at this point image and index are set correctly for searching the custom attr */
2199 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2200 /* the table is not sorted */
2201 for (i = 0; i < ca->rows; ++i) {
2202 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
2203 if (cols [MONO_CUSTOM_ATTR_PARENT] != index)
2205 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
2206 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
2207 case CUSTOM_ATTR_TYPE_METHODDEF:
2208 mtoken |= MONO_TOKEN_METHOD_DEF;
2210 case CUSTOM_ATTR_TYPE_MEMBERREF:
2211 mtoken |= MONO_TOKEN_MEMBER_REF;
2214 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
2217 method = mono_get_method (image, mtoken, NULL);
2219 g_error ("Can't find custom attr constructor");
2220 mono_class_init (method->klass);
2221 /*g_print ("got attr %s\n", method->klass->name);*/
2222 params = g_new (void*, method->signature->param_count);
2223 fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
2224 attr = mono_object_new (mono_domain_get (), method->klass);
2225 mono_runtime_invoke (method, attr, params);
2226 list = g_list_prepend (list, attr);
2227 free_param_data (method->signature, params);
2231 index = g_list_length (list);
2233 * The return type is really object[], but System/Attribute.cs does a cast
2234 * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
2235 * probably fix that.
2237 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
2238 result = mono_array_new (mono_domain_get (), klass, index);
2239 for (i = 0; i < index; ++i) {
2240 mono_array_set (result, gpointer, i, list->data);
2243 g_list_free (g_list_first (list));
2249 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *porpValues, MonoArray *fields, MonoArray* fieldValues) {
2251 MonoMethodSignature *sig;
2253 char *buffer, *p, *argval;
2254 guint32 buflen, i, type;
2256 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
2257 g_warning ("ConstructorBuilder Custom attribute not yet supported");
2259 * maybe we should have a param array to method signature function and
2260 * continue with the normal codepath.
2262 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, 4);
2263 mono_array_set (result, char, 0, 1);
2267 p = buffer = g_malloc (buflen);
2268 /* write the prolog */
2271 sig = ((MonoReflectionMethod*)ctor)->method->signature;
2272 /* FIXME: ENOENDIAN */
2273 for (i = 0; i < sig->param_count; ++i) {
2274 if ((p-buffer) + 10 >= buflen) {
2277 newbuf = g_realloc (buffer, buflen);
2278 p = newbuf + (p-buffer);
2281 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
2282 argval = ((char*)arg + sizeof (MonoObject));
2283 type = sig->params [i]->type;
2286 case MONO_TYPE_BOOLEAN:
2291 case MONO_TYPE_CHAR:
2293 case MONO_TYPE_I2: {
2294 guint16 *val = (guint16*)p;
2295 *val = *(guint16*)argval;
2301 case MONO_TYPE_R4: {
2302 guint32 *val = (guint32*)p;
2303 *val = *(guint32*)argval;
2309 case MONO_TYPE_R8: {
2310 guint64 *val = (guint64*)p;
2311 *val = *(guint64*)argval;
2315 case MONO_TYPE_VALUETYPE:
2316 if (sig->params [i]->data.klass->enumtype) {
2317 type = sig->params [i]->data.klass->enum_basetype->type;
2320 g_warning ("generic valutype not handled in custom attr value decoding");
2323 case MONO_TYPE_STRING: {
2324 char *str = mono_string_to_utf8 ((MonoString*)arg);
2325 guint32 slen = strlen (str);
2326 if ((p-buffer) + 10 + slen >= buflen) {
2330 newbuf = g_realloc (buffer, buflen);
2331 p = newbuf + (p-buffer);
2334 mono_metadata_encode_value (slen, p, &p);
2335 memcpy (p, str, slen);
2341 g_error ("type 0x%02x not yet supported in custom attr encoder", type);
2345 * we don't support properties and fields, yet, set to 0.
2349 buflen = p - buffer;
2350 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
2351 p = mono_array_addr (result, char, 0);
2352 memcpy (p, buffer, buflen);