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);
209 case MONO_TYPE_SZARRAY:
210 mono_metadata_encode_value (type->type, p, &p);
211 encode_type (assembly, type->data.type, p, &p);
213 case MONO_TYPE_VALUETYPE:
214 case MONO_TYPE_CLASS:
215 mono_metadata_encode_value (type->type, p, &p);
216 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
219 g_error ("need to encode type %x", type->type);
225 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
227 MonoReflectionTypeBuilder *tb;
231 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
235 encode_type (assembly, type->type, p, endbuf);
239 tb = (MonoReflectionTypeBuilder*) type;
240 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS); /* typedef */
242 /* FIXME: handle other base types (need to have also some hacks to compile corlib) ... */
243 /* FIXME: handle byref ... */
244 mono_metadata_encode_value (MONO_TYPE_CLASS, p, &p);
245 mono_metadata_encode_value (token, p, endbuf);
246 /*g_print ("encoding type %s to 0x%08x\n", mono_string_to_utf8 (tb->name), token);*/
250 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
255 guint32 nparams = sig->param_count;
256 guint32 size = 10 + nparams * 10;
261 p = buf = g_malloc (size);
263 * FIXME: vararg, explicit_this, differenc call_conv values...
265 *p = sig->call_convention;
267 *p |= 0x20; /* hasthis */
269 mono_metadata_encode_value (nparams, p, &p);
270 encode_type (assembly, sig->ret, p, &p);
271 for (i = 0; i < nparams; ++i)
272 encode_type (assembly, sig->params [i], p, &p);
274 mono_metadata_encode_value (p-buf, b, &b);
275 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
276 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
282 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
285 * FIXME: reuse code from method_encode_signature().
290 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
291 guint32 size = 10 + nparams * 10;
296 p = buf = g_malloc (size);
297 /* LAMESPEC: all the call conv spec is foobared */
298 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
299 if (mb->call_conv & 2)
300 *p |= 0x5; /* vararg */
301 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
302 *p |= 0x20; /* hasthis */
304 mono_metadata_encode_value (nparams, p, &p);
305 encode_reflection_type (assembly, mb->rtype, p, &p);
306 for (i = 0; i < nparams; ++i) {
307 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
308 encode_reflection_type (assembly, pt, p, &p);
311 mono_metadata_encode_value (p-buf, b, &b);
312 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
313 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
319 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
321 MonoDynamicTable *table;
324 guint32 idx, sig_idx;
325 guint nl = mono_array_length (ilgen->locals);
331 p = buf = g_malloc (10 + nl * 10);
332 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
333 idx = table->next_idx ++;
335 alloc_table (table, table->rows);
336 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
338 mono_metadata_encode_value (0x07, p, &p);
339 mono_metadata_encode_value (nl, p, &p);
340 for (i = 0; i < nl; ++i) {
341 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
342 encode_reflection_type (assembly, lb->type, p, &p);
344 mono_metadata_encode_value (p-buf, b, &b);
345 sig_idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
346 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
349 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
355 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
357 /* we use only tiny formats now: need to implement ILGenerator */
362 gint32 num_locals = 0;
363 gint32 num_exception = 0;
366 char fat_header [12];
369 guint32 local_sig = 0;
370 guint32 header_size = 12;
373 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
374 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
375 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
376 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
380 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
382 code = mb->ilgen->code;
383 code_size = mb->ilgen->code_len;
384 max_stack = mb->ilgen->max_stack;
385 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
386 if (mb->ilgen->ex_handlers) {
387 MonoILExceptionInfo *ex_info;
388 for (i = 0; i < mono_array_length (mb->ilgen->ex_handlers); ++i) {
389 ex_info = (MonoILExceptionInfo*)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
390 if (ex_info->handlers)
391 num_exception += mono_array_length (ex_info->handlers);
398 code_size = mono_array_length (code);
399 max_stack = 8; /* we probably need to run a verifier on the code... */
402 /* check for exceptions, maxstack, locals */
403 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
405 if (code_size < 64 && !(code_size & 1)) {
406 flags = (code_size << 2) | 0x2;
407 } else if (code_size < 32 && (code_size & 1)) {
408 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
412 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
413 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
414 return assembly->text_rva + idx + CLI_H_SIZE;
418 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
420 * FIXME: need to set also the header size in fat_flags.
421 * (and more sects and init locals flags)
425 fat_flags |= METHOD_HEADER_MORE_SECTS;
426 fat_header [0] = fat_flags;
427 fat_header [1] = (header_size / 4 ) << 4;
428 shortp = (guint16*)(fat_header + 2);
430 intp = (guint32*)(fat_header + 4);
432 intp = (guint32*)(fat_header + 8);
434 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
435 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
437 unsigned char sheader [4];
438 MonoExceptionClause clause;
439 MonoILExceptionInfo * ex_info;
440 MonoILExceptionBlock * ex_block;
443 stream_data_align (&assembly->code);
444 /* always use fat format for now */
445 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
446 num_exception *= sizeof (MonoExceptionClause);
447 sheader [1] = num_exception & 0xff;
448 sheader [2] = (num_exception >> 8) & 0xff;
449 sheader [3] = (num_exception >> 16) & 0xff;
450 mono_image_add_stream_data (&assembly->code, sheader, 4);
451 /* fat header, so we are already aligned */
453 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
454 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
455 if (ex_info->handlers) {
456 int finally_start = 0;
457 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
458 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
459 clause.flags = ex_block->type;
460 clause.try_offset = ex_info->start;
461 /* need fault, too, probably */
462 if (clause.flags == MONO_EXCEPTION_CLAUSE_FINALLY)
463 clause.try_len = finally_start - ex_info->start;
465 clause.try_len = ex_info->len;
466 clause.handler_offset = ex_block->start;
467 clause.handler_len = ex_block->len;
468 finally_start = clause.handler_offset + clause.handler_len;
469 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
470 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
471 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d\n",
472 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len);*/
473 /* FIXME: ENOENDIAN */
474 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
477 g_error ("No clauses");
481 return assembly->text_rva + idx + CLI_H_SIZE;
485 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 index)
488 MonoDynamicTable *table;
491 table = &assembly->tables [table_idx];
493 g_assert (col < table->columns);
495 values = table->values + table->columns;
496 for (i = 1; i <= table->rows; ++i) {
497 if (values [col] == index)
504 * index is the table index of the object
505 * type is one of CUSTOM_ATTR_*
508 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 index, guint32 type, MonoArray *cattrs)
510 MonoDynamicTable *table;
511 MonoReflectionCustomAttr *cattr;
513 guint32 count, i, token;
517 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
520 count = mono_array_length (cattrs);
521 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
522 table->rows += count;
523 alloc_table (table, table->rows);
524 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
525 index <<= CUSTOM_ATTR_BITS;
527 for (i = 0; i < count; ++i) {
528 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
529 values [MONO_CUSTOM_ATTR_PARENT] = index;
530 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
531 type = mono_metadata_token_index (token);
532 type <<= CUSTOM_ATTR_TYPE_BITS;
533 switch (mono_metadata_token_table (token)) {
534 case MONO_TABLE_METHOD:
535 type |= CUSTOM_ATTR_TYPE_METHODDEF;
537 case MONO_TABLE_MEMBERREF:
538 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
541 g_error ("got wrong token in custom attr");
543 values [MONO_CUSTOM_ATTR_TYPE] = type;
545 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
546 values [MONO_CUSTOM_ATTR_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, p - blob_size);
547 mono_image_add_stream_data (&assembly->blob,
548 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
549 values += MONO_CUSTOM_ATTR_SIZE;
555 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
557 MonoDynamicTable *table;
562 /* room in this table is already allocated */
563 table = &assembly->tables [MONO_TABLE_METHOD];
564 *mb->table_idx = table->next_idx ++;
565 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
567 name = mono_string_to_utf8 (mb->name);
568 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
570 } else { /* a constructor */
571 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
573 values [MONO_METHOD_FLAGS] = mb->attrs;
574 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
575 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
576 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
578 table = &assembly->tables [MONO_TABLE_PARAM];
579 values [MONO_METHOD_PARAMLIST] = table->next_idx;
583 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
584 if (mono_array_get (mb->pinfo, gpointer, i))
587 table->rows += count;
588 alloc_table (table, table->rows);
589 values = table->values + table->next_idx * MONO_PARAM_SIZE;
590 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
591 MonoReflectionParamBuilder *pb;
592 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
593 values [MONO_PARAM_FLAGS] = pb->attrs;
594 values [MONO_PARAM_SEQUENCE] = i;
595 name = mono_string_to_utf8 (pb->name);
596 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
598 values += MONO_PARAM_SIZE;
600 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
607 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
609 MonoDynamicTable *table;
612 ReflectionMethodBuilder rmb;
614 rmb.ilgen = mb->ilgen;
615 rmb.rtype = mb->rtype;
616 rmb.parameters = mb->parameters;
617 rmb.pinfo = mb->pinfo;
618 rmb.attrs = mb->attrs;
619 rmb.iattrs = mb->iattrs;
620 rmb.call_conv = mb->call_conv;
624 rmb.table_idx = &mb->table_idx;
626 mono_image_basic_method (&rmb, assembly);
628 if (mb->dll) { /* It's a P/Invoke method */
630 table = &assembly->tables [MONO_TABLE_IMPLMAP];
632 alloc_table (table, table->rows);
633 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
634 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
635 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
636 name = mono_string_to_utf8 (mb->dllentry);
637 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
639 name = mono_string_to_utf8 (mb->dll);
640 moduleref = string_heap_insert (&assembly->sheap, name);
642 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
643 table = &assembly->tables [MONO_TABLE_MODULEREF];
645 alloc_table (table, table->rows);
646 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
647 values [MONO_IMPLMAP_SCOPE] = table->rows;
650 if (mb->override_method) {
651 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
652 table = &assembly->tables [MONO_TABLE_METHODIMPL];
654 alloc_table (table, table->rows);
655 values = table->values + table->rows * MONO_MTHODIMPL_SIZE;
656 values [MONO_MTHODIMPL_CLASS] = tb->table_idx;
657 values [MONO_MTHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
658 if (mb->override_method->method)
659 values [MONO_MTHODIMPL_DECLARATION] = mono_image_get_methodref_token (assembly, mb->override_method->method);
661 MonoReflectionMethodBuilder *omb = (MonoReflectionMethodBuilder*)mb->override_method;
662 values [MONO_MTHODIMPL_DECLARATION] = METHODDEFORREF_METHODDEF | (omb->table_idx << METHODDEFORREF_BITS);
665 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
669 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
671 ReflectionMethodBuilder rmb;
673 rmb.ilgen = mb->ilgen;
674 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
675 rmb.parameters = mb->parameters;
676 rmb.pinfo = mb->pinfo;
677 rmb.attrs = mb->attrs;
678 rmb.iattrs = mb->iattrs;
679 rmb.call_conv = mb->call_conv;
683 rmb.table_idx = &mb->table_idx;
685 mono_image_basic_method (&rmb, assembly);
686 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
691 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
699 p = buf = g_malloc (64);
701 /* No start code with field refs...
702 * mono_metadata_encode_value (0x06, p, &p);
704 /* encode custom attributes before the type */
705 encode_type (assembly, field->type, p, &p);
706 g_assert (p-buf < 64);
707 mono_metadata_encode_value (p-buf, b, &b);
708 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
709 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
715 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
723 p = buf = g_malloc (64);
725 mono_metadata_encode_value (0x06, p, &p);
726 /* encode custom attributes before the type */
727 encode_reflection_type (assembly, fb->type, p, &p);
728 g_assert (p-buf < 64);
729 mono_metadata_encode_value (p-buf, b, &b);
730 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
731 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
737 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
744 p = buf = g_malloc (64);
746 box_val = ((char*)val) + sizeof (MonoObject);
747 *ret_type = val->vtable->klass->byval_arg.type;
749 case MONO_TYPE_BOOLEAN:
769 case MONO_TYPE_STRING:
771 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
774 /* there is no signature */
775 mono_metadata_encode_value (len, b, &b);
776 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
777 /* FIXME: ENOENDIAN */
778 mono_image_add_stream_data (&assembly->blob, box_val, len);
785 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
787 MonoDynamicTable *table;
791 table = &assembly->tables [MONO_TABLE_FIELD];
792 fb->table_idx = table->next_idx ++;
793 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
794 name = mono_string_to_utf8 (fb->name);
795 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
797 values [MONO_FIELD_FLAGS] = fb->attrs;
798 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
800 if (fb->offset != -1) {
801 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
803 alloc_table (table, table->rows);
804 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
805 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
806 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
808 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
809 guint32 field_type = 0;
810 table = &assembly->tables [MONO_TABLE_CONSTANT];
812 alloc_table (table, table->rows);
813 values = table->values + table->rows * MONO_CONSTANT_SIZE;
814 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
815 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
816 values [MONO_CONSTANT_TYPE] = field_type;
817 values [MONO_CONSTANT_PADDING] = 0;
821 table = &assembly->tables [MONO_TABLE_FIELDRVA];
823 alloc_table (table, table->rows);
824 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
825 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
827 * We store it in the code section because it's simpler for now.
829 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
830 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva + CLI_H_SIZE;
832 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
836 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
842 MonoReflectionMethodBuilder *mb = fb->get_method;
845 if (mb && mb->parameters)
846 nparams = mono_array_length (mb->parameters);
847 buf = p = g_malloc (24 + nparams * 10);
850 mono_metadata_encode_value (nparams, p, &p);
852 encode_reflection_type (assembly, mb->rtype, p, &p);
853 for (i = 0; i < nparams; ++i) {
854 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
855 encode_reflection_type (assembly, pt, p, &p);
858 *p++ = 1; /* void: a property should probably not be allowed without a getter */
861 mono_metadata_encode_value (p-buf, b, &b);
862 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
863 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
869 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
871 MonoDynamicTable *table;
874 guint num_methods = 0;
878 * we need to set things in the following tables:
879 * PROPERTYMAP (info already filled in _get_type_info ())
880 * PROPERTY (rows already preallocated in _get_type_info ())
881 * METHOD (method info already done with the generic method code)
884 table = &assembly->tables [MONO_TABLE_PROPERTY];
885 pb->table_idx = table->next_idx ++;
886 values = table->values + pb->table_idx * MONO_FIELD_SIZE;
887 name = mono_string_to_utf8 (pb->name);
888 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
890 values [MONO_PROPERTY_FLAGS] = pb->attrs;
891 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
893 /* FIXME: we still don't handle 'other' methods */
894 if (pb->get_method) num_methods ++;
895 if (pb->set_method) num_methods ++;
897 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
898 table->rows += num_methods;
899 alloc_table (table, table->rows);
901 if (pb->get_method) {
902 semaidx = table->next_idx ++;
903 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
904 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
905 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
906 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
908 if (pb->set_method) {
909 semaidx = table->next_idx ++;
910 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
911 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
912 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
913 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
915 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
919 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
921 if (image != mono_defaults.corlib)
922 g_error ("multiple assemblyref not yet supported");
923 /* first row in assemblyref */
924 return (1 << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_ASSEMBLYREF;
928 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
930 MonoDynamicTable *table;
935 if (!assembly->typeref)
936 assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
938 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
941 klass = type->data.klass;
943 * If it's in the same module:
944 * return TYPEDEFORREF_TYPEDEF | ((klass->token & 0xffffff) << TYPEDEFORREF_BITS)
947 table = &assembly->tables [MONO_TABLE_TYPEREF];
948 alloc_table (table, table->rows + 1);
949 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
950 values [MONO_TYPEREF_SCOPE] = resolution_scope_from_image (assembly, klass->image);
951 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
952 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
953 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
954 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
960 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoClass *klass, const char *name, guint32 sig)
962 MonoDynamicTable *table;
964 guint32 token, pclass;
967 parent = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
968 switch (parent & TYPEDEFORREF_MASK) {
969 case TYPEDEFORREF_TYPEREF:
970 pclass = MEMBERREF_PARENT_TYPEREF;
972 case TYPEDEFORREF_TYPESPEC:
973 pclass = MEMBERREF_PARENT_TYPESPEC;
975 case TYPEDEFORREF_TYPEDEF:
976 /* should never get here */
978 g_error ("unknow typeref or def token");
980 /* extract the index */
981 parent >>= TYPEDEFORREF_BITS;
983 table = &assembly->tables [MONO_TABLE_MEMBERREF];
984 alloc_table (table, table->rows + 1);
985 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
986 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
987 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
988 values [MONO_MEMBERREF_SIGNATURE] = sig;
989 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
996 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
999 if (!assembly->typeref)
1000 assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
1002 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, method));
1005 token = mono_image_get_memberref_token (assembly, method->klass,
1006 method->name, method_encode_signature (assembly, method->signature));
1007 g_hash_table_insert (assembly->typeref, method, GUINT_TO_POINTER(token));
1012 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1015 if (!assembly->typeref)
1016 assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
1018 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, field));
1021 token = mono_image_get_memberref_token (assembly, klass,
1022 field->name, fieldref_encode_signature (assembly, field));
1023 g_hash_table_insert (assembly->typeref, field, GUINT_TO_POINTER(token));
1028 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1030 MonoDynamicTable *table;
1035 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1036 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1037 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1038 if (tb->parent) { /* interfaces don't have a parent */
1039 if (tb->parent->type)
1040 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1042 MonoReflectionTypeBuilder *ptb = (MonoReflectionTypeBuilder *)tb->parent;
1043 values [MONO_TYPEDEF_EXTENDS] = TYPEDEFORREF_TYPEDEF | (ptb->table_idx << TYPEDEFORREF_BITS);
1046 values [MONO_TYPEDEF_EXTENDS] = 0;
1047 n = mono_string_to_utf8 (tb->name);
1048 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1050 n = mono_string_to_utf8 (tb->nspace);
1051 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1053 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1054 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1057 * if we have explicitlayout or sequentiallayouts, output data in the
1058 * ClassLayout table.
1060 if ((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1061 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1063 alloc_table (table, table->rows);
1064 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1065 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1066 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1067 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1071 * FIXME: constructors and methods need to be output in the same order
1072 * as they are defined (according to table_idx).
1075 /* handle constructors */
1077 table = &assembly->tables [MONO_TABLE_METHOD];
1078 table->rows += mono_array_length (tb->ctors);
1079 alloc_table (table, table->rows);
1080 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1081 mono_image_get_ctor_info (domain,
1082 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1085 /* handle methods */
1087 table = &assembly->tables [MONO_TABLE_METHOD];
1088 table->rows += mono_array_length (tb->methods);
1089 alloc_table (table, table->rows);
1090 for (i = 0; i < mono_array_length (tb->methods); ++i)
1091 mono_image_get_method_info (
1092 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1097 table = &assembly->tables [MONO_TABLE_FIELD];
1098 table->rows += mono_array_length (tb->fields);
1099 alloc_table (table, table->rows);
1100 for (i = 0; i < mono_array_length (tb->fields); ++i)
1101 mono_image_get_field_info (
1102 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1105 /* Do the same with properties etc.. */
1106 if (tb->properties && mono_array_length (tb->properties)) {
1107 table = &assembly->tables [MONO_TABLE_PROPERTY];
1108 table->rows += mono_array_length (tb->properties);
1109 alloc_table (table, table->rows);
1110 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1112 alloc_table (table, table->rows);
1113 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1114 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1115 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1116 for (i = 0; i < mono_array_length (tb->properties); ++i)
1117 mono_image_get_property_info (
1118 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1121 MonoDynamicTable *ntable;
1123 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1124 table->rows += mono_array_length (tb->subtypes);
1125 alloc_table (table, table->rows);
1127 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1128 ntable->rows += mono_array_length (tb->subtypes);
1129 alloc_table (ntable, ntable->rows);
1130 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1132 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1133 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1135 mono_image_get_type_info (domain, subtype, assembly);
1136 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1137 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1138 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1139 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1140 mono_string_to_utf8 (tb->name), tb->table_idx,
1141 ntable->next_idx, ntable->rows);*/
1142 values += MONO_NESTED_CLASS_SIZE;
1146 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1150 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1152 MonoDynamicTable *table;
1156 table = &assembly->tables [MONO_TABLE_MODULE];
1157 mb->table_idx = table->next_idx ++;
1158 name = mono_string_to_utf8 (mb->module.name);
1159 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1161 /* need to set mvid? */
1163 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1165 * fill-in info in other tables as well.
1167 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1168 table->rows += mono_array_length (mb->types);
1169 alloc_table (table, table->rows);
1171 * We assign here the typedef indexes to avoid mismatches if a type that
1172 * has not yet been stored in the tables is referenced by another type.
1174 for (i = 0; i < mono_array_length (mb->types); ++i) {
1176 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1177 type->table_idx = table->next_idx ++;
1178 if (!type->subtypes)
1180 for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1181 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1182 subtype->table_idx = table->next_idx ++;
1185 for (i = 0; i < mono_array_length (mb->types); ++i)
1186 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1189 #define align_pointer(base,p)\
1191 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1193 (p) += 4 - (__diff & 3);\
1197 build_compressed_metadata (MonoDynamicAssembly *assembly)
1200 guint64 valid_mask = 0;
1201 guint32 heapt_size = 0;
1202 guint32 meta_size = 256; /* allow for header and other stuff */
1203 guint32 table_offset;
1204 guint32 ntables = 0;
1210 char *version = "mono" VERSION;
1212 /* Compute table sizes */
1213 meta = assembly->assembly.image = g_new0 (MonoImage, 1);
1215 /* Setup the info used by compute_sizes () */
1216 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1217 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1218 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1220 meta_size += assembly->blob.index;
1221 meta_size += assembly->guid.index;
1222 meta_size += assembly->sheap.index;
1223 meta_size += assembly->us.index;
1225 for (i=0; i < 64; ++i)
1226 meta->tables [i].rows = assembly->tables [i].rows;
1228 for (i = 0; i < 64; i++){
1229 if (meta->tables [i].rows == 0)
1231 valid_mask |= (guint64)1 << i;
1233 meta->tables [i].row_size = mono_metadata_compute_size (
1234 meta, i, &meta->tables [i].size_bitfield);
1235 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1237 heapt_size += 24; /* #~ header size */
1238 heapt_size += ntables * 4;
1239 meta_size += heapt_size;
1240 meta->raw_metadata = g_malloc0 (meta_size);
1241 p = meta->raw_metadata;
1242 /* the metadata signature */
1243 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1244 /* version numbers and 4 bytes reserved */
1245 int16val = (guint16*)p;
1249 /* version string */
1250 int32val = (guint32*)p;
1251 *int32val = strlen (version);
1253 memcpy (p, version, *int32val);
1255 align_pointer (meta->raw_metadata, p);
1256 int16val = (guint16*)p;
1257 *int16val++ = 0; /* flags must be 0 */
1258 *int16val = 5; /* number of streams */
1262 * write the stream info.
1264 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1265 table_offset += 3; table_offset &= ~3;
1267 int32val = (guint32*)p;
1268 *int32val++ = assembly->tstream.offset = table_offset;
1269 *int32val = heapt_size;
1270 table_offset += *int32val;
1271 table_offset += 3; table_offset &= ~3;
1275 align_pointer (meta->raw_metadata, p);
1277 int32val = (guint32*)p;
1278 *int32val++ = assembly->sheap.offset = table_offset;
1279 *int32val = assembly->sheap.index;
1280 table_offset += *int32val;
1281 table_offset += 3; table_offset &= ~3;
1283 strcpy (p, "#Strings");
1285 align_pointer (meta->raw_metadata, p);
1287 int32val = (guint32*)p;
1288 *int32val++ = assembly->us.offset = table_offset;
1289 *int32val = assembly->us.index;
1290 table_offset += *int32val;
1291 table_offset += 3; table_offset &= ~3;
1295 align_pointer (meta->raw_metadata, p);
1297 int32val = (guint32*)p;
1298 *int32val++ = assembly->blob.offset = table_offset;
1299 *int32val = assembly->blob.index;
1300 table_offset += *int32val;
1301 table_offset += 3; table_offset &= ~3;
1303 strcpy (p, "#Blob");
1305 align_pointer (meta->raw_metadata, p);
1307 int32val = (guint32*)p;
1308 *int32val++ = assembly->guid.offset = table_offset;
1309 *int32val = assembly->guid.index;
1310 table_offset += *int32val;
1311 table_offset += 3; table_offset &= ~3;
1313 strcpy (p, "#GUID");
1315 align_pointer (meta->raw_metadata, p);
1318 * now copy the data, the table stream header and contents goes first.
1320 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1321 p = meta->raw_metadata + assembly->tstream.offset;
1322 int32val = (guint32*)p;
1323 *int32val = 0; /* reserved */
1325 *p++ = 1; /* version */
1327 if (meta->idx_string_wide)
1329 if (meta->idx_guid_wide)
1331 if (meta->idx_blob_wide)
1334 *p++ = 0; /* reserved */
1335 int64val = (guint64*)p;
1336 *int64val++ = valid_mask;
1337 *int64val++ = 0; /* bitvector of sorted tables, set to 0 for now */
1339 int32val = (guint32*)p;
1340 for (i = 0; i < 64; i++){
1341 if (meta->tables [i].rows == 0)
1343 *int32val++ = meta->tables [i].rows;
1345 p = (unsigned char*)int32val;
1346 /* compress the tables */
1347 for (i = 0; i < 64; i++){
1350 guint32 bitfield = meta->tables [i].size_bitfield;
1351 if (!meta->tables [i].rows)
1353 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1354 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1355 meta->tables [i].base = p;
1356 for (row = 1; row <= meta->tables [i].rows; ++row) {
1357 values = assembly->tables [i].values + row * assembly->tables [i].columns;
1358 for (col = 0; col < assembly->tables [i].columns; ++col) {
1359 switch (mono_metadata_table_size (bitfield, col)) {
1361 *p++ = values [col];
1364 int16val = (guint16*)p;
1365 *int16val = values [col];
1369 int32val = (guint32*)p;
1370 *int32val = values [col];
1374 g_assert_not_reached ();
1378 g_assert ((p - (unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1381 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1382 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1383 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1384 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1385 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1387 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1391 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
1393 MonoDynamicTable *table;
1394 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
1395 MonoDomain *domain = ((MonoObject *)assemblyb)->vtable->domain;
1401 assembly->text_rva = START_TEXT_RVA;
1403 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
1404 alloc_table (table, 1);
1405 values = table->values + MONO_ASSEMBLY_SIZE;
1406 values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
1407 name = mono_string_to_utf8 (assemblyb->name);
1408 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
1410 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
1411 values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
1412 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1413 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1414 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1415 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1417 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
1419 assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
1420 assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
1422 len = mono_array_length (assemblyb->modules);
1423 table = &assembly->tables [MONO_TABLE_MODULE];
1424 alloc_table (table, len);
1425 for (i = 0; i < len; ++i)
1426 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
1428 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1430 * table->rows is already set above and in mono_image_fill_module_table.
1432 alloc_table (table, table->rows);
1434 * Set the first entry.
1436 values = table->values + table->columns;
1437 values [MONO_TYPEDEF_FLAGS] = 0;
1438 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
1439 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
1440 values [MONO_TYPEDEF_EXTENDS] = 0;
1441 values [MONO_TYPEDEF_FIELD_LIST] = 1;
1442 values [MONO_TYPEDEF_METHOD_LIST] = 1;
1444 /* later include all the assemblies referenced */
1445 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1446 alloc_table (table, 1);
1447 values = table->values + table->columns;
1448 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "corlib");
1449 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 0;
1450 values [MONO_ASSEMBLYREF_MINOR_VERSION] = 0;
1451 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 0;
1452 values [MONO_ASSEMBLYREF_REV_NUMBER] = 0;
1453 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1454 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1455 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1456 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1458 build_compressed_metadata (assembly);
1462 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
1468 if (!assembly->dynamic_assembly)
1469 mono_image_basic_init (assembly);
1470 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
1471 index = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
1472 /* FIXME: ENOENDIAN */
1473 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (char*)mono_string_chars (str), str->length * 2);
1474 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
1475 return MONO_TOKEN_STRING | index;
1479 * Get a token to insert in the IL code stream for the given MemberInfo.
1481 * ConstructorBuilder
1491 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
1493 MonoClass *klass = obj->vtable->klass;
1496 if (strcmp (klass->name, "MethodBuilder") == 0) {
1497 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
1498 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1499 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1502 if (strcmp (klass->name, "ConstructorBuilder") == 0) {
1503 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
1504 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1505 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1508 if (strcmp (klass->name, "FieldBuilder") == 0) {
1509 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
1510 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
1512 if (strcmp (klass->name, "TypeBuilder") == 0) {
1513 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
1514 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
1516 if (strcmp (klass->name, "MonoType") == 0) {
1517 MonoReflectionType *tb = (MonoReflectionType *)obj;
1518 return mono_metadata_token_from_dor (
1519 mono_image_typedef_or_ref (assembly, tb->type));
1521 if (strcmp (klass->name, "MonoCMethod") == 0 ||
1522 strcmp (klass->name, "MonoMethod") == 0) {
1523 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
1524 token = mono_image_get_methodref_token (assembly, m->method);
1525 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1528 if (strcmp (klass->name, "MonoField") == 0) {
1529 MonoReflectionField *f = (MonoReflectionField *)obj;
1530 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
1531 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1534 g_print ("requested token for %s\n", klass->name);
1539 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1541 MonoDynamicAssembly *assembly;
1544 if (assemblyb->dynamic_assembly)
1547 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1549 string_heap_init (&assembly->sheap);
1550 mono_image_add_stream_data (&assembly->us, "", 1);
1551 mono_image_add_stream_data (&assembly->blob, "", 1);
1553 for (i=0; i < 64; ++i) {
1554 assembly->tables [i].next_idx = 1;
1555 assembly->tables [i].columns = table_sizes [i];
1561 mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, int maxsize)
1563 MonoMSDOSHeader *msdos;
1564 MonoDotNetHeader *header;
1565 MonoSectionTable *section;
1566 MonoCLIHeader *cli_header;
1567 guint32 header_size = TEXT_OFFSET + CLI_H_SIZE;
1568 MonoDynamicAssembly *assembly;
1570 static const unsigned char msheader[] = {
1571 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
1572 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
1575 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
1576 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
1577 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
1578 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1581 if (maxsize < header_size)
1584 mono_image_basic_init (assemblyb);
1585 assembly = assemblyb->dynamic_assembly;
1587 mono_image_build_metadata (assemblyb);
1589 memset (buffer, 0, header_size);
1590 memcpy (buffer, msheader, sizeof (MonoMSDOSHeader));
1592 msdos = (MonoMSDOSHeader *)buffer;
1593 header = (MonoDotNetHeader *)(buffer + sizeof (MonoMSDOSHeader));
1594 section = (MonoSectionTable*) (buffer + sizeof (MonoMSDOSHeader) + sizeof (MonoDotNetHeader));
1596 /* FIXME: ENDIAN problem: byteswap as needed */
1597 msdos->pe_offset = sizeof (MonoMSDOSHeader);
1599 header->pesig [0] = 'P';
1600 header->pesig [1] = 'E';
1601 header->pesig [2] = header->pesig [3] = 0;
1603 header->coff.coff_machine = 0x14c;
1604 header->coff.coff_sections = 1; /* only .text supported now */
1605 header->coff.coff_time = time (NULL);
1606 header->coff.coff_opt_header_size = sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4;
1608 header->coff.coff_attributes = 0x010e;
1610 //header->coff.coff_attributes = 0x210e;
1611 header->pe.pe_magic = 0x10B;
1612 header->pe.pe_major = 6;
1613 header->pe.pe_minor = 0;
1614 /* need to set: pe_code_size pe_data_size pe_rva_entry_point pe_rva_code_base pe_rva_data_base */
1616 header->nt.pe_image_base = 0x400000;
1617 header->nt.pe_section_align = 8192;
1618 header->nt.pe_file_alignment = FILE_ALIGN;
1619 header->nt.pe_os_major = 4;
1620 header->nt.pe_os_minor = 0;
1621 header->nt.pe_subsys_major = 4;
1622 /* need to set pe_image_size, pe_header_size */
1623 header->nt.pe_subsys_required = 3; /* 3 -> cmdline app, 2 -> GUI app */
1624 header->nt.pe_stack_reserve = 0x00100000;
1625 header->nt.pe_stack_commit = 0x00001000;
1626 header->nt.pe_heap_reserve = 0x00100000;
1627 header->nt.pe_heap_commit = 0x00001000;
1628 header->nt.pe_loader_flags = 1;
1629 header->nt.pe_data_dir_count = 16;
1633 header->datadir.pe_import_table
1638 header->datadir.pe_cli_header.size = CLI_H_SIZE;
1639 header->datadir.pe_cli_header.rva = assembly->text_rva; /* we put it always at the beginning */
1641 /* Write section tables */
1642 strcpy (section->st_name, ".text");
1643 section->st_virtual_size = 1024; /* FIXME */
1644 section->st_virtual_address = START_TEXT_RVA;
1645 section->st_raw_data_size = 1024; /* FIXME */
1646 section->st_raw_data_ptr = TEXT_OFFSET;
1647 section->st_flags = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
1650 * align: build_compressed_metadata () assumes metadata is aligned
1652 * cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1654 assembly->code.index += 3;
1655 assembly->code.index &= ~3;
1658 * Write the MonoCLIHeader header
1660 cli_header = (MonoCLIHeader*)(buffer + TEXT_OFFSET);
1661 cli_header->ch_size = CLI_H_SIZE;
1662 cli_header->ch_runtime_major = 2;
1663 cli_header->ch_flags = CLI_FLAGS_ILONLY;
1664 if (assemblyb->entry_point)
1665 cli_header->ch_entry_point = assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF;
1667 cli_header->ch_entry_point = 0;
1668 cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1669 cli_header->ch_metadata.size = assembly->meta_size;
1675 * We need to return always the same object for Type, MethodInfo, FieldInfo etc..
1677 static GHashTable *object_cache = NULL;
1679 #define CHECK_OBJECT(t,p) \
1682 if (!object_cache) \
1683 object_cache = g_hash_table_new (g_direct_hash, g_direct_equal); \
1684 if ((_obj = g_hash_table_lookup (object_cache, (p)))) \
1688 #define CACHE_OBJECT(p,o) \
1690 g_hash_table_insert (object_cache, p,o); \
1693 MonoReflectionAssembly*
1694 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
1696 static MonoClass *System_Reflection_Assembly;
1697 MonoReflectionAssembly *res;
1699 CHECK_OBJECT (MonoReflectionAssembly *, assembly);
1700 if (!System_Reflection_Assembly)
1701 System_Reflection_Assembly = mono_class_from_name (
1702 mono_defaults.corlib, "System.Reflection", "Assembly");
1703 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
1704 res->assembly = assembly;
1705 CACHE_OBJECT (assembly, res);
1710 mono_type_get_object (MonoDomain *domain, MonoType *type)
1712 MonoReflectionType *res;
1716 * FIXME: type may come from the cache in metadata.c, we hand out only
1717 * the types from a MonoClass structure: the long term fix is to just
1718 * load corlib always and remove the cache in metadata.c altogether.
1719 * Or we may still handle it this way so we can store in MonoType additional info
1722 klass = mono_class_from_mono_type (type);
1723 if ((type != &klass->byval_arg) && (type != &klass->this_arg)) {
1725 type = &klass->this_arg;
1727 type = &klass->byval_arg;
1729 CHECK_OBJECT (MonoReflectionType *, type);
1730 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
1732 CACHE_OBJECT (type, res);
1736 MonoReflectionMethod*
1737 mono_method_get_object (MonoDomain *domain, MonoMethod *method)
1740 * We use the same C representation for methods and constructors, but the type
1741 * name in C# is different.
1745 MonoReflectionMethod *ret;
1747 CHECK_OBJECT (MonoReflectionMethod *, method);
1748 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
1749 cname = "MonoCMethod";
1751 cname = "MonoMethod";
1752 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
1754 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
1755 ret->method = method;
1756 CACHE_OBJECT (method, ret);
1760 MonoReflectionField*
1761 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
1763 MonoReflectionField *res;
1766 CHECK_OBJECT (MonoReflectionField *, field);
1767 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
1768 res = (MonoReflectionField *)mono_object_new (domain, oklass);
1771 CACHE_OBJECT (field, res);
1775 MonoReflectionProperty*
1776 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
1778 MonoReflectionProperty *res;
1781 CHECK_OBJECT (MonoReflectionProperty *, property);
1782 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
1783 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
1785 res->property = property;
1786 CACHE_OBJECT (property, res);
1790 MonoReflectionParameter**
1791 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
1793 MonoReflectionParameter **res;
1794 MonoReflectionMethod *member;
1799 if (!method->signature->param_count)
1802 member = mono_method_get_object (domain, method);
1803 names = g_new (char *, method->signature->param_count);
1804 mono_method_get_param_names (method, (const char **) names);
1806 /* Note: the cache is based on the address of the signature into the method
1807 * since we already cache MethodInfos with the method as keys.
1809 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature));
1810 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
1811 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
1812 for (i = 0; i < method->signature->param_count; ++i) {
1813 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
1814 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
1815 res [i]->DefaultValueImpl = NULL; /* FIXME */
1816 res [i]->MemberImpl = (MonoObject*)member;
1817 res [i]->NameImpl = mono_string_new (domain, names [i]);
1818 res [i]->PositionImpl = i + 1;
1819 res [i]->AttrsImpl = method->signature->params [i]->attrs;
1822 CACHE_OBJECT (&(method->signature), res);
1827 * Parse a type name as accepted by the GetType () method and output the info
1828 * extracted in the info structure.
1829 * the name param will be mangled, so, make a copy before passing it to this function.
1830 * The fields in info will be valid until the memory pointed to by name is valid.
1831 * Returns 0 on parse error.
1834 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
1836 char *start, *p, *w, *last_point;
1837 int in_modifiers = 0;
1839 start = p = w = name;
1841 info->name = info->name_space = info->assembly = NULL;
1842 info->nest_name = info->nest_name_space = NULL;
1843 info->rank = info->isbyref = info->ispointer = 0;
1850 /* we have parsed the nesting namespace + name */
1852 info->nest_name_space = start;
1854 info->nest_name = last_point + 1;
1856 info->nest_name_space = "";
1857 info->nest_name = start;
1859 *p = 0; /* NULL terminate */
1884 info->name_space = start;
1886 info->name = last_point + 1;
1888 info->name_space = "";
1891 /* FIXME: we don't mainatin an order for byref, pointer and array... */
1899 info->ispointer = 1;
1925 return 0; /* missing assembly name */
1932 *w = 0; /* terminate class name */
1933 if (!info->name || !*info->name)
1935 if (info->nest_name && !*info->nest_name)
1937 /* add other consistency checks */
1942 dummy_runtime_invoke (MonoMethod *method, void *obj, void **params)
1944 g_error ("runtime invoke called on uninitialized runtime");
1948 MonoInvokeFunc mono_default_runtime_invoke = dummy_runtime_invoke;
1951 mono_install_runtime_invoke (MonoInvokeFunc func) {
1953 mono_default_runtime_invoke = func;
1955 mono_default_runtime_invoke = dummy_runtime_invoke;
1959 mono_runtime_invoke (MonoMethod *method, void *obj, void **params)
1961 return mono_default_runtime_invoke (method, obj, params);;
1965 * Optimization we could avoid mallocing() an little-endian archs that
1966 * don't crash with unaligned accesses.
1969 fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
1970 int len, i, slen, type;
1971 const char *p = mono_metadata_blob_heap (image, blobidx);
1973 len = mono_metadata_decode_value (p, &p);
1974 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
1979 for (i = 0; i < sig->param_count; ++i) {
1980 type = sig->params [i]->type;
1985 case MONO_TYPE_BOOLEAN: {
1986 MonoBoolean *bval = params [i] = g_malloc (sizeof (MonoBoolean));
1991 case MONO_TYPE_CHAR:
1993 case MONO_TYPE_I2: {
1994 guint16 *val = params [i] = g_malloc (sizeof (guint16));
1999 #if SIZEOF_VOID_P == 4
2005 case MONO_TYPE_I4: {
2006 guint32 *val = params [i] = g_malloc (sizeof (guint32));
2011 #if SIZEOF_VOID_P == 8
2012 case MONO_TYPE_U: /* error out instead? this should probably not happen */
2017 case MONO_TYPE_I8: {
2018 guint64 *val = params [i] = g_malloc (sizeof (guint64));
2023 case MONO_TYPE_VALUETYPE:
2024 if (sig->params [i]->data.klass->enumtype) {
2025 type = sig->params [i]->data.klass->enum_basetype->type;
2028 g_warning ("generic valutype not handled in custom attr value decoding");
2031 case MONO_TYPE_STRING: {
2032 slen = mono_metadata_decode_value (p, &p);
2033 params [i] = mono_string_new_len (mono_domain_get (), p, slen);
2038 g_warning ("Type %02x not handled in custom attr value decoding", sig->params [i]->type);
2045 free_param_data (MonoMethodSignature *sig, void **params) {
2047 for (i = 0; i < sig->param_count; ++i) {
2048 switch (sig->params [i]->type) {
2049 case MONO_TYPE_BOOLEAN:
2050 case MONO_TYPE_CHAR:
2063 case MONO_TYPE_VALUETYPE:
2064 g_free (params [i]);
2073 * Find the method index in the metadata methodDef table.
2076 find_method_index (MonoMethod *method) {
2077 MonoClass *klass = method->klass;
2080 for (i = 0; i < klass->method.count; ++i) {
2081 if (method == klass->methods [i]) {
2082 guint32 mlist = mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_TYPEDEF], mono_metadata_token_index (klass->type_token) - 1, MONO_TYPEDEF_METHOD_LIST);
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 guint32 flist = mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_TYPEDEF], mono_metadata_token_index (klass->type_token) - 1, MONO_TYPEDEF_FIELD_LIST);
2106 mono_reflection_get_custom_attrs (MonoObject *obj)
2108 guint32 index, mtoken, i;
2109 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
2119 klass = obj->vtable->klass;
2120 /* FIXME: need to handle: Module, MonoProperty */
2121 if (klass == mono_defaults.monotype_class) {
2122 MonoReflectionType *rtype = (MonoReflectionType*)obj;
2123 klass = mono_class_from_mono_type (rtype->type);
2124 index = mono_metadata_token_index (klass->type_token);
2125 index <<= CUSTOM_ATTR_BITS;
2126 index |= CUSTOM_ATTR_TYPEDEF;
2127 image = klass->image;
2128 } else if (strcmp ("Assembly", klass->name) == 0) {
2129 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
2130 index = 1; /* there is only one assembly */
2131 index <<= CUSTOM_ATTR_BITS;
2132 index |= CUSTOM_ATTR_ASSEMBLY;
2133 image = rassembly->assembly->image;
2134 } else if (strcmp ("MonoField", klass->name) == 0) {
2135 MonoReflectionField *rfield = (MonoReflectionField*)obj;
2136 index = find_field_index (rfield->klass, rfield->field);
2137 index <<= CUSTOM_ATTR_BITS;
2138 index |= CUSTOM_ATTR_FIELDDEF;
2139 image = rfield->klass->image;
2140 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
2141 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
2142 index = find_method_index (rmethod->method);
2143 index <<= CUSTOM_ATTR_BITS;
2144 index |= CUSTOM_ATTR_METHODDEF;
2145 image = method->klass->image;
2146 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
2147 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
2148 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
2149 guint32 method_index = find_method_index (rmethod->method);
2150 guint32 param_list, param_last, param_pos, found;
2152 image = rmethod->method->klass->image;
2153 ca = &image->tables [MONO_TABLE_METHOD];
2155 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
2156 if (method_index == ca->rows) {
2157 ca = &image->tables [MONO_TABLE_PARAM];
2158 param_last = ca->rows + 1;
2160 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
2161 ca = &image->tables [MONO_TABLE_PARAM];
2164 for (i = param_list; i < param_list; ++i) {
2165 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
2166 if (param_pos == param->PositionImpl) {
2172 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
2174 index <<= CUSTOM_ATTR_BITS;
2175 index |= CUSTOM_ATTR_PARAMDEF;
2176 } else { /* handle other types here... */
2177 g_error ("get custom attrs not yet supported for %s", klass->name);
2180 /* at this point image and index are set correctly for searching the custom attr */
2181 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2182 /* the table is not sorted */
2183 for (i = 0; i < ca->rows; ++i) {
2184 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
2185 if (cols [MONO_CUSTOM_ATTR_PARENT] != index)
2187 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
2188 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
2189 case CUSTOM_ATTR_TYPE_METHODDEF:
2190 mtoken |= MONO_TOKEN_METHOD_DEF;
2192 case CUSTOM_ATTR_TYPE_MEMBERREF:
2193 mtoken |= MONO_TOKEN_MEMBER_REF;
2196 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
2199 method = mono_get_method (image, mtoken, NULL);
2201 g_error ("Can't find custom attr constructor");
2202 mono_class_init (method->klass);
2203 /*g_print ("got attr %s\n", method->klass->name);*/
2204 params = g_new (void*, method->signature->param_count);
2205 fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
2206 attr = mono_object_new (mono_domain_get (), method->klass);
2207 mono_runtime_invoke (method, attr, params);
2208 list = g_list_prepend (list, attr);
2209 free_param_data (method->signature, params);
2213 index = g_list_length (list);
2215 * The return type is really object[], but System/Attribute.cs does a cast
2216 * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
2217 * probably fix that.
2219 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
2220 result = mono_array_new (mono_domain_get (), klass, index);
2221 for (i = 0; i < index; ++i) {
2222 mono_array_set (result, gpointer, i, list->data);
2225 g_list_free (g_list_first (list));
2231 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *porpValues, MonoArray *fields, MonoArray* fieldValues) {
2233 MonoMethodSignature *sig;
2235 char *buffer, *p, *argval;
2236 guint32 buflen, i, type;
2238 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
2239 g_warning ("ConstructorBuilder Custom attribute not yet supported");
2241 * maybe we should have a param array to method signature function and
2242 * continue with the normal codepath.
2244 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, 4);
2245 mono_array_set (result, char, 0, 1);
2249 p = buffer = g_malloc (buflen);
2250 /* write the prolog */
2253 sig = ((MonoReflectionMethod*)ctor)->method->signature;
2254 /* FIXME: ENOENDIAN */
2255 for (i = 0; i < sig->param_count; ++i) {
2256 if ((p-buffer) + 10 >= buflen) {
2259 newbuf = g_realloc (buffer, buflen);
2260 p = newbuf + (p-buffer);
2263 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
2264 argval = ((char*)arg + sizeof (MonoObject));
2265 type = sig->params [i]->type;
2268 case MONO_TYPE_BOOLEAN:
2273 case MONO_TYPE_CHAR:
2275 case MONO_TYPE_I2: {
2276 guint16 *val = (guint16*)p;
2277 *val = *(guint16*)argval;
2283 case MONO_TYPE_R4: {
2284 guint32 *val = (guint32*)p;
2285 *val = *(guint32*)argval;
2291 case MONO_TYPE_R8: {
2292 guint64 *val = (guint64*)p;
2293 *val = *(guint64*)argval;
2297 case MONO_TYPE_VALUETYPE:
2298 if (sig->params [i]->data.klass->enumtype) {
2299 type = sig->params [i]->data.klass->enum_basetype->type;
2302 g_warning ("generic valutype not handled in custom attr value decoding");
2305 case MONO_TYPE_STRING: {
2306 char *str = mono_string_to_utf8 ((MonoString*)arg);
2307 guint32 slen = strlen (str);
2308 if ((p-buffer) + 10 + slen >= buflen) {
2312 newbuf = g_realloc (buffer, buflen);
2313 p = newbuf + (p-buffer);
2316 mono_metadata_encode_value (slen, p, &p);
2317 memcpy (p, str, slen);
2323 g_error ("type 0x%02x not yet supported in custom attr encoder", type);
2327 * we don't support properties and fields, yet, set to 0.
2331 buflen = p - buffer;
2332 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
2333 p = mono_array_addr (result, char, 0);
2334 memcpy (p, buffer, buflen);