3 * reflection.c: Routines for creating an image at runtime.
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/tokentype.h"
15 #include "mono/metadata/appdomain.h"
16 #include "mono/metadata/opcodes.h"
24 #include "rawbuffer.h"
25 #include "mono-endian.h"
28 #define TEXT_OFFSET 512
29 #define CLI_H_SIZE 136
30 #define FILE_ALIGN 512
31 #define START_TEXT_RVA 0x00002000
34 MonoReflectionILGen *ilgen;
35 MonoReflectionType *rtype;
36 MonoArray *parameters;
41 guint32 *table_idx; /* note: it's a pointer */
45 } ReflectionMethodBuilder;
47 const unsigned char table_sizes [64] = {
57 MONO_INTERFACEIMPL_SIZE,
58 MONO_MEMBERREF_SIZE, /* 0x0A */
60 MONO_CUSTOM_ATTR_SIZE,
61 MONO_FIELD_MARSHAL_SIZE,
62 MONO_DECL_SECURITY_SIZE,
63 MONO_CLASS_LAYOUT_SIZE,
64 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
65 MONO_STAND_ALONE_SIGNATURE_SIZE,
69 MONO_PROPERTY_MAP_SIZE,
72 MONO_METHOD_SEMA_SIZE,
74 MONO_MODULEREF_SIZE, /* 0x1A */
80 MONO_ASSEMBLY_SIZE, /* 0x20 */
81 MONO_ASSEMBLY_PROCESSOR_SIZE,
83 MONO_ASSEMBLYREF_SIZE,
84 MONO_ASSEMBLYREFPROC_SIZE,
85 MONO_ASSEMBLYREFOS_SIZE,
89 MONO_NESTED_CLASS_SIZE,
93 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
94 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
97 alloc_table (MonoDynamicTable *table, guint nrows)
100 g_assert (table->columns);
101 table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
105 string_heap_insert (MonoDynamicStream *sh, const char *str)
109 gpointer oldkey, oldval;
111 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
112 return GPOINTER_TO_UINT (oldval);
114 len = strlen (str) + 1;
116 if (idx + len > sh->alloc_size) {
117 sh->alloc_size += len + 4096;
118 sh->data = g_realloc (sh->data, sh->alloc_size);
121 * We strdup the string even if we already copy them in sh->data
122 * so that the string pointers in the hash remain valid even if
123 * we need to realloc sh->data. We may want to avoid that later.
125 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
126 memcpy (sh->data + idx, str, len);
132 string_heap_init (MonoDynamicStream *sh)
135 sh->alloc_size = 4096;
136 sh->data = g_malloc (4096);
137 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
138 string_heap_insert (sh, "");
142 string_heap_free (MonoDynamicStream *sh)
145 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
146 g_hash_table_destroy (sh->hash);
150 mono_image_add_stream_data (MonoDynamicStream *stream, char *data, guint32 len)
153 if (stream->alloc_size < stream->index + len) {
154 stream->alloc_size += len + 4096;
155 stream->data = g_realloc (stream->data, stream->alloc_size);
157 memcpy (stream->data + stream->index, data, len);
159 stream->index += len;
161 * align index? Not without adding an additional param that controls it since
162 * we may store a blob value in pieces.
168 stream_data_align (MonoDynamicStream *stream)
171 guint32 count = stream->index % 4;
173 /* we assume the stream data will be aligned */
175 mono_image_add_stream_data (stream, buf, 4 - count);
179 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
182 g_assert_not_reached ();
187 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
191 case MONO_TYPE_BOOLEAN:
205 case MONO_TYPE_STRING:
206 case MONO_TYPE_OBJECT:
207 case MONO_TYPE_TYPEDBYREF:
208 mono_metadata_encode_value (type->type, p, &p);
211 g_print ("encode pointer\n");
212 case MONO_TYPE_SZARRAY:
213 mono_metadata_encode_value (type->type, p, &p);
214 encode_type (assembly, type->data.type, p, &p);
216 case MONO_TYPE_VALUETYPE:
217 case MONO_TYPE_CLASS:
218 mono_metadata_encode_value (type->type, p, &p);
219 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
221 case MONO_TYPE_ARRAY:
222 mono_metadata_encode_value (type->type, p, &p);
223 encode_type (assembly, type->data.array->type, p, &p);
224 mono_metadata_encode_value (type->data.array->rank, p, &p);
225 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
226 mono_metadata_encode_value (0, p, &p);
229 g_error ("need to encode type %x", type->type);
235 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
238 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
242 encode_type (assembly, type->type, p, endbuf);
246 g_assert_not_reached ();
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 g_assert (p - buf < size);
276 mono_metadata_encode_value (p-buf, b, &b);
277 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
278 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
284 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
287 * FIXME: reuse code from method_encode_signature().
292 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
293 guint32 size = 10 + nparams * 10;
298 p = buf = g_malloc (size);
299 /* LAMESPEC: all the call conv spec is foobared */
300 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
301 if (mb->call_conv & 2)
302 *p |= 0x5; /* vararg */
303 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
304 *p |= 0x20; /* hasthis */
306 mono_metadata_encode_value (nparams, p, &p);
307 encode_reflection_type (assembly, mb->rtype, p, &p);
308 for (i = 0; i < nparams; ++i) {
309 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
310 encode_reflection_type (assembly, pt, p, &p);
313 g_assert (p - buf < size);
314 mono_metadata_encode_value (p-buf, b, &b);
315 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
316 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
322 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
324 MonoDynamicTable *table;
327 guint32 idx, sig_idx, size;
328 guint nl = mono_array_length (ilgen->locals);
335 p = buf = g_malloc (size);
336 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
337 idx = table->next_idx ++;
339 alloc_table (table, table->rows);
340 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
342 mono_metadata_encode_value (0x07, p, &p);
343 mono_metadata_encode_value (nl, p, &p);
344 for (i = 0; i < nl; ++i) {
345 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
346 encode_reflection_type (assembly, lb->type, p, &p);
348 g_assert (p - buf < size);
349 mono_metadata_encode_value (p-buf, b, &b);
350 sig_idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
351 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
354 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
360 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
366 gint32 num_locals = 0;
367 gint32 num_exception = 0;
370 char fat_header [12];
373 guint32 local_sig = 0;
374 guint32 header_size = 12;
377 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
378 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
379 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
380 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
384 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
386 code = mb->ilgen->code;
387 code_size = mb->ilgen->code_len;
388 max_stack = mb->ilgen->max_stack;
389 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
390 if (mb->ilgen->ex_handlers) {
391 MonoILExceptionInfo *ex_info;
392 for (i = 0; i < mono_array_length (mb->ilgen->ex_handlers); ++i) {
393 ex_info = (MonoILExceptionInfo*)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
394 if (ex_info->handlers)
395 num_exception += mono_array_length (ex_info->handlers);
402 code_size = mono_array_length (code);
403 max_stack = 8; /* we probably need to run a verifier on the code... */
406 /* check for exceptions, maxstack, locals */
407 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
409 if (code_size < 64 && !(code_size & 1)) {
410 flags = (code_size << 2) | 0x2;
411 } else if (code_size < 32 && (code_size & 1)) {
412 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
416 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
417 /* add to the fixup todo list */
418 if (mb->ilgen && mb->ilgen->num_token_fixups)
419 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
420 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
421 return assembly->text_rva + idx + CLI_H_SIZE;
425 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
427 * FIXME: need to set also the header size in fat_flags.
428 * (and more sects and init locals flags)
432 fat_flags |= METHOD_HEADER_MORE_SECTS;
433 fat_header [0] = fat_flags;
434 fat_header [1] = (header_size / 4 ) << 4;
435 shortp = (guint16*)(fat_header + 2);
437 intp = (guint32*)(fat_header + 4);
439 intp = (guint32*)(fat_header + 8);
441 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
442 /* add to the fixup todo list */
443 if (mb->ilgen && mb->ilgen->num_token_fixups)
444 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
446 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
448 unsigned char sheader [4];
449 MonoExceptionClause clause;
450 MonoILExceptionInfo * ex_info;
451 MonoILExceptionBlock * ex_block;
454 stream_data_align (&assembly->code);
455 /* always use fat format for now */
456 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
457 num_exception *= sizeof (MonoExceptionClause);
458 sheader [1] = num_exception & 0xff;
459 sheader [2] = (num_exception >> 8) & 0xff;
460 sheader [3] = (num_exception >> 16) & 0xff;
461 mono_image_add_stream_data (&assembly->code, sheader, 4);
462 /* fat header, so we are already aligned */
464 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
465 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
466 if (ex_info->handlers) {
467 int finally_start = 0;
468 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
469 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
470 clause.flags = ex_block->type;
471 clause.try_offset = ex_info->start;
472 /* need fault, too, probably */
473 if (clause.flags == MONO_EXCEPTION_CLAUSE_FINALLY)
474 clause.try_len = finally_start - ex_info->start;
476 clause.try_len = ex_info->len;
477 clause.handler_offset = ex_block->start;
478 clause.handler_len = ex_block->len;
479 finally_start = clause.handler_offset + clause.handler_len;
480 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
481 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
482 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d\n",
483 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len);*/
484 /* FIXME: ENOENDIAN */
485 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
488 g_error ("No clauses");
492 return assembly->text_rva + idx + CLI_H_SIZE;
496 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 index)
499 MonoDynamicTable *table;
502 table = &assembly->tables [table_idx];
504 g_assert (col < table->columns);
506 values = table->values + table->columns;
507 for (i = 1; i <= table->rows; ++i) {
508 if (values [col] == index)
515 * index is the table index of the object
516 * type is one of CUSTOM_ATTR_*
519 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 index, guint32 type, MonoArray *cattrs)
521 MonoDynamicTable *table;
522 MonoReflectionCustomAttr *cattr;
524 guint32 count, i, token;
528 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
531 count = mono_array_length (cattrs);
532 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
533 table->rows += count;
534 alloc_table (table, table->rows);
535 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
536 index <<= CUSTOM_ATTR_BITS;
538 for (i = 0; i < count; ++i) {
539 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
540 values [MONO_CUSTOM_ATTR_PARENT] = index;
541 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
542 type = mono_metadata_token_index (token);
543 type <<= CUSTOM_ATTR_TYPE_BITS;
544 switch (mono_metadata_token_table (token)) {
545 case MONO_TABLE_METHOD:
546 type |= CUSTOM_ATTR_TYPE_METHODDEF;
548 case MONO_TABLE_MEMBERREF:
549 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
552 g_error ("got wrong token in custom attr");
554 values [MONO_CUSTOM_ATTR_TYPE] = type;
556 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
557 values [MONO_CUSTOM_ATTR_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, p - blob_size);
558 mono_image_add_stream_data (&assembly->blob,
559 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
560 values += MONO_CUSTOM_ATTR_SIZE;
566 * Fill in the MethodDef and ParamDef tables for a method.
567 * This is used for both normal methods and constructors.
570 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
572 MonoDynamicTable *table;
577 /* room in this table is already allocated */
578 table = &assembly->tables [MONO_TABLE_METHOD];
579 *mb->table_idx = table->next_idx ++;
580 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
582 name = mono_string_to_utf8 (mb->name);
583 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
585 } else { /* a constructor */
586 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
588 values [MONO_METHOD_FLAGS] = mb->attrs;
589 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
590 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
591 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
593 table = &assembly->tables [MONO_TABLE_PARAM];
594 values [MONO_METHOD_PARAMLIST] = table->next_idx;
598 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
599 if (mono_array_get (mb->pinfo, gpointer, i))
602 table->rows += count;
603 alloc_table (table, table->rows);
604 values = table->values + table->next_idx * MONO_PARAM_SIZE;
605 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
606 MonoReflectionParamBuilder *pb;
607 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
608 values [MONO_PARAM_FLAGS] = pb->attrs;
609 values [MONO_PARAM_SEQUENCE] = i;
610 name = mono_string_to_utf8 (pb->name);
611 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
613 values += MONO_PARAM_SIZE;
615 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
622 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
624 MonoDynamicTable *table;
627 ReflectionMethodBuilder rmb;
629 rmb.ilgen = mb->ilgen;
630 rmb.rtype = mb->rtype;
631 rmb.parameters = mb->parameters;
632 rmb.pinfo = mb->pinfo;
633 rmb.attrs = mb->attrs;
634 rmb.iattrs = mb->iattrs;
635 rmb.call_conv = mb->call_conv;
639 rmb.table_idx = &mb->table_idx;
641 mono_image_basic_method (&rmb, assembly);
643 if (mb->dll) { /* It's a P/Invoke method */
645 table = &assembly->tables [MONO_TABLE_IMPLMAP];
647 alloc_table (table, table->rows);
648 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
649 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
650 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
651 name = mono_string_to_utf8 (mb->dllentry);
652 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
654 name = mono_string_to_utf8 (mb->dll);
655 moduleref = string_heap_insert (&assembly->sheap, name);
657 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
658 table = &assembly->tables [MONO_TABLE_MODULEREF];
660 alloc_table (table, table->rows);
661 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
662 values [MONO_IMPLMAP_SCOPE] = table->rows;
665 if (mb->override_method) {
666 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
667 table = &assembly->tables [MONO_TABLE_METHODIMPL];
669 alloc_table (table, table->rows);
670 values = table->values + table->rows * MONO_MTHODIMPL_SIZE;
671 values [MONO_MTHODIMPL_CLASS] = tb->table_idx;
672 values [MONO_MTHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
673 if (mb->override_method->method)
674 values [MONO_MTHODIMPL_DECLARATION] = mono_image_get_methodref_token (assembly, mb->override_method->method);
676 MonoReflectionMethodBuilder *omb = (MonoReflectionMethodBuilder*)mb->override_method;
677 values [MONO_MTHODIMPL_DECLARATION] = METHODDEFORREF_METHODDEF | (omb->table_idx << METHODDEFORREF_BITS);
680 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
684 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
686 ReflectionMethodBuilder rmb;
688 rmb.ilgen = mb->ilgen;
689 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
690 rmb.parameters = mb->parameters;
691 rmb.pinfo = mb->pinfo;
692 rmb.attrs = mb->attrs;
693 rmb.iattrs = mb->iattrs;
694 rmb.call_conv = mb->call_conv;
698 rmb.table_idx = &mb->table_idx;
700 mono_image_basic_method (&rmb, assembly);
701 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
706 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
714 p = buf = g_malloc (64);
716 /* No start code with field refs...
717 * mono_metadata_encode_value (0x06, p, &p);
719 /* encode custom attributes before the type */
720 encode_type (assembly, field->type, p, &p);
721 g_assert (p-buf < 64);
722 mono_metadata_encode_value (p-buf, b, &b);
723 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
724 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
730 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
738 p = buf = g_malloc (64);
740 mono_metadata_encode_value (0x06, p, &p);
741 /* encode custom attributes before the type */
742 encode_reflection_type (assembly, fb->type, p, &p);
743 g_assert (p-buf < 64);
744 mono_metadata_encode_value (p-buf, b, &b);
745 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
746 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
752 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
759 p = buf = g_malloc (64);
761 box_val = ((char*)val) + sizeof (MonoObject);
762 *ret_type = val->vtable->klass->byval_arg.type;
765 case MONO_TYPE_BOOLEAN:
785 case MONO_TYPE_VALUETYPE:
786 if (val->vtable->klass->enumtype) {
787 *ret_type = val->vtable->klass->enum_basetype->type;
790 g_error ("we can't encode valuetypes");
791 case MONO_TYPE_STRING:
793 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
796 /* there is no signature */
797 mono_metadata_encode_value (len, b, &b);
798 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
799 /* FIXME: ENOENDIAN */
800 mono_image_add_stream_data (&assembly->blob, box_val, len);
807 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
809 MonoDynamicTable *table;
813 table = &assembly->tables [MONO_TABLE_FIELD];
814 fb->table_idx = table->next_idx ++;
815 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
816 name = mono_string_to_utf8 (fb->name);
817 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
819 values [MONO_FIELD_FLAGS] = fb->attrs;
820 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
822 if (fb->offset != -1) {
823 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
825 alloc_table (table, table->rows);
826 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
827 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
828 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
830 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
831 guint32 field_type = 0;
832 table = &assembly->tables [MONO_TABLE_CONSTANT];
834 alloc_table (table, table->rows);
835 values = table->values + table->rows * MONO_CONSTANT_SIZE;
836 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
837 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
838 values [MONO_CONSTANT_TYPE] = field_type;
839 values [MONO_CONSTANT_PADDING] = 0;
843 table = &assembly->tables [MONO_TABLE_FIELDRVA];
845 alloc_table (table, table->rows);
846 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
847 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
849 * We store it in the code section because it's simpler for now.
851 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
852 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva + CLI_H_SIZE;
854 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
858 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
864 MonoReflectionMethodBuilder *mb = fb->get_method;
865 guint32 idx, i, size;
867 if (mb && mb->parameters)
868 nparams = mono_array_length (mb->parameters);
869 size = 24 + nparams * 10;
870 buf = p = g_malloc (size);
873 mono_metadata_encode_value (nparams, p, &p);
875 encode_reflection_type (assembly, mb->rtype, p, &p);
876 for (i = 0; i < nparams; ++i) {
877 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
878 encode_reflection_type (assembly, pt, p, &p);
881 *p++ = 1; /* void: a property should probably not be allowed without a getter */
884 g_assert (p - buf < size);
885 mono_metadata_encode_value (p-buf, b, &b);
886 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
887 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
893 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
895 MonoDynamicTable *table;
898 guint num_methods = 0;
902 * we need to set things in the following tables:
903 * PROPERTYMAP (info already filled in _get_type_info ())
904 * PROPERTY (rows already preallocated in _get_type_info ())
905 * METHOD (method info already done with the generic method code)
908 table = &assembly->tables [MONO_TABLE_PROPERTY];
909 pb->table_idx = table->next_idx ++;
910 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
911 name = mono_string_to_utf8 (pb->name);
912 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
914 values [MONO_PROPERTY_FLAGS] = pb->attrs;
915 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
917 /* FIXME: we still don't handle 'other' methods */
918 if (pb->get_method) num_methods ++;
919 if (pb->set_method) num_methods ++;
921 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
922 table->rows += num_methods;
923 alloc_table (table, table->rows);
925 if (pb->get_method) {
926 semaidx = table->next_idx ++;
927 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
928 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
929 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
930 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
932 if (pb->set_method) {
933 semaidx = table->next_idx ++;
934 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
935 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
936 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
937 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
939 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
943 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
945 MonoDynamicTable *table;
948 guint num_methods = 0;
952 * we need to set things in the following tables:
953 * EVENTMAP (info already filled in _get_type_info ())
954 * EVENT (rows already preallocated in _get_type_info ())
955 * METHOD (method info already done with the generic method code)
958 table = &assembly->tables [MONO_TABLE_EVENT];
959 eb->table_idx = table->next_idx ++;
960 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
961 name = mono_string_to_utf8 (eb->name);
962 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
964 values [MONO_EVENT_FLAGS] = eb->attrs;
965 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
968 * FIXME: we still don't handle 'other' methods
970 if (eb->add_method) num_methods ++;
971 if (eb->remove_method) num_methods ++;
972 if (eb->raise_method) num_methods ++;
974 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
975 table->rows += num_methods;
976 alloc_table (table, table->rows);
978 if (eb->add_method) {
979 semaidx = table->next_idx ++;
980 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
981 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
982 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
983 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
985 if (eb->remove_method) {
986 semaidx = table->next_idx ++;
987 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
988 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
989 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
990 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
992 if (eb->raise_method) {
993 semaidx = table->next_idx ++;
994 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
995 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
996 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
997 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
999 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1003 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
1005 MonoDynamicTable *table;
1008 guint32 cols [MONO_ASSEMBLY_SIZE];
1010 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, image))))
1013 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1015 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1016 token = table->next_idx ++;
1018 alloc_table (table, table->rows);
1019 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1020 if (strcmp ("corlib", image->assembly_name) == 0)
1021 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1023 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1024 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1025 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1026 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1027 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1028 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1029 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1030 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1031 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1033 token <<= RESOLTION_SCOPE_BITS;
1034 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1035 g_hash_table_insert (assembly->typeref, image, GUINT_TO_POINTER (token));
1040 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1042 MonoDynamicTable *table;
1047 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1050 klass = mono_class_from_mono_type (type);
1052 * If it's in the same module:
1054 if (klass->image == assembly->assembly.image) {
1055 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1056 return TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1059 table = &assembly->tables [MONO_TABLE_TYPEREF];
1060 alloc_table (table, table->rows + 1);
1061 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1062 values [MONO_TYPEREF_SCOPE] = resolution_scope_from_image (assembly, klass->image);
1063 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1064 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1065 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1066 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1072 * Insert a memberef row into the metadata: the token that point to the memberref
1073 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1074 * mono_image_get_fieldref_token()).
1075 * The sig param is an index to an already built signature.
1078 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoClass *klass, const char *name, guint32 sig)
1080 MonoDynamicTable *table;
1082 guint32 token, pclass;
1085 parent = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1086 switch (parent & TYPEDEFORREF_MASK) {
1087 case TYPEDEFORREF_TYPEREF:
1088 pclass = MEMBERREF_PARENT_TYPEREF;
1090 case TYPEDEFORREF_TYPESPEC:
1091 pclass = MEMBERREF_PARENT_TYPESPEC;
1093 case TYPEDEFORREF_TYPEDEF:
1094 /* should never get here */
1096 g_error ("unknow typeref or def token");
1098 /* extract the index */
1099 parent >>= TYPEDEFORREF_BITS;
1101 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1102 alloc_table (table, table->rows + 1);
1103 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1104 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1105 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1106 values [MONO_MEMBERREF_SIGNATURE] = sig;
1107 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1114 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1118 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, method));
1121 token = mono_image_get_memberref_token (assembly, method->klass,
1122 method->name, method_encode_signature (assembly, method->signature));
1123 g_hash_table_insert (assembly->typeref, method, GUINT_TO_POINTER(token));
1128 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1132 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, field));
1135 token = mono_image_get_memberref_token (assembly, klass,
1136 field->name, fieldref_encode_signature (assembly, field));
1137 g_hash_table_insert (assembly->typeref, field, GUINT_TO_POINTER(token));
1142 * Insert into the metadata tables all the info about the TypeBuilder tb.
1143 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1146 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1148 MonoDynamicTable *table;
1153 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1154 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1155 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1156 if (tb->parent) { /* interfaces don't have a parent */
1157 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1159 values [MONO_TYPEDEF_EXTENDS] = 0;
1160 n = mono_string_to_utf8 (tb->name);
1161 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1163 n = mono_string_to_utf8 (tb->nspace);
1164 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1166 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1167 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1170 * if we have explicitlayout or sequentiallayouts, output data in the
1171 * ClassLayout table.
1173 if ((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1174 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1176 alloc_table (table, table->rows);
1177 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1178 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1179 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1180 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1183 /* handle interfaces */
1184 if (tb->interfaces) {
1185 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1187 table->rows += mono_array_length (tb->interfaces);
1188 alloc_table (table, table->rows);
1189 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1190 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1191 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1192 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1193 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1194 values += MONO_INTERFACEIMPL_SIZE;
1200 table = &assembly->tables [MONO_TABLE_FIELD];
1201 table->rows += mono_array_length (tb->fields);
1202 alloc_table (table, table->rows);
1203 for (i = 0; i < mono_array_length (tb->fields); ++i)
1204 mono_image_get_field_info (
1205 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1208 /* handle constructors */
1210 table = &assembly->tables [MONO_TABLE_METHOD];
1211 table->rows += mono_array_length (tb->ctors);
1212 alloc_table (table, table->rows);
1213 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1214 mono_image_get_ctor_info (domain,
1215 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1218 /* handle methods */
1220 table = &assembly->tables [MONO_TABLE_METHOD];
1221 table->rows += mono_array_length (tb->methods);
1222 alloc_table (table, table->rows);
1223 for (i = 0; i < mono_array_length (tb->methods); ++i)
1224 mono_image_get_method_info (
1225 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1228 /* Do the same with properties etc.. */
1230 * FIXME: note that the methodsemantics table needs to be sorted, so events
1231 * go before properties; not sure if this is enough...
1233 if (tb->events && mono_array_length (tb->events)) {
1234 table = &assembly->tables [MONO_TABLE_EVENT];
1235 table->rows += mono_array_length (tb->events);
1236 alloc_table (table, table->rows);
1237 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1239 alloc_table (table, table->rows);
1240 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1241 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1242 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1243 for (i = 0; i < mono_array_length (tb->events); ++i)
1244 mono_image_get_event_info (
1245 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1247 if (tb->properties && mono_array_length (tb->properties)) {
1248 table = &assembly->tables [MONO_TABLE_PROPERTY];
1249 table->rows += mono_array_length (tb->properties);
1250 alloc_table (table, table->rows);
1251 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1253 alloc_table (table, table->rows);
1254 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1255 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1256 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1257 for (i = 0; i < mono_array_length (tb->properties); ++i)
1258 mono_image_get_property_info (
1259 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1262 MonoDynamicTable *ntable;
1264 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1265 table->rows += mono_array_length (tb->subtypes);
1266 alloc_table (table, table->rows);
1268 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1269 ntable->rows += mono_array_length (tb->subtypes);
1270 alloc_table (ntable, ntable->rows);
1271 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1273 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1274 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1276 mono_image_get_type_info (domain, subtype, assembly);
1277 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1278 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1279 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1280 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1281 mono_string_to_utf8 (tb->name), tb->table_idx,
1282 ntable->next_idx, ntable->rows);*/
1283 values += MONO_NESTED_CLASS_SIZE;
1287 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1291 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1293 MonoDynamicTable *table;
1297 table = &assembly->tables [MONO_TABLE_MODULE];
1298 mb->table_idx = table->next_idx ++;
1299 name = mono_string_to_utf8 (mb->module.name);
1300 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1302 /* need to set mvid? */
1304 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1306 * fill-in info in other tables as well.
1308 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1309 table->rows += mono_array_length (mb->types);
1310 alloc_table (table, table->rows);
1312 * We assign here the typedef indexes to avoid mismatches if a type that
1313 * has not yet been stored in the tables is referenced by another type.
1315 for (i = 0; i < mono_array_length (mb->types); ++i) {
1317 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1318 type->table_idx = table->next_idx ++;
1319 if (!type->subtypes)
1321 for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1322 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1323 subtype->table_idx = table->next_idx ++;
1326 for (i = 0; i < mono_array_length (mb->types); ++i)
1327 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1330 #define align_pointer(base,p)\
1332 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1334 (p) += 4 - (__diff & 3);\
1338 * build_compressed_metadata() fills in the blob of data that represents the
1339 * raw metadata as it will be saved in the PE file. The five streams are output
1340 * and the metadata tables are comnpressed from the guint32 array representation,
1341 * to the compressed on-disk format.
1344 build_compressed_metadata (MonoDynamicAssembly *assembly)
1347 guint64 valid_mask = 0;
1348 guint64 sorted_mask;
1349 guint32 heapt_size = 0;
1350 guint32 meta_size = 256; /* allow for header and other stuff */
1351 guint32 table_offset;
1352 guint32 ntables = 0;
1358 char *version = "mono" VERSION;
1361 MonoDynamicStream *stream;
1362 } stream_desc [] = {
1363 {"#~", &assembly->tstream},
1364 {"#Strings", &assembly->sheap},
1365 {"#US", &assembly->us},
1366 {"#Blob", &assembly->blob},
1367 {"#GUID", &assembly->guid},
1370 /* tables that are sorted */
1371 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
1372 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
1373 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
1374 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
1375 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
1376 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
1378 /* Compute table sizes */
1379 /* the MonoImage has already been created in mono_image_basic_init() */
1380 meta = assembly->assembly.image;
1382 /* Setup the info used by compute_sizes () */
1383 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1384 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1385 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1387 meta_size += assembly->blob.index;
1388 meta_size += assembly->guid.index;
1389 meta_size += assembly->sheap.index;
1390 meta_size += assembly->us.index;
1392 for (i=0; i < 64; ++i)
1393 meta->tables [i].rows = assembly->tables [i].rows;
1395 for (i = 0; i < 64; i++){
1396 if (meta->tables [i].rows == 0)
1398 valid_mask |= (guint64)1 << i;
1400 meta->tables [i].row_size = mono_metadata_compute_size (
1401 meta, i, &meta->tables [i].size_bitfield);
1402 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1404 heapt_size += 24; /* #~ header size */
1405 heapt_size += ntables * 4;
1406 meta_size += heapt_size;
1407 meta->raw_metadata = g_malloc0 (meta_size);
1408 p = meta->raw_metadata;
1409 /* the metadata signature */
1410 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1411 /* version numbers and 4 bytes reserved */
1412 int16val = (guint16*)p;
1416 /* version string */
1417 int32val = (guint32*)p;
1418 *int32val = strlen (version);
1420 memcpy (p, version, *int32val);
1422 align_pointer (meta->raw_metadata, p);
1423 int16val = (guint16*)p;
1424 *int16val++ = 0; /* flags must be 0 */
1425 *int16val = 5; /* number of streams */
1429 * write the stream info.
1431 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1432 table_offset += 3; table_offset &= ~3;
1434 assembly->tstream.index = heapt_size;
1435 for (i = 0; i < 5; ++i) {
1436 int32val = (guint32*)p;
1437 *int32val++ = stream_desc [i].stream->offset = table_offset;
1438 *int32val = stream_desc [i].stream->index;
1439 table_offset += *int32val;
1440 table_offset += 3; table_offset &= ~3;
1442 strcpy (p, stream_desc [i].name);
1443 p += strlen (stream_desc [i].name) + 1;
1444 align_pointer (meta->raw_metadata, p);
1447 * now copy the data, the table stream header and contents goes first.
1449 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1450 p = meta->raw_metadata + assembly->tstream.offset;
1451 int32val = (guint32*)p;
1452 *int32val = 0; /* reserved */
1454 *p++ = 1; /* version */
1456 if (meta->idx_string_wide)
1458 if (meta->idx_guid_wide)
1460 if (meta->idx_blob_wide)
1463 *p++ = 0; /* reserved */
1464 int64val = (guint64*)p;
1465 *int64val++ = valid_mask;
1466 *int64val++ = valid_mask & sorted_mask; /* bitvector of sorted tables */
1468 int32val = (guint32*)p;
1469 for (i = 0; i < 64; i++){
1470 if (meta->tables [i].rows == 0)
1472 *int32val++ = meta->tables [i].rows;
1474 p = (unsigned char*)int32val;
1475 /* compress the tables */
1476 for (i = 0; i < 64; i++){
1479 guint32 bitfield = meta->tables [i].size_bitfield;
1480 if (!meta->tables [i].rows)
1482 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1483 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1484 meta->tables [i].base = p;
1485 for (row = 1; row <= meta->tables [i].rows; ++row) {
1486 values = assembly->tables [i].values + row * assembly->tables [i].columns;
1487 for (col = 0; col < assembly->tables [i].columns; ++col) {
1488 switch (mono_metadata_table_size (bitfield, col)) {
1490 *p++ = values [col];
1493 int16val = (guint16*)p;
1494 *int16val = values [col];
1498 int32val = (guint32*)p;
1499 *int32val = values [col];
1503 g_assert_not_reached ();
1507 g_assert ((p - (unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1510 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1511 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1512 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1513 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1514 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1516 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1520 * Some tables in metadata need to be sorted according to some criteria, but
1521 * when methods and fields are first created with reflection, they may be assigned a token
1522 * that doesn't correspond to the final token they will get assigned after the sorting.
1523 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
1524 * with the reflection objects that represent them. Once all the tables are set up, the
1525 * reflection objects will contains the correct table index. fixup_method() will fixup the
1526 * tokens for the method with ILGenerator @ilgen.
1529 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
1530 guint32 code_idx = GPOINTER_TO_UINT (value);
1531 MonoReflectionILTokenInfo *iltoken;
1532 MonoReflectionFieldBuilder *field;
1533 MonoReflectionCtorBuilder *ctor;
1534 MonoReflectionMethodBuilder *method;
1536 unsigned char *target;
1538 for (i = 0; i < ilgen->num_token_fixups; ++i) {
1539 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
1540 target = assembly->code.data + code_idx + iltoken->code_pos;
1541 switch (target [3]) {
1542 case MONO_TABLE_FIELD:
1543 if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
1544 g_assert_not_reached ();
1545 field = (MonoReflectionFieldBuilder *)iltoken->member;
1546 index = field->table_idx;
1548 case MONO_TABLE_METHOD:
1549 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1550 method = (MonoReflectionMethodBuilder *)iltoken->member;
1551 index = method->table_idx;
1552 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1553 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
1554 index = ctor->table_idx;
1556 g_assert_not_reached ();
1560 g_error ("got unexpected table 0x%02x in fixup", target [3]);
1562 target [0] = index & 0xff;
1563 target [1] = (index >> 8) & 0xff;
1564 target [2] = (index >> 16) & 0xff;
1569 * mono_image_build_metadata() will fill the info in all the needed metadata tables
1570 * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
1571 * and recursively outputs the info for a module. Each module will output all the info
1572 * about it's types etc.
1573 * At the end of the process, method and field tokens are fixed up and the on-disk
1574 * compressed metadata representation is created.
1577 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
1579 MonoDynamicTable *table;
1580 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
1581 MonoDomain *domain = ((MonoObject *)assemblyb)->vtable->domain;
1587 assembly->text_rva = START_TEXT_RVA;
1589 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
1590 alloc_table (table, 1);
1591 values = table->values + MONO_ASSEMBLY_SIZE;
1592 values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
1593 name = mono_string_to_utf8 (assemblyb->name);
1594 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
1596 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
1597 values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
1598 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1599 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1600 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1601 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1603 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
1605 assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
1606 assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
1608 if (assemblyb->modules) {
1609 len = mono_array_length (assemblyb->modules);
1610 table = &assembly->tables [MONO_TABLE_MODULE];
1611 alloc_table (table, len);
1612 for (i = 0; i < len; ++i)
1613 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
1615 table = &assembly->tables [MONO_TABLE_MODULE];
1617 alloc_table (table, table->rows);
1618 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
1622 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1624 * table->rows is already set above and in mono_image_fill_module_table.
1626 alloc_table (table, table->rows);
1628 * Set the first entry.
1630 values = table->values + table->columns;
1631 values [MONO_TYPEDEF_FLAGS] = 0;
1632 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
1633 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
1634 values [MONO_TYPEDEF_EXTENDS] = 0;
1635 values [MONO_TYPEDEF_FIELD_LIST] = 1;
1636 values [MONO_TYPEDEF_METHOD_LIST] = 1;
1639 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
1641 build_compressed_metadata (assembly);
1645 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
1651 if (!assembly->dynamic_assembly)
1652 mono_image_basic_init (assembly);
1653 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
1654 index = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
1655 /* FIXME: ENOENDIAN */
1656 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (char*)mono_string_chars (str), str->length * 2);
1657 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
1658 return MONO_TOKEN_STRING | index;
1662 * Get a token to insert in the IL code stream for the given MemberInfo.
1664 * ConstructorBuilder
1674 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
1680 g_error ("System.Array methods not yet supported");
1682 klass = obj->vtable->klass;
1683 if (strcmp (klass->name, "MethodBuilder") == 0) {
1684 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
1685 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1686 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1689 if (strcmp (klass->name, "ConstructorBuilder") == 0) {
1690 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
1691 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1692 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1695 if (strcmp (klass->name, "FieldBuilder") == 0) {
1696 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
1697 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
1699 if (strcmp (klass->name, "TypeBuilder") == 0) {
1700 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
1701 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
1703 if (strcmp (klass->name, "MonoType") == 0) {
1704 MonoReflectionType *tb = (MonoReflectionType *)obj;
1705 return mono_metadata_token_from_dor (
1706 mono_image_typedef_or_ref (assembly, tb->type));
1708 if (strcmp (klass->name, "MonoCMethod") == 0 ||
1709 strcmp (klass->name, "MonoMethod") == 0) {
1710 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
1711 token = mono_image_get_methodref_token (assembly, m->method);
1712 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1715 if (strcmp (klass->name, "MonoField") == 0) {
1716 MonoReflectionField *f = (MonoReflectionField *)obj;
1717 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
1718 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1721 g_print ("requested token for %s\n", klass->name);
1726 * Create the MonoImage that represents the assembly builder and setup some
1727 * of the helper hash table and the basic metadata streams.
1730 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1732 MonoDynamicAssembly *assembly;
1736 if (assemblyb->dynamic_assembly)
1740 assembly = assemblyb->dynamic_assembly = GC_malloc (sizeof (MonoDynamicAssembly));
1742 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1745 assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
1746 assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
1748 string_heap_init (&assembly->sheap);
1749 mono_image_add_stream_data (&assembly->us, "", 1);
1750 mono_image_add_stream_data (&assembly->blob, "", 1);
1752 for (i=0; i < 64; ++i) {
1753 assembly->tables [i].next_idx = 1;
1754 assembly->tables [i].columns = table_sizes [i];
1757 image = g_new0 (MonoImage, 1);
1759 /* keep in sync with image.c */
1760 image->name = mono_string_to_utf8 (assemblyb->name);
1761 image->assembly_name = image->name; /* they may be different */
1763 image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
1764 image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
1765 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
1766 image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
1768 assembly->assembly.image = image;
1773 * When we need to save an assembly, we first call this function that ensures the metadata
1774 * tables are built for all the modules in the assembly. This function creates the PE-COFF
1775 * header, the image sections, the CLI header etc. The header is written in @buffer
1776 * and the length of the data written is returned.
1779 mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, int maxsize)
1781 MonoMSDOSHeader *msdos;
1782 MonoDotNetHeader *header;
1783 MonoSectionTable *section;
1784 MonoCLIHeader *cli_header;
1785 guint32 header_size = TEXT_OFFSET + CLI_H_SIZE;
1786 MonoDynamicAssembly *assembly;
1788 static const unsigned char msheader[] = {
1789 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
1790 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1791 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1792 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
1793 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
1794 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
1795 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
1796 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1799 if (maxsize < header_size)
1802 mono_image_basic_init (assemblyb);
1803 assembly = assemblyb->dynamic_assembly;
1805 mono_image_build_metadata (assemblyb);
1807 memset (buffer, 0, header_size);
1808 memcpy (buffer, msheader, sizeof (MonoMSDOSHeader));
1810 msdos = (MonoMSDOSHeader *)buffer;
1811 header = (MonoDotNetHeader *)(buffer + sizeof (MonoMSDOSHeader));
1812 section = (MonoSectionTable*) (buffer + sizeof (MonoMSDOSHeader) + sizeof (MonoDotNetHeader));
1814 /* FIXME: ENDIAN problem: byteswap as needed */
1815 msdos->pe_offset = sizeof (MonoMSDOSHeader);
1817 header->pesig [0] = 'P';
1818 header->pesig [1] = 'E';
1819 header->pesig [2] = header->pesig [3] = 0;
1821 header->coff.coff_machine = 0x14c;
1822 header->coff.coff_sections = 1; /* only .text supported now */
1823 header->coff.coff_time = time (NULL);
1824 header->coff.coff_opt_header_size = sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4;
1826 header->coff.coff_attributes = 0x010e;
1828 //header->coff.coff_attributes = 0x210e;
1829 header->pe.pe_magic = 0x10B;
1830 header->pe.pe_major = 6;
1831 header->pe.pe_minor = 0;
1832 /* need to set: pe_code_size pe_data_size pe_rva_entry_point pe_rva_code_base pe_rva_data_base */
1834 header->nt.pe_image_base = 0x400000;
1835 header->nt.pe_section_align = 8192;
1836 header->nt.pe_file_alignment = FILE_ALIGN;
1837 header->nt.pe_os_major = 4;
1838 header->nt.pe_os_minor = 0;
1839 header->nt.pe_subsys_major = 4;
1840 /* need to set pe_image_size, pe_header_size */
1841 header->nt.pe_header_size = 0x200;
1842 header->nt.pe_image_size = 0x00008000;
1843 header->nt.pe_subsys_required = 3; /* 3 -> cmdline app, 2 -> GUI app */
1844 header->nt.pe_stack_reserve = 0x00100000;
1845 header->nt.pe_stack_commit = 0x00001000;
1846 header->nt.pe_heap_reserve = 0x00100000;
1847 header->nt.pe_heap_commit = 0x00001000;
1848 header->nt.pe_loader_flags = 0;
1849 header->nt.pe_data_dir_count = 16;
1853 header->datadir.pe_import_table
1858 header->datadir.pe_cli_header.size = 72;
1859 header->datadir.pe_cli_header.rva = assembly->text_rva; /* we put it always at the beginning */
1861 /* Write section tables */
1862 strcpy (section->st_name, ".text");
1863 section->st_virtual_address = START_TEXT_RVA;
1864 section->st_virtual_size = assembly->meta_size + assembly->code.index;
1865 section->st_raw_data_size = section->st_virtual_size + (FILE_ALIGN - 1);
1866 section->st_raw_data_size &= ~(FILE_ALIGN - 1);
1867 section->st_raw_data_ptr = TEXT_OFFSET;
1868 section->st_flags = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
1871 * align: build_compressed_metadata () assumes metadata is aligned
1873 * cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1875 assembly->code.index += 3;
1876 assembly->code.index &= ~3;
1879 * Write the MonoCLIHeader header
1881 cli_header = (MonoCLIHeader*)(buffer + TEXT_OFFSET);
1882 cli_header->ch_size = 72;
1883 cli_header->ch_runtime_major = 2;
1884 cli_header->ch_flags = CLI_FLAGS_ILONLY;
1885 if (assemblyb->entry_point)
1886 cli_header->ch_entry_point = assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF;
1888 cli_header->ch_entry_point = 0;
1889 cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1890 cli_header->ch_metadata.size = assembly->meta_size;
1896 * We need to return always the same object for MethodInfo, FieldInfo etc..
1897 * type uses a different hash, since it uses custom hash/equal functions.
1899 static MonoGHashTable *object_cache = NULL;
1900 static MonoGHashTable *type_cache = NULL;
1902 #define CHECK_OBJECT(t,p) \
1905 if (!object_cache) \
1906 object_cache = mono_g_hash_table_new (g_direct_hash, g_direct_equal); \
1907 if ((_obj = mono_g_hash_table_lookup (object_cache, (p)))) \
1911 #define CACHE_OBJECT(p,o) \
1913 mono_g_hash_table_insert (object_cache, p,o); \
1916 MonoReflectionAssembly*
1917 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
1919 static MonoClass *System_Reflection_Assembly;
1920 MonoReflectionAssembly *res;
1922 CHECK_OBJECT (MonoReflectionAssembly *, assembly);
1923 if (!System_Reflection_Assembly)
1924 System_Reflection_Assembly = mono_class_from_name (
1925 mono_defaults.corlib, "System.Reflection", "Assembly");
1926 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
1927 res->assembly = assembly;
1928 CACHE_OBJECT (assembly, res);
1933 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
1935 if ((t1->type != t2->type) ||
1936 (t1->byref != t2->byref))
1940 case MONO_TYPE_VOID:
1941 case MONO_TYPE_BOOLEAN:
1942 case MONO_TYPE_CHAR:
1953 case MONO_TYPE_STRING:
1956 case MONO_TYPE_OBJECT:
1958 case MONO_TYPE_VALUETYPE:
1959 case MONO_TYPE_CLASS:
1960 return t1->data.klass == t2->data.klass;
1962 case MONO_TYPE_SZARRAY:
1963 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
1964 case MONO_TYPE_ARRAY:
1965 if (t1->data.array->rank != t2->data.array->rank)
1967 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
1969 g_error ("implement type compare for %0x!", t1->type);
1977 mymono_metadata_type_hash (MonoType *t1)
1983 hash |= t1->byref << 6; /* do not collide with t1->type values */
1985 case MONO_TYPE_VALUETYPE:
1986 case MONO_TYPE_CLASS:
1987 /* check if the distribution is good enough */
1988 return hash << 7 | g_str_hash (t1->data.klass->name);
1990 case MONO_TYPE_SZARRAY:
1991 return hash << 7 | mymono_metadata_type_hash (t1->data.type);
1997 mono_type_get_object (MonoDomain *domain, MonoType *type)
1999 MonoReflectionType *res;
2000 MonoClass *klass = mono_class_from_mono_type (type);
2003 type_cache = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
2004 (GCompareFunc)mymono_metadata_type_equal);
2005 if ((res = mono_g_hash_table_lookup (type_cache, type)))
2007 if (klass->reflection_info) {
2008 /* should this be considered an error condition? */
2010 return klass->reflection_info;
2012 mono_class_init (klass);
2013 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
2015 mono_g_hash_table_insert (type_cache, type, res);
2019 MonoReflectionMethod*
2020 mono_method_get_object (MonoDomain *domain, MonoMethod *method)
2023 * We use the same C representation for methods and constructors, but the type
2024 * name in C# is different.
2028 MonoReflectionMethod *ret;
2030 CHECK_OBJECT (MonoReflectionMethod *, method);
2031 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
2032 cname = "MonoCMethod";
2034 cname = "MonoMethod";
2035 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
2037 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
2038 ret->method = method;
2039 CACHE_OBJECT (method, ret);
2043 MonoReflectionField*
2044 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
2046 MonoReflectionField *res;
2049 CHECK_OBJECT (MonoReflectionField *, field);
2050 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
2051 res = (MonoReflectionField *)mono_object_new (domain, oklass);
2054 CACHE_OBJECT (field, res);
2058 MonoReflectionProperty*
2059 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
2061 MonoReflectionProperty *res;
2064 CHECK_OBJECT (MonoReflectionProperty *, property);
2065 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
2066 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
2068 res->property = property;
2069 CACHE_OBJECT (property, res);
2073 MonoReflectionEvent*
2074 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
2076 MonoReflectionEvent *res;
2079 CHECK_OBJECT (MonoReflectionEvent *, event);
2080 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
2081 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
2084 CACHE_OBJECT (event, res);
2088 MonoReflectionParameter**
2089 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
2091 MonoReflectionParameter **res;
2092 MonoReflectionMethod *member;
2097 if (!method->signature->param_count)
2100 member = mono_method_get_object (domain, method);
2101 names = g_new (char *, method->signature->param_count);
2102 mono_method_get_param_names (method, (const char **) names);
2104 /* Note: the cache is based on the address of the signature into the method
2105 * since we already cache MethodInfos with the method as keys.
2107 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature));
2108 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
2109 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
2110 for (i = 0; i < method->signature->param_count; ++i) {
2111 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
2112 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
2113 res [i]->DefaultValueImpl = NULL; /* FIXME */
2114 res [i]->MemberImpl = (MonoObject*)member;
2115 res [i]->NameImpl = mono_string_new (domain, names [i]);
2116 res [i]->PositionImpl = i + 1;
2117 res [i]->AttrsImpl = method->signature->params [i]->attrs;
2120 CACHE_OBJECT (&(method->signature), res);
2125 * Parse a type name as accepted by the GetType () method and output the info
2126 * extracted in the info structure.
2127 * the name param will be mangled, so, make a copy before passing it to this function.
2128 * The fields in info will be valid until the memory pointed to by name is valid.
2129 * Returns 0 on parse error.
2132 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
2134 char *start, *p, *w, *last_point;
2135 int in_modifiers = 0;
2136 int isbyref = 0, rank;
2138 start = p = w = name;
2140 info->name = info->name_space = info->assembly = NULL;
2141 info->nest_name = info->nest_name_space = NULL;
2142 info->modifiers = NULL;
2149 /* we have parsed the nesting namespace + name */
2151 info->nest_name_space = start;
2153 info->nest_name = last_point + 1;
2155 info->nest_name_space = "";
2156 info->nest_name = start;
2158 *p = 0; /* NULL terminate */
2183 info->name_space = start;
2185 info->name = last_point + 1;
2187 info->name_space = "";
2193 if (isbyref) /* only one level allowed by the spec */
2196 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
2200 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
2211 else if (*p != '*') /* '*' means unknown lower bound */
2217 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
2229 return 0; /* missing assembly name */
2236 *w = 0; /* terminate class name */
2237 if (!info->name || !*info->name)
2239 if (info->nest_name && !*info->nest_name)
2241 /* add other consistency checks */
2246 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
2253 g_warning ("Ignore case not yet supported in GetType()");
2258 image = mono_defaults.corlib;
2260 if (info->nest_name) {
2261 klass = mono_class_from_name (image, info->nest_name_space, info->nest_name);
2264 mono_class_init (klass);
2265 nested = klass->nested_classes;
2268 klass = nested->data;
2269 if (strcmp (klass->name, info->nest_name) == 0 &&
2270 strcmp (klass->name_space, info->nest_name_space) == 0)
2273 nested = nested->next;
2277 klass = mono_class_from_name (image, info->name_space, info->name);
2281 mono_class_init (klass);
2282 for (mod = info->modifiers; mod; mod = mod->next) {
2283 modval = GPOINTER_TO_UINT (mod->data);
2284 if (!modval) { /* byref: must be last modifier */
2285 return &klass->this_arg;
2286 } else if (modval == -1) {
2287 klass = mono_ptr_class_get (&klass->byval_arg);
2288 } else { /* array rank */
2289 klass = mono_array_class_get (&klass->byval_arg, modval);
2291 mono_class_init (klass);
2293 return &klass->byval_arg;
2297 dummy_runtime_invoke (MonoMethod *method, void *obj, void **params)
2299 g_error ("runtime invoke called on uninitialized runtime");
2303 MonoInvokeFunc mono_default_runtime_invoke = dummy_runtime_invoke;
2306 mono_install_runtime_invoke (MonoInvokeFunc func) {
2308 mono_default_runtime_invoke = func;
2310 mono_default_runtime_invoke = dummy_runtime_invoke;
2314 mono_runtime_invoke (MonoMethod *method, void *obj, void **params)
2316 return mono_default_runtime_invoke (method, obj, params);;
2320 * Optimization we could avoid mallocing() an little-endian archs that
2321 * don't crash with unaligned accesses.
2324 fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
2325 int len, i, slen, type;
2326 const char *p = mono_metadata_blob_heap (image, blobidx);
2328 len = mono_metadata_decode_value (p, &p);
2329 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
2334 for (i = 0; i < sig->param_count; ++i) {
2335 type = sig->params [i]->type;
2340 case MONO_TYPE_BOOLEAN: {
2341 MonoBoolean *bval = params [i] = g_malloc (sizeof (MonoBoolean));
2346 case MONO_TYPE_CHAR:
2348 case MONO_TYPE_I2: {
2349 guint16 *val = params [i] = g_malloc (sizeof (guint16));
2354 #if SIZEOF_VOID_P == 4
2360 case MONO_TYPE_I4: {
2361 guint32 *val = params [i] = g_malloc (sizeof (guint32));
2366 #if SIZEOF_VOID_P == 8
2367 case MONO_TYPE_U: /* error out instead? this should probably not happen */
2372 case MONO_TYPE_I8: {
2373 guint64 *val = params [i] = g_malloc (sizeof (guint64));
2378 case MONO_TYPE_VALUETYPE:
2379 if (sig->params [i]->data.klass->enumtype) {
2380 type = sig->params [i]->data.klass->enum_basetype->type;
2383 g_warning ("generic valutype %s not handled in custom attr value decoding", sig->params [i]->data.klass->name);
2386 case MONO_TYPE_STRING: {
2387 slen = mono_metadata_decode_value (p, &p);
2388 params [i] = mono_string_new_len (mono_domain_get (), p, slen);
2393 g_warning ("Type %02x not handled in custom attr value decoding", sig->params [i]->type);
2400 free_param_data (MonoMethodSignature *sig, void **params) {
2402 for (i = 0; i < sig->param_count; ++i) {
2403 switch (sig->params [i]->type) {
2404 case MONO_TYPE_BOOLEAN:
2405 case MONO_TYPE_CHAR:
2418 case MONO_TYPE_VALUETYPE:
2419 g_free (params [i]);
2428 * Find the method index in the metadata methodDef table.
2429 * Later put these three helper methods in metadata and export them.
2432 find_method_index (MonoMethod *method) {
2433 MonoClass *klass = method->klass;
2436 for (i = 0; i < klass->method.count; ++i) {
2437 if (method == klass->methods [i])
2438 return klass->method.first + 1 + i;
2444 * Find the field index in the metadata FieldDef table.
2447 find_field_index (MonoClass *klass, MonoClassField *field) {
2450 for (i = 0; i < klass->field.count; ++i) {
2451 if (field == &klass->fields [i])
2452 return klass->field.first + 1 + i;
2458 * Find the property index in the metadata Property table.
2461 find_property_index (MonoClass *klass, MonoProperty *property) {
2464 for (i = 0; i < klass->property.count; ++i) {
2465 if (property == &klass->properties [i])
2466 return klass->property.first + 1 + i;
2472 * Find the event index in the metadata Event table.
2475 find_event_index (MonoClass *klass, MonoEvent *event) {
2478 for (i = 0; i < klass->event.count; ++i) {
2479 if (event == &klass->events [i])
2480 return klass->event.first + 1 + i;
2486 mono_reflection_get_custom_attrs (MonoObject *obj)
2488 guint32 index, mtoken, i;
2489 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
2499 klass = obj->vtable->klass;
2500 /* FIXME: need to handle: Module */
2501 if (klass == mono_defaults.monotype_class) {
2502 MonoReflectionType *rtype = (MonoReflectionType*)obj;
2503 klass = mono_class_from_mono_type (rtype->type);
2504 index = mono_metadata_token_index (klass->type_token);
2505 index <<= CUSTOM_ATTR_BITS;
2506 index |= CUSTOM_ATTR_TYPEDEF;
2507 image = klass->image;
2508 } else if (strcmp ("Assembly", klass->name) == 0) {
2509 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
2510 index = 1; /* there is only one assembly */
2511 index <<= CUSTOM_ATTR_BITS;
2512 index |= CUSTOM_ATTR_ASSEMBLY;
2513 image = rassembly->assembly->image;
2514 } else if (strcmp ("MonoProperty", klass->name) == 0) {
2515 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
2516 index = find_property_index (rprop->klass, rprop->property);
2517 index <<= CUSTOM_ATTR_BITS;
2518 index |= CUSTOM_ATTR_PROPERTY;
2519 image = rprop->klass->image;
2520 } else if (strcmp ("MonoEvent", klass->name) == 0) {
2521 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
2522 index = find_event_index (revent->klass, revent->event);
2523 index <<= CUSTOM_ATTR_BITS;
2524 index |= CUSTOM_ATTR_EVENT;
2525 image = revent->klass->image;
2526 } else if (strcmp ("MonoField", klass->name) == 0) {
2527 MonoReflectionField *rfield = (MonoReflectionField*)obj;
2528 index = find_field_index (rfield->klass, rfield->field);
2529 index <<= CUSTOM_ATTR_BITS;
2530 index |= CUSTOM_ATTR_FIELDDEF;
2531 image = rfield->klass->image;
2532 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
2533 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
2534 index = find_method_index (rmethod->method);
2535 index <<= CUSTOM_ATTR_BITS;
2536 index |= CUSTOM_ATTR_METHODDEF;
2537 image = method->klass->image;
2538 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
2539 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
2540 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
2541 guint32 method_index = find_method_index (rmethod->method);
2542 guint32 param_list, param_last, param_pos, found;
2544 image = rmethod->method->klass->image;
2545 ca = &image->tables [MONO_TABLE_METHOD];
2547 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
2548 if (method_index == ca->rows) {
2549 ca = &image->tables [MONO_TABLE_PARAM];
2550 param_last = ca->rows + 1;
2552 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
2553 ca = &image->tables [MONO_TABLE_PARAM];
2556 for (i = param_list; i < param_last; ++i) {
2557 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
2558 if (param_pos == param->PositionImpl) {
2564 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
2566 index <<= CUSTOM_ATTR_BITS;
2567 index |= CUSTOM_ATTR_PARAMDEF;
2568 } else { /* handle other types here... */
2569 g_error ("get custom attrs not yet supported for %s", klass->name);
2572 /* at this point image and index are set correctly for searching the custom attr */
2573 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2574 /* the table is not sorted */
2575 for (i = 0; i < ca->rows; ++i) {
2576 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
2577 if (cols [MONO_CUSTOM_ATTR_PARENT] != index)
2579 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
2580 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
2581 case CUSTOM_ATTR_TYPE_METHODDEF:
2582 mtoken |= MONO_TOKEN_METHOD_DEF;
2584 case CUSTOM_ATTR_TYPE_MEMBERREF:
2585 mtoken |= MONO_TOKEN_MEMBER_REF;
2588 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
2591 method = mono_get_method (image, mtoken, NULL);
2593 g_error ("Can't find custom attr constructor");
2594 mono_class_init (method->klass);
2595 /*g_print ("got attr %s\n", method->klass->name);*/
2596 params = g_new (void*, method->signature->param_count);
2597 fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
2598 attr = mono_object_new (mono_domain_get (), method->klass);
2599 mono_runtime_invoke (method, attr, params);
2600 list = g_list_prepend (list, attr);
2601 free_param_data (method->signature, params);
2605 index = g_list_length (list);
2607 * The return type is really object[], but System/Attribute.cs does a cast
2608 * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
2609 * probably fix that.
2611 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
2612 result = mono_array_new (mono_domain_get (), klass, index);
2613 for (i = 0; i < index; ++i) {
2614 mono_array_set (result, gpointer, i, list->data);
2617 g_list_free (g_list_first (list));
2623 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *porpValues, MonoArray *fields, MonoArray* fieldValues) {
2625 MonoMethodSignature *sig;
2627 char *buffer, *p, *argval;
2628 guint32 buflen, i, type;
2630 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
2631 g_warning ("ConstructorBuilder Custom attribute not yet supported");
2633 * maybe we should have a param array to method signature function and
2634 * continue with the normal codepath.
2636 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, 4);
2637 mono_array_set (result, char, 0, 1);
2641 p = buffer = g_malloc (buflen);
2642 /* write the prolog */
2645 sig = ((MonoReflectionMethod*)ctor)->method->signature;
2646 /* FIXME: ENOENDIAN */
2647 for (i = 0; i < sig->param_count; ++i) {
2648 if ((p-buffer) + 10 >= buflen) {
2651 newbuf = g_realloc (buffer, buflen);
2652 p = newbuf + (p-buffer);
2655 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
2656 argval = ((char*)arg + sizeof (MonoObject));
2657 type = sig->params [i]->type;
2660 case MONO_TYPE_BOOLEAN:
2665 case MONO_TYPE_CHAR:
2667 case MONO_TYPE_I2: {
2668 guint16 *val = (guint16*)p;
2669 *val = *(guint16*)argval;
2675 case MONO_TYPE_R4: {
2676 guint32 *val = (guint32*)p;
2677 *val = *(guint32*)argval;
2683 case MONO_TYPE_R8: {
2684 guint64 *val = (guint64*)p;
2685 *val = *(guint64*)argval;
2689 case MONO_TYPE_VALUETYPE:
2690 if (sig->params [i]->data.klass->enumtype) {
2691 type = sig->params [i]->data.klass->enum_basetype->type;
2694 g_warning ("generic valutype %s not handled in custom attr value decoding", sig->params [i]->data.klass->name);
2697 case MONO_TYPE_STRING: {
2698 char *str = mono_string_to_utf8 ((MonoString*)arg);
2699 guint32 slen = strlen (str);
2700 if ((p-buffer) + 10 + slen >= buflen) {
2704 newbuf = g_realloc (buffer, buflen);
2705 p = newbuf + (p-buffer);
2708 mono_metadata_encode_value (slen, p, &p);
2709 memcpy (p, str, slen);
2715 g_error ("type 0x%02x not yet supported in custom attr encoder", type);
2719 * we don't support properties and fields, yet, set to 0.
2723 buflen = p - buffer;
2724 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
2725 p = mono_array_addr (result, char, 0);
2726 memcpy (p, buffer, buflen);
2732 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
2734 MonoClass *klass, *parent;
2736 klass = g_new0 (MonoClass, 1);
2738 klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
2741 parent = mono_class_from_mono_type (tb->parent->type);
2743 klass->inited = 1; /* we lie to the runtime */
2744 klass->name = mono_string_to_utf8 (tb->name);
2745 klass->name_space = mono_string_to_utf8 (tb->nspace);
2746 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
2747 klass->flags = tb->attrs;
2749 klass->element_class = klass;
2750 klass->reflection_info = tb; /* need to pin. */
2752 mono_class_setup_parent (klass, parent);
2753 mono_class_setup_mono_type (klass);
2756 * FIXME: handle interfaces.
2759 tb->type.type = &klass->byval_arg;
2761 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
2765 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
2767 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
2768 guint32 na = mono_array_length (sig->arguments);
2773 p = buf = g_malloc (10 + na * 10);
2775 mono_metadata_encode_value (0x07, p, &p);
2776 mono_metadata_encode_value (na, p, &p);
2777 for (i = 0; i < na; ++i) {
2778 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
2779 encode_reflection_type (assembly, type, p, &p);
2783 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
2784 p = mono_array_addr (result, char, 0);
2785 memcpy (p, buf, buflen);
2792 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
2794 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
2795 guint32 na = mono_array_length (sig->arguments);
2800 p = buf = g_malloc (10 + na * 10);
2802 mono_metadata_encode_value (0x06, p, &p);
2803 for (i = 0; i < na; ++i) {
2804 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
2805 encode_reflection_type (assembly, type, p, &p);
2809 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
2810 p = mono_array_addr (result, char, 0);
2811 memcpy (p, buf, buflen);