3 * reflection.c: Routines for creating an image at runtime.
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/tokentype.h"
15 #include "mono/metadata/appdomain.h"
16 #include "mono/metadata/opcodes.h"
24 #include "rawbuffer.h"
25 #include "mono-endian.h"
31 #define TEXT_OFFSET 512
32 #define CLI_H_SIZE 136
33 #define FILE_ALIGN 512
34 #define VIRT_ALIGN 8192
35 #define START_TEXT_RVA 0x00002000
38 MonoReflectionILGen *ilgen;
39 MonoReflectionType *rtype;
40 MonoArray *parameters;
45 guint32 *table_idx; /* note: it's a pointer */
49 MonoBoolean init_locals;
50 } ReflectionMethodBuilder;
52 const unsigned char table_sizes [64] = {
62 MONO_INTERFACEIMPL_SIZE,
63 MONO_MEMBERREF_SIZE, /* 0x0A */
65 MONO_CUSTOM_ATTR_SIZE,
66 MONO_FIELD_MARSHAL_SIZE,
67 MONO_DECL_SECURITY_SIZE,
68 MONO_CLASS_LAYOUT_SIZE,
69 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
70 MONO_STAND_ALONE_SIGNATURE_SIZE,
74 MONO_PROPERTY_MAP_SIZE,
77 MONO_METHOD_SEMA_SIZE,
79 MONO_MODULEREF_SIZE, /* 0x1A */
85 MONO_ASSEMBLY_SIZE, /* 0x20 */
86 MONO_ASSEMBLY_PROCESSOR_SIZE,
88 MONO_ASSEMBLYREF_SIZE,
89 MONO_ASSEMBLYREFPROC_SIZE,
90 MONO_ASSEMBLYREFOS_SIZE,
94 MONO_NESTED_CLASS_SIZE,
98 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
99 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
100 static guint32 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo);
103 alloc_table (MonoDynamicTable *table, guint nrows)
106 g_assert (table->columns);
107 table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
111 string_heap_insert (MonoDynamicStream *sh, const char *str)
115 gpointer oldkey, oldval;
117 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
118 return GPOINTER_TO_UINT (oldval);
120 len = strlen (str) + 1;
122 if (idx + len > sh->alloc_size) {
123 sh->alloc_size += len + 4096;
124 sh->data = g_realloc (sh->data, sh->alloc_size);
127 * We strdup the string even if we already copy them in sh->data
128 * so that the string pointers in the hash remain valid even if
129 * we need to realloc sh->data. We may want to avoid that later.
131 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
132 memcpy (sh->data + idx, str, len);
138 string_heap_init (MonoDynamicStream *sh)
141 sh->alloc_size = 4096;
142 sh->data = g_malloc (4096);
143 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
144 string_heap_insert (sh, "");
147 #if 0 /* never used */
149 string_heap_free (MonoDynamicStream *sh)
152 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
153 g_hash_table_destroy (sh->hash);
158 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
161 if (stream->alloc_size < stream->index + len) {
162 stream->alloc_size += len + 4096;
163 stream->data = g_realloc (stream->data, stream->alloc_size);
165 memcpy (stream->data + stream->index, data, len);
167 stream->index += len;
169 * align index? Not without adding an additional param that controls it since
170 * we may store a blob value in pieces.
176 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
179 if (stream->alloc_size < stream->index + len) {
180 stream->alloc_size += len + 4096;
181 stream->data = g_realloc (stream->data, stream->alloc_size);
183 memset (stream->data + stream->index, 0, len);
185 stream->index += len;
190 stream_data_align (MonoDynamicStream *stream)
193 guint32 count = stream->index % 4;
195 /* we assume the stream data will be aligned */
197 mono_image_add_stream_data (stream, buf, 4 - count);
201 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
204 g_assert_not_reached ();
209 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
213 case MONO_TYPE_BOOLEAN:
227 case MONO_TYPE_STRING:
228 case MONO_TYPE_OBJECT:
229 case MONO_TYPE_TYPEDBYREF:
230 mono_metadata_encode_value (type->type, p, &p);
233 case MONO_TYPE_SZARRAY:
234 mono_metadata_encode_value (type->type, p, &p);
235 encode_type (assembly, type->data.type, p, &p);
237 case MONO_TYPE_VALUETYPE:
238 case MONO_TYPE_CLASS:
239 mono_metadata_encode_value (type->type, p, &p);
240 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
243 case MONO_TYPE_VALUETYPE:
244 case MONO_TYPE_CLASS: {
245 MonoClass *k = mono_class_from_mono_type (type);
246 mono_metadata_encode_value (type->type, p, &p);
247 /* ensure only non-byref gets passed to mono_image_typedef_or_ref() */
248 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
252 case MONO_TYPE_ARRAY:
253 mono_metadata_encode_value (type->type, p, &p);
254 encode_type (assembly, type->data.array->type, p, &p);
255 mono_metadata_encode_value (type->data.array->rank, p, &p);
256 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
257 mono_metadata_encode_value (0, p, &p);
260 g_error ("need to encode type %x", type->type);
266 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
269 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
273 encode_type (assembly, type->type, p, endbuf);
277 g_assert_not_reached ();
282 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
287 guint32 nparams = sig->param_count;
288 guint32 size = 10 + nparams * 10;
293 p = buf = g_malloc (size);
295 * FIXME: vararg, explicit_this, differenc call_conv values...
297 *p = sig->call_convention;
299 *p |= 0x20; /* hasthis */
301 mono_metadata_encode_value (nparams, p, &p);
302 encode_type (assembly, sig->ret, p, &p);
303 for (i = 0; i < nparams; ++i)
304 encode_type (assembly, sig->params [i], p, &p);
306 g_assert (p - buf < size);
307 mono_metadata_encode_value (p-buf, b, &b);
308 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
309 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
315 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
318 * FIXME: reuse code from method_encode_signature().
323 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
324 guint32 size = 10 + nparams * 10;
329 p = buf = g_malloc (size);
330 /* LAMESPEC: all the call conv spec is foobared */
331 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
332 if (mb->call_conv & 2)
333 *p |= 0x5; /* vararg */
334 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
335 *p |= 0x20; /* hasthis */
337 mono_metadata_encode_value (nparams, p, &p);
338 encode_reflection_type (assembly, mb->rtype, p, &p);
339 for (i = 0; i < nparams; ++i) {
340 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
341 encode_reflection_type (assembly, pt, p, &p);
344 g_assert (p - buf < size);
345 mono_metadata_encode_value (p-buf, b, &b);
346 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
347 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
353 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
355 MonoDynamicTable *table;
358 guint32 idx, sig_idx, size;
359 guint nl = mono_array_length (ilgen->locals);
366 p = buf = g_malloc (size);
367 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
368 idx = table->next_idx ++;
370 alloc_table (table, table->rows);
371 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
373 mono_metadata_encode_value (0x07, p, &p);
374 mono_metadata_encode_value (nl, p, &p);
375 for (i = 0; i < nl; ++i) {
376 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
377 encode_reflection_type (assembly, lb->type, p, &p);
379 g_assert (p - buf < size);
380 mono_metadata_encode_value (p-buf, b, &b);
381 sig_idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
382 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
385 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
391 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
397 gint32 num_locals = 0;
398 gint32 num_exception = 0;
401 char fat_header [12];
404 guint32 local_sig = 0;
405 guint32 header_size = 12;
408 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
409 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
410 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
411 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
415 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
417 code = mb->ilgen->code;
418 code_size = mb->ilgen->code_len;
419 max_stack = mb->ilgen->max_stack;
420 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
421 if (mb->ilgen->ex_handlers) {
422 MonoILExceptionInfo *ex_info;
423 for (i = 0; i < mono_array_length (mb->ilgen->ex_handlers); ++i) {
424 ex_info = (MonoILExceptionInfo*)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
425 if (ex_info->handlers)
426 num_exception += mono_array_length (ex_info->handlers);
433 code_size = mono_array_length (code);
434 max_stack = 8; /* we probably need to run a verifier on the code... */
437 /* check for exceptions, maxstack, locals */
438 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
440 if (code_size < 64 && !(code_size & 1)) {
441 flags = (code_size << 2) | 0x2;
442 } else if (code_size < 32 && (code_size & 1)) {
443 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
447 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
448 /* add to the fixup todo list */
449 if (mb->ilgen && mb->ilgen->num_token_fixups)
450 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
451 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
452 return assembly->text_rva + idx;
456 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
458 * FIXME: need to set also the header size in fat_flags.
459 * (and more sects and init locals flags)
463 fat_flags |= METHOD_HEADER_MORE_SECTS;
465 fat_flags |= METHOD_HEADER_INIT_LOCALS;
466 fat_header [0] = fat_flags;
467 fat_header [1] = (header_size / 4 ) << 4;
468 shortp = (guint16*)(fat_header + 2);
469 *shortp = GUINT16_TO_LE (max_stack);
470 intp = (guint32*)(fat_header + 4);
471 *intp = GUINT32_TO_LE (code_size);
472 intp = (guint32*)(fat_header + 8);
473 *intp = GUINT32_TO_LE (local_sig);
474 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
475 /* add to the fixup todo list */
476 if (mb->ilgen && mb->ilgen->num_token_fixups)
477 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
479 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
481 unsigned char sheader [4];
482 MonoExceptionClause clause;
483 MonoILExceptionInfo * ex_info;
484 MonoILExceptionBlock * ex_block;
487 stream_data_align (&assembly->code);
488 /* always use fat format for now */
489 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
490 num_exception *= sizeof (MonoExceptionClause);
491 sheader [1] = num_exception & 0xff;
492 sheader [2] = (num_exception >> 8) & 0xff;
493 sheader [3] = (num_exception >> 16) & 0xff;
494 mono_image_add_stream_data (&assembly->code, sheader, 4);
495 /* fat header, so we are already aligned */
497 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
498 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
499 if (ex_info->handlers) {
500 int finally_start = ex_info->start + ex_info->len;
501 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
502 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
503 clause.flags = GUINT32_TO_LE (ex_block->type);
504 clause.try_offset = GUINT32_TO_LE (ex_info->start);
505 /* need fault, too, probably */
506 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
507 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
509 clause.try_len = GUINT32_TO_LE (ex_info->len);
510 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
511 clause.handler_len = GUINT32_TO_LE (ex_block->len);
512 finally_start = clause.handler_offset + clause.handler_len;
513 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
514 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
515 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
516 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
517 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
518 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
521 g_error ("No clauses for ex info block %d", i);
525 return assembly->text_rva + idx;
529 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 token)
532 MonoDynamicTable *table;
535 table = &assembly->tables [table_idx];
537 g_assert (col < table->columns);
539 values = table->values + table->columns;
540 for (i = 1; i <= table->rows; ++i) {
541 if (values [col] == token)
548 * idx is the table index of the object
549 * type is one of CUSTOM_ATTR_*
552 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
554 MonoDynamicTable *table;
555 MonoReflectionCustomAttr *cattr;
557 guint32 count, i, token;
561 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
564 count = mono_array_length (cattrs);
565 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
566 table->rows += count;
567 alloc_table (table, table->rows);
568 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
569 idx <<= CUSTOM_ATTR_BITS;
571 for (i = 0; i < count; ++i) {
572 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
573 values [MONO_CUSTOM_ATTR_PARENT] = idx;
574 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
575 type = mono_metadata_token_index (token);
576 type <<= CUSTOM_ATTR_TYPE_BITS;
577 switch (mono_metadata_token_table (token)) {
578 case MONO_TABLE_METHOD:
579 type |= CUSTOM_ATTR_TYPE_METHODDEF;
581 case MONO_TABLE_MEMBERREF:
582 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
585 g_error ("got wrong token in custom attr");
587 values [MONO_CUSTOM_ATTR_TYPE] = type;
589 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
590 values [MONO_CUSTOM_ATTR_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, p - blob_size);
591 mono_image_add_stream_data (&assembly->blob,
592 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
593 values += MONO_CUSTOM_ATTR_SIZE;
599 * Fill in the MethodDef and ParamDef tables for a method.
600 * This is used for both normal methods and constructors.
603 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
605 MonoDynamicTable *table;
610 /* room in this table is already allocated */
611 table = &assembly->tables [MONO_TABLE_METHOD];
612 *mb->table_idx = table->next_idx ++;
613 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
615 name = mono_string_to_utf8 (mb->name);
616 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
618 } else { /* a constructor */
619 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
621 values [MONO_METHOD_FLAGS] = mb->attrs;
622 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
623 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
624 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
626 table = &assembly->tables [MONO_TABLE_PARAM];
627 values [MONO_METHOD_PARAMLIST] = table->next_idx;
630 MonoDynamicTable *mtable;
633 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
634 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
637 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
638 if (mono_array_get (mb->pinfo, gpointer, i))
641 table->rows += count;
642 alloc_table (table, table->rows);
643 values = table->values + table->next_idx * MONO_PARAM_SIZE;
644 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
645 MonoReflectionParamBuilder *pb;
646 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
647 values [MONO_PARAM_FLAGS] = pb->attrs;
648 values [MONO_PARAM_SEQUENCE] = i;
649 name = mono_string_to_utf8 (pb->name);
650 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
652 values += MONO_PARAM_SIZE;
653 if (pb->marshal_info) {
655 alloc_table (mtable, mtable->rows);
656 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
657 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
658 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
661 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
668 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
670 MonoDynamicTable *table;
673 ReflectionMethodBuilder rmb;
675 rmb.ilgen = mb->ilgen;
676 rmb.rtype = mb->rtype;
677 rmb.parameters = mb->parameters;
678 rmb.pinfo = mb->pinfo;
679 rmb.attrs = mb->attrs;
680 rmb.iattrs = mb->iattrs;
681 rmb.call_conv = mb->call_conv;
685 rmb.table_idx = &mb->table_idx;
686 rmb.init_locals = mb->init_locals;
688 mono_image_basic_method (&rmb, assembly);
690 if (mb->dll) { /* It's a P/Invoke method */
692 table = &assembly->tables [MONO_TABLE_IMPLMAP];
694 alloc_table (table, table->rows);
695 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
696 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
697 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
698 name = mono_string_to_utf8 (mb->dllentry);
699 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
701 name = mono_string_to_utf8 (mb->dll);
702 moduleref = string_heap_insert (&assembly->sheap, name);
704 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
705 table = &assembly->tables [MONO_TABLE_MODULEREF];
707 alloc_table (table, table->rows);
708 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
709 values [MONO_IMPLMAP_SCOPE] = table->rows;
712 if (mb->override_method) {
713 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
714 table = &assembly->tables [MONO_TABLE_METHODIMPL];
716 alloc_table (table, table->rows);
717 values = table->values + table->rows * MONO_MTHODIMPL_SIZE;
718 values [MONO_MTHODIMPL_CLASS] = tb->table_idx;
719 values [MONO_MTHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
720 if (mb->override_method->method)
721 values [MONO_MTHODIMPL_DECLARATION] = mono_image_get_methodref_token (assembly, mb->override_method->method);
723 MonoReflectionMethodBuilder *omb = (MonoReflectionMethodBuilder*)mb->override_method;
724 values [MONO_MTHODIMPL_DECLARATION] = METHODDEFORREF_METHODDEF | (omb->table_idx << METHODDEFORREF_BITS);
727 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
731 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
733 ReflectionMethodBuilder rmb;
735 rmb.ilgen = mb->ilgen;
736 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
737 rmb.parameters = mb->parameters;
738 rmb.pinfo = mb->pinfo;
739 rmb.attrs = mb->attrs;
740 rmb.iattrs = mb->iattrs;
741 rmb.call_conv = mb->call_conv;
745 rmb.table_idx = &mb->table_idx;
746 rmb.init_locals = mb->init_locals;
748 mono_image_basic_method (&rmb, assembly);
749 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
754 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
762 p = buf = g_malloc (64);
764 mono_metadata_encode_value (0x06, p, &p);
765 /* encode custom attributes before the type */
766 encode_type (assembly, field->type, p, &p);
767 g_assert (p-buf < 64);
768 mono_metadata_encode_value (p-buf, b, &b);
769 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
770 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
776 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
784 p = buf = g_malloc (64);
786 mono_metadata_encode_value (0x06, p, &p);
787 /* encode custom attributes before the type */
788 encode_reflection_type (assembly, fb->type, p, &p);
789 g_assert (p-buf < 64);
790 mono_metadata_encode_value (p-buf, b, &b);
791 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
792 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
798 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
799 * dest may be misaligned.
802 swap_with_size (char *dest, const char* val, int len, int nelem) {
803 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
806 for (elem = 0; elem < nelem; ++elem) {
832 g_assert_not_reached ();
838 memcpy (dest, val, len * nelem);
843 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
850 p = buf = g_malloc (64);
852 box_val = ((char*)val) + sizeof (MonoObject);
853 *ret_type = val->vtable->klass->byval_arg.type;
856 case MONO_TYPE_BOOLEAN:
876 case MONO_TYPE_VALUETYPE:
877 if (val->vtable->klass->enumtype) {
878 *ret_type = val->vtable->klass->enum_basetype->type;
881 g_error ("we can't encode valuetypes");
882 case MONO_TYPE_STRING: {
883 MonoString *str = (MonoString*)val;
884 /* there is no signature */
885 len = str->length * 2;
886 mono_metadata_encode_value (len, b, &b);
887 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
888 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
890 char *swapped = g_malloc (2 * mono_string_length (str));
891 const char *p = (const char*)mono_string_chars (str);
893 swap_with_size (swapped, p, 2, mono_string_length (str));
894 mono_image_add_stream_data (&assembly->blob, swapped, len);
898 mono_image_add_stream_data (&assembly->blob, (const char*)mono_string_chars (str), len);
905 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
908 /* there is no signature */
909 mono_metadata_encode_value (len, b, &b);
910 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
911 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
912 swap_with_size (blob_size, val, len, 1);
913 mono_image_add_stream_data (&assembly->blob, blob_size, len);
915 mono_image_add_stream_data (&assembly->blob, box_val, len);
923 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo) {
929 p = buf = g_malloc (256);
931 switch (minfo->type) {
932 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
934 mono_metadata_encode_value (minfo->type, p, &p);
938 mono_metadata_encode_value (len, b, &b);
939 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
940 mono_image_add_stream_data (&assembly->blob, buf, len);
946 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
948 MonoDynamicTable *table;
952 /* maybe this fixup should be done in the C# code */
953 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
954 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
955 table = &assembly->tables [MONO_TABLE_FIELD];
956 fb->table_idx = table->next_idx ++;
957 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
958 name = mono_string_to_utf8 (fb->name);
959 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
961 values [MONO_FIELD_FLAGS] = fb->attrs;
962 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
964 if (fb->offset != -1) {
965 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
967 alloc_table (table, table->rows);
968 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
969 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
970 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
972 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
973 guint32 field_type = 0;
974 table = &assembly->tables [MONO_TABLE_CONSTANT];
976 alloc_table (table, table->rows);
977 values = table->values + table->rows * MONO_CONSTANT_SIZE;
978 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
979 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
980 values [MONO_CONSTANT_TYPE] = field_type;
981 values [MONO_CONSTANT_PADDING] = 0;
985 table = &assembly->tables [MONO_TABLE_FIELDRVA];
987 alloc_table (table, table->rows);
988 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
989 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
991 * We store it in the code section because it's simpler for now.
993 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
994 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
996 if (fb->marshal_info) {
997 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
999 alloc_table (table, table->rows);
1000 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1001 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1002 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1004 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
1008 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
1012 char *b = blob_size;
1013 guint32 nparams = 0;
1014 MonoReflectionMethodBuilder *mb = fb->get_method;
1015 guint32 idx, i, size;
1017 if (mb && mb->parameters)
1018 nparams = mono_array_length (mb->parameters);
1019 size = 24 + nparams * 10;
1020 buf = p = g_malloc (size);
1023 mono_metadata_encode_value (nparams, p, &p);
1025 encode_reflection_type (assembly, mb->rtype, p, &p);
1026 for (i = 0; i < nparams; ++i) {
1027 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1028 encode_reflection_type (assembly, pt, p, &p);
1031 *p++ = 1; /* void: a property should probably not be allowed without a getter */
1034 g_assert (p - buf < size);
1035 mono_metadata_encode_value (p-buf, b, &b);
1036 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1037 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
1043 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
1045 MonoDynamicTable *table;
1048 guint num_methods = 0;
1052 * we need to set things in the following tables:
1053 * PROPERTYMAP (info already filled in _get_type_info ())
1054 * PROPERTY (rows already preallocated in _get_type_info ())
1055 * METHOD (method info already done with the generic method code)
1058 table = &assembly->tables [MONO_TABLE_PROPERTY];
1059 pb->table_idx = table->next_idx ++;
1060 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1061 name = mono_string_to_utf8 (pb->name);
1062 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1064 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1065 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1067 /* FIXME: we still don't handle 'other' methods */
1068 if (pb->get_method) num_methods ++;
1069 if (pb->set_method) num_methods ++;
1071 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1072 table->rows += num_methods;
1073 alloc_table (table, table->rows);
1075 if (pb->get_method) {
1076 semaidx = table->next_idx ++;
1077 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1078 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1079 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1080 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1082 if (pb->set_method) {
1083 semaidx = table->next_idx ++;
1084 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1085 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1086 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1087 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1089 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
1093 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
1095 MonoDynamicTable *table;
1098 guint num_methods = 0;
1102 * we need to set things in the following tables:
1103 * EVENTMAP (info already filled in _get_type_info ())
1104 * EVENT (rows already preallocated in _get_type_info ())
1105 * METHOD (method info already done with the generic method code)
1108 table = &assembly->tables [MONO_TABLE_EVENT];
1109 eb->table_idx = table->next_idx ++;
1110 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1111 name = mono_string_to_utf8 (eb->name);
1112 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1114 values [MONO_EVENT_FLAGS] = eb->attrs;
1115 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1118 * FIXME: we still don't handle 'other' methods
1120 if (eb->add_method) num_methods ++;
1121 if (eb->remove_method) num_methods ++;
1122 if (eb->raise_method) num_methods ++;
1124 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1125 table->rows += num_methods;
1126 alloc_table (table, table->rows);
1128 if (eb->add_method) {
1129 semaidx = table->next_idx ++;
1130 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1131 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1132 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1133 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1135 if (eb->remove_method) {
1136 semaidx = table->next_idx ++;
1137 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1138 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1139 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1140 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1142 if (eb->raise_method) {
1143 semaidx = table->next_idx ++;
1144 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1145 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1146 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1147 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1149 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1153 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
1155 MonoDynamicTable *table;
1158 guint32 cols [MONO_ASSEMBLY_SIZE];
1160 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1163 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1165 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1166 token = table->next_idx ++;
1168 alloc_table (table, table->rows);
1169 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1170 if (strcmp ("corlib", image->assembly_name) == 0)
1171 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1173 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1174 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1175 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1176 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1177 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1178 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1179 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1180 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1181 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1183 token <<= RESOLTION_SCOPE_BITS;
1184 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1185 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1190 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1192 MonoDynamicTable *table;
1198 char *b = blob_size;
1200 switch (type->type) {
1201 case MONO_TYPE_FNPTR:
1203 case MONO_TYPE_SZARRAY:
1204 case MONO_TYPE_ARRAY:
1205 encode_type (assembly, type, p, &p);
1211 g_assert (p-sig < 128);
1212 mono_metadata_encode_value (p-sig, b, &b);
1213 token = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1214 mono_image_add_stream_data (&assembly->blob, sig, p-sig);
1216 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1217 alloc_table (table, table->rows + 1);
1218 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1219 values [MONO_TYPESPEC_SIGNATURE] = token;
1221 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1222 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1228 * Despite the name, we handle also TypeSpec (with the above helper).
1231 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1233 MonoDynamicTable *table;
1235 guint32 token, scope, enclosing;
1238 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1241 token = create_typespec (assembly, type);
1244 klass = mono_class_from_mono_type (type);
1246 * If it's in the same module:
1248 if (klass->image == assembly->assembly.image) {
1249 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1250 return TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1253 if (klass->nested_in) {
1254 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1255 /* get the typeref idx of the enclosing type */
1256 enclosing >>= TYPEDEFORREF_BITS;
1257 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1259 scope = resolution_scope_from_image (assembly, klass->image);
1261 table = &assembly->tables [MONO_TABLE_TYPEREF];
1262 alloc_table (table, table->rows + 1);
1263 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1264 values [MONO_TYPEREF_SCOPE] = scope;
1265 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1266 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1267 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1268 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1274 * Insert a memberef row into the metadata: the token that point to the memberref
1275 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1276 * mono_image_get_fieldref_token()).
1277 * The sig param is an index to an already built signature.
1280 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1282 MonoDynamicTable *table;
1284 guint32 token, pclass;
1287 parent = mono_image_typedef_or_ref (assembly, type);
1288 switch (parent & TYPEDEFORREF_MASK) {
1289 case TYPEDEFORREF_TYPEREF:
1290 pclass = MEMBERREF_PARENT_TYPEREF;
1292 case TYPEDEFORREF_TYPESPEC:
1293 pclass = MEMBERREF_PARENT_TYPESPEC;
1295 case TYPEDEFORREF_TYPEDEF:
1296 /* should never get here */
1298 g_error ("unknow typeref or def token");
1300 /* extract the index */
1301 parent >>= TYPEDEFORREF_BITS;
1303 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1304 alloc_table (table, table->rows + 1);
1305 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1306 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1307 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1308 values [MONO_MEMBERREF_SIGNATURE] = sig;
1309 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1316 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1320 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1323 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1324 method->name, method_encode_signature (assembly, method->signature));
1325 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1330 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1334 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1337 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
1338 field->name, fieldref_encode_signature (assembly, field));
1339 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1344 reflection_cc_to_file (int call_conv) {
1345 switch (call_conv & 0x3) {
1347 case 1: return MONO_CALL_DEFAULT;
1348 case 2: return MONO_CALL_VARARG;
1350 g_assert_not_reached ();
1357 MonoMethodSignature *sig;
1363 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1368 MonoMethodSignature *sig;
1371 name = mono_string_to_utf8 (m->name);
1372 nparams = mono_array_length (m->parameters);
1373 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1375 sig->call_convention = reflection_cc_to_file (m->call_conv);
1376 sig->param_count = nparams;
1377 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1378 for (i = 0; i < nparams; ++i) {
1379 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1380 sig->params [i] = t->type;
1383 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1385 if (strcmp (name, am->name) == 0 &&
1386 mono_metadata_type_equal (am->parent, m->parent->type) &&
1387 mono_metadata_signature_equal (am->sig, sig)) {
1393 am = g_new0 (ArrayMethod, 1);
1396 am->parent = m->parent->type;
1397 am->token = mono_image_get_memberref_token (assembly, am->parent,
1398 name, method_encode_signature (assembly, sig));
1399 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1400 m->table_idx = am->token & 0xffffff;
1405 * Insert into the metadata tables all the info about the TypeBuilder tb.
1406 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1409 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1411 MonoDynamicTable *table;
1416 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1417 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1418 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1419 if (tb->parent) { /* interfaces don't have a parent */
1420 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1422 values [MONO_TYPEDEF_EXTENDS] = 0;
1423 n = mono_string_to_utf8 (tb->name);
1424 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1426 n = mono_string_to_utf8 (tb->nspace);
1427 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1429 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1430 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1433 * if we have explicitlayout or sequentiallayouts, output data in the
1434 * ClassLayout table.
1436 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1437 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1439 alloc_table (table, table->rows);
1440 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1441 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1442 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1443 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1446 /* handle interfaces */
1447 if (tb->interfaces) {
1448 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1450 table->rows += mono_array_length (tb->interfaces);
1451 alloc_table (table, table->rows);
1452 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1453 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1454 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1455 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1456 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1457 values += MONO_INTERFACEIMPL_SIZE;
1463 table = &assembly->tables [MONO_TABLE_FIELD];
1464 table->rows += mono_array_length (tb->fields);
1465 alloc_table (table, table->rows);
1466 for (i = 0; i < mono_array_length (tb->fields); ++i)
1467 mono_image_get_field_info (
1468 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1471 /* handle constructors */
1473 table = &assembly->tables [MONO_TABLE_METHOD];
1474 table->rows += mono_array_length (tb->ctors);
1475 alloc_table (table, table->rows);
1476 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1477 mono_image_get_ctor_info (domain,
1478 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1481 /* handle methods */
1483 table = &assembly->tables [MONO_TABLE_METHOD];
1484 table->rows += mono_array_length (tb->methods);
1485 alloc_table (table, table->rows);
1486 for (i = 0; i < mono_array_length (tb->methods); ++i)
1487 mono_image_get_method_info (
1488 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1491 /* Do the same with properties etc.. */
1492 if (tb->events && mono_array_length (tb->events)) {
1493 table = &assembly->tables [MONO_TABLE_EVENT];
1494 table->rows += mono_array_length (tb->events);
1495 alloc_table (table, table->rows);
1496 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1498 alloc_table (table, table->rows);
1499 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1500 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1501 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1502 for (i = 0; i < mono_array_length (tb->events); ++i)
1503 mono_image_get_event_info (
1504 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1506 if (tb->properties && mono_array_length (tb->properties)) {
1507 table = &assembly->tables [MONO_TABLE_PROPERTY];
1508 table->rows += mono_array_length (tb->properties);
1509 alloc_table (table, table->rows);
1510 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1512 alloc_table (table, table->rows);
1513 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1514 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1515 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1516 for (i = 0; i < mono_array_length (tb->properties); ++i)
1517 mono_image_get_property_info (
1518 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1521 MonoDynamicTable *ntable;
1523 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1524 table->rows += mono_array_length (tb->subtypes);
1525 alloc_table (table, table->rows);
1527 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1528 ntable->rows += mono_array_length (tb->subtypes);
1529 alloc_table (ntable, ntable->rows);
1530 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1532 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1533 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1535 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1536 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1537 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1538 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1539 mono_string_to_utf8 (tb->name), tb->table_idx,
1540 ntable->next_idx, ntable->rows);*/
1541 values += MONO_NESTED_CLASS_SIZE;
1544 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1545 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1547 mono_image_get_type_info (domain, subtype, assembly);
1550 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1554 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1556 MonoDynamicTable *table;
1560 table = &assembly->tables [MONO_TABLE_MODULE];
1561 mb->table_idx = table->next_idx ++;
1562 name = mono_string_to_utf8 (mb->module.name);
1563 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1565 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1568 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1569 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1570 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1572 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1574 * fill-in info in other tables as well.
1576 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1577 table->rows += mono_array_length (mb->types);
1578 alloc_table (table, table->rows);
1580 * We assign here the typedef indexes to avoid mismatches if a type that
1581 * has not yet been stored in the tables is referenced by another type.
1583 for (i = 0; i < mono_array_length (mb->types); ++i) {
1585 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1586 type->table_idx = table->next_idx ++;
1587 if (!type->subtypes)
1589 for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1590 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1591 subtype->table_idx = table->next_idx ++;
1594 for (i = 0; i < mono_array_length (mb->types); ++i)
1595 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1598 #define align_pointer(base,p)\
1600 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1602 (p) += 4 - (__diff & 3);\
1606 compare_semantics (const void *a, const void *b)
1608 const guint32 *a_values = a;
1609 const guint32 *b_values = b;
1610 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
1613 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
1617 compare_custom_attrs (const void *a, const void *b)
1619 const guint32 *a_values = a;
1620 const guint32 *b_values = b;
1622 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
1626 compare_field_marshal (const void *a, const void *b)
1628 const guint32 *a_values = a;
1629 const guint32 *b_values = b;
1631 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
1635 compare_nested (const void *a, const void *b)
1637 const guint32 *a_values = a;
1638 const guint32 *b_values = b;
1640 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
1644 * build_compressed_metadata() fills in the blob of data that represents the
1645 * raw metadata as it will be saved in the PE file. The five streams are output
1646 * and the metadata tables are comnpressed from the guint32 array representation,
1647 * to the compressed on-disk format.
1650 build_compressed_metadata (MonoDynamicAssembly *assembly)
1652 MonoDynamicTable *table;
1654 guint64 valid_mask = 0;
1655 guint64 sorted_mask;
1656 guint32 heapt_size = 0;
1657 guint32 meta_size = 256; /* allow for header and other stuff */
1658 guint32 table_offset;
1659 guint32 ntables = 0;
1666 * We need to use the current ms version or the ms runtime it won't find
1667 * the support dlls. D'oh!
1668 * const char *version = "mono-" VERSION;
1670 const char *version = "v1.0.3705";
1673 MonoDynamicStream *stream;
1674 } stream_desc [] = {
1675 {"#~", &assembly->tstream},
1676 {"#Strings", &assembly->sheap},
1677 {"#US", &assembly->us},
1678 {"#Blob", &assembly->blob},
1679 {"#GUID", &assembly->guid}
1682 /* tables that are sorted */
1683 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
1684 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
1685 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
1686 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
1687 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
1688 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
1690 /* Compute table sizes */
1691 /* the MonoImage has already been created in mono_image_basic_init() */
1692 meta = assembly->assembly.image;
1694 /* Setup the info used by compute_sizes () */
1695 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1696 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1697 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1699 meta_size += assembly->blob.index;
1700 meta_size += assembly->guid.index;
1701 meta_size += assembly->sheap.index;
1702 meta_size += assembly->us.index;
1704 for (i=0; i < 64; ++i)
1705 meta->tables [i].rows = assembly->tables [i].rows;
1707 for (i = 0; i < 64; i++){
1708 if (meta->tables [i].rows == 0)
1710 valid_mask |= (guint64)1 << i;
1712 meta->tables [i].row_size = mono_metadata_compute_size (
1713 meta, i, &meta->tables [i].size_bitfield);
1714 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1716 heapt_size += 24; /* #~ header size */
1717 heapt_size += ntables * 4;
1718 meta_size += heapt_size;
1719 meta->raw_metadata = g_malloc0 (meta_size);
1720 p = meta->raw_metadata;
1721 /* the metadata signature */
1722 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1723 /* version numbers and 4 bytes reserved */
1724 int16val = (guint16*)p;
1725 *int16val++ = GUINT16_TO_LE (1);
1726 *int16val = GUINT16_TO_LE (1);
1728 /* version string */
1729 int32val = (guint32*)p;
1730 *int32val = GUINT32_TO_LE ((strlen (version) + 3) & (~3)); /* needs to be multiple of 4 */
1732 memcpy (p, version, GUINT32_FROM_LE (*int32val));
1733 p += GUINT32_FROM_LE (*int32val);
1734 align_pointer (meta->raw_metadata, p);
1735 int16val = (guint16*)p;
1736 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
1737 *int16val = GUINT16_TO_LE (5); /* number of streams */
1741 * write the stream info.
1743 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1744 table_offset += 3; table_offset &= ~3;
1746 assembly->tstream.index = heapt_size;
1747 for (i = 0; i < 5; ++i) {
1748 int32val = (guint32*)p;
1749 stream_desc [i].stream->offset = table_offset;
1750 *int32val++ = GUINT32_TO_LE (table_offset);
1751 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
1752 table_offset += GUINT32_FROM_LE (*int32val);
1753 table_offset += 3; table_offset &= ~3;
1755 strcpy (p, stream_desc [i].name);
1756 p += strlen (stream_desc [i].name) + 1;
1757 align_pointer (meta->raw_metadata, p);
1760 * now copy the data, the table stream header and contents goes first.
1762 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1763 p = meta->raw_metadata + assembly->tstream.offset;
1764 int32val = (guint32*)p;
1765 *int32val = GUINT32_TO_LE (0); /* reserved */
1767 *p++ = 1; /* version */
1769 if (meta->idx_string_wide)
1771 if (meta->idx_guid_wide)
1773 if (meta->idx_blob_wide)
1776 *p++ = 0; /* reserved */
1777 int64val = (guint64*)p;
1778 *int64val++ = GUINT64_TO_LE (valid_mask);
1779 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
1781 int32val = (guint32*)p;
1782 for (i = 0; i < 64; i++){
1783 if (meta->tables [i].rows == 0)
1785 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
1787 p = (unsigned char*)int32val;
1789 /* sort the tables that still need sorting */
1790 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1792 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
1793 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1795 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
1796 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1798 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
1799 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1801 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
1803 /* compress the tables */
1804 for (i = 0; i < 64; i++){
1807 guint32 bitfield = meta->tables [i].size_bitfield;
1808 if (!meta->tables [i].rows)
1810 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1811 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1812 meta->tables [i].base = p;
1813 for (row = 1; row <= meta->tables [i].rows; ++row) {
1814 values = assembly->tables [i].values + row * assembly->tables [i].columns;
1815 for (col = 0; col < assembly->tables [i].columns; ++col) {
1816 switch (mono_metadata_table_size (bitfield, col)) {
1818 *p++ = values [col];
1821 int16val = (guint16*)p;
1822 *int16val = GUINT16_TO_LE (values [col]);
1826 int32val = (guint32*)p;
1827 *int32val = GUINT32_TO_LE (values [col]);
1831 g_assert_not_reached ();
1835 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1838 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1839 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1840 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1841 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1842 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1844 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1848 * Some tables in metadata need to be sorted according to some criteria, but
1849 * when methods and fields are first created with reflection, they may be assigned a token
1850 * that doesn't correspond to the final token they will get assigned after the sorting.
1851 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
1852 * with the reflection objects that represent them. Once all the tables are set up, the
1853 * reflection objects will contains the correct table index. fixup_method() will fixup the
1854 * tokens for the method with ILGenerator @ilgen.
1857 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
1858 guint32 code_idx = GPOINTER_TO_UINT (value);
1859 MonoReflectionILTokenInfo *iltoken;
1860 MonoReflectionFieldBuilder *field;
1861 MonoReflectionCtorBuilder *ctor;
1862 MonoReflectionMethodBuilder *method;
1864 unsigned char *target;
1866 for (i = 0; i < ilgen->num_token_fixups; ++i) {
1867 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
1868 target = assembly->code.data + code_idx + iltoken->code_pos;
1869 switch (target [3]) {
1870 case MONO_TABLE_FIELD:
1871 if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
1872 g_assert_not_reached ();
1873 field = (MonoReflectionFieldBuilder *)iltoken->member;
1874 idx = field->table_idx;
1876 case MONO_TABLE_METHOD:
1877 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1878 method = (MonoReflectionMethodBuilder *)iltoken->member;
1879 idx = method->table_idx;
1880 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1881 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
1882 idx = ctor->table_idx;
1884 g_assert_not_reached ();
1888 g_error ("got unexpected table 0x%02x in fixup", target [3]);
1890 target [0] = idx & 0xff;
1891 target [1] = (idx >> 8) & 0xff;
1892 target [2] = (idx >> 16) & 0xff;
1897 * mono_image_build_metadata() will fill the info in all the needed metadata tables
1898 * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
1899 * and recursively outputs the info for a module. Each module will output all the info
1900 * about it's types etc.
1901 * At the end of the process, method and field tokens are fixed up and the on-disk
1902 * compressed metadata representation is created.
1905 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
1907 MonoDynamicTable *table;
1908 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
1909 MonoDomain *domain = ((MonoObject *)assemblyb)->vtable->domain;
1915 assembly->text_rva = START_TEXT_RVA;
1917 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
1918 alloc_table (table, 1);
1919 values = table->values + MONO_ASSEMBLY_SIZE;
1920 values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
1921 name = mono_string_to_utf8 (assemblyb->name);
1922 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
1924 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
1925 values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
1926 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1927 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1928 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1929 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1930 values [MONO_ASSEMBLY_FLAGS] = 0;
1932 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
1934 assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
1935 assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
1937 if (assemblyb->modules) {
1938 len = mono_array_length (assemblyb->modules);
1939 table = &assembly->tables [MONO_TABLE_MODULE];
1940 alloc_table (table, len);
1941 for (i = 0; i < len; ++i)
1942 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
1944 table = &assembly->tables [MONO_TABLE_MODULE];
1946 alloc_table (table, table->rows);
1947 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
1951 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1953 * table->rows is already set above and in mono_image_fill_module_table.
1955 alloc_table (table, table->rows);
1957 * Set the first entry.
1959 values = table->values + table->columns;
1960 values [MONO_TYPEDEF_FLAGS] = 0;
1961 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
1962 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
1963 values [MONO_TYPEDEF_EXTENDS] = 0;
1964 values [MONO_TYPEDEF_FIELD_LIST] = 1;
1965 values [MONO_TYPEDEF_METHOD_LIST] = 1;
1968 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
1970 build_compressed_metadata (assembly);
1974 * mono_image_insert_string:
1975 * @assembly: assembly builder object
1978 * Insert @str into the user string stream of @assembly.
1981 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
1987 if (!assembly->dynamic_assembly)
1988 mono_image_basic_init (assembly);
1989 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
1990 idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
1991 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1993 char *swapped = g_malloc (2 * mono_string_length (str));
1994 const char *p = (const char*)mono_string_chars (str);
1996 swap_with_size (swapped, p, 2, mono_string_length (str));
1997 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2001 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2003 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2004 return MONO_TOKEN_STRING | idx;
2008 * mono_image_create_token:
2009 * @assembly: a dynamic assembly
2012 * Get a token to insert in the IL code stream for the given MemberInfo.
2013 * @obj can be one of:
2014 * ConstructorBuilder
2024 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2030 g_error ("System.Array methods not yet supported");
2032 klass = obj->vtable->klass;
2033 if (strcmp (klass->name, "MethodBuilder") == 0) {
2034 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2035 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2036 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2039 if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2040 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2041 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2042 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2045 if (strcmp (klass->name, "FieldBuilder") == 0) {
2046 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2047 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
2049 if (strcmp (klass->name, "TypeBuilder") == 0) {
2050 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2051 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
2053 if (strcmp (klass->name, "MonoType") == 0) {
2054 MonoReflectionType *tb = (MonoReflectionType *)obj;
2055 return mono_metadata_token_from_dor (
2056 mono_image_typedef_or_ref (assembly, tb->type));
2058 if (strcmp (klass->name, "MonoCMethod") == 0 ||
2059 strcmp (klass->name, "MonoMethod") == 0) {
2060 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2061 token = mono_image_get_methodref_token (assembly, m->method);
2062 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2065 if (strcmp (klass->name, "MonoField") == 0) {
2066 MonoReflectionField *f = (MonoReflectionField *)obj;
2067 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2068 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2071 if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2072 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2073 token = mono_image_get_array_token (assembly, m);
2076 g_print ("requested token for %s\n", klass->name);
2081 guint32 import_lookup_table;
2085 guint32 import_address_table_rva;
2094 * mono_image_basic_ini:
2095 * @assembly: an assembly builder object
2097 * Create the MonoImage that represents the assembly builder and setup some
2098 * of the helper hash table and the basic metadata streams.
2101 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2103 static const guchar entrycode [16] = {0xff, 0x25, 0};
2104 MonoDynamicAssembly *assembly;
2108 if (assemblyb->dynamic_assembly)
2112 assembly = assemblyb->dynamic_assembly = GC_malloc (sizeof (MonoDynamicAssembly));
2114 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2117 assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2118 assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2119 assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2121 string_heap_init (&assembly->sheap);
2122 mono_image_add_stream_data (&assembly->us, "", 1);
2123 mono_image_add_stream_data (&assembly->blob, "", 1);
2124 /* import tables... */
2125 mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2126 assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2127 assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2128 mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2129 assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2130 mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2131 assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2132 stream_data_align (&assembly->code);
2134 assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2136 for (i=0; i < 64; ++i) {
2137 assembly->tables [i].next_idx = 1;
2138 assembly->tables [i].columns = table_sizes [i];
2141 image = g_new0 (MonoImage, 1);
2143 /* keep in sync with image.c */
2144 image->name = mono_string_to_utf8 (assemblyb->name);
2145 image->assembly_name = image->name; /* they may be different */
2147 image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2148 image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2149 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2150 image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2152 assembly->assembly.image = image;
2157 calc_section_size (MonoDynamicAssembly *assembly)
2161 /* alignment constraints */
2162 assembly->code.index += 3;
2163 assembly->code.index &= ~3;
2164 assembly->meta_size += 3;
2165 assembly->meta_size &= ~3;
2167 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index;
2168 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2171 assembly->sections [MONO_SECTION_RELOC].size = 12;
2172 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2179 * mono_image_create_pefile:
2180 * @assemblyb: an assembly builder object
2182 * When we need to save an assembly, we first call this function that ensures the metadata
2183 * tables are built for all the modules in the assembly. This function creates the PE-COFF
2184 * header, the image sections, the CLI header etc. all the data is written in
2185 * assembly->pefile where it can be easily retrieved later in chunks.
2188 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
2189 MonoMSDOSHeader *msdos;
2190 MonoDotNetHeader *header;
2191 MonoSectionTable *section;
2192 MonoCLIHeader *cli_header;
2193 guint32 size, image_size, virtual_base;
2194 guint32 header_start, section_start, file_offset, virtual_offset;
2195 MonoDynamicAssembly *assembly;
2196 MonoDynamicStream *pefile;
2200 static const unsigned char msheader[] = {
2201 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2202 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2205 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2206 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2207 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2208 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2211 mono_image_basic_init (assemblyb);
2212 assembly = assemblyb->dynamic_assembly;
2214 /* already created */
2215 if (assembly->pefile.index)
2218 mono_image_build_metadata (assemblyb);
2219 nsections = calc_section_size (assembly);
2221 pefile = &assembly->pefile;
2223 /* The DOS header and stub */
2224 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2225 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
2227 /* the dotnet header */
2228 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2230 /* the section tables */
2231 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2233 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2234 virtual_offset = VIRT_ALIGN;
2237 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2238 if (!assembly->sections [i].size)
2241 file_offset += FILE_ALIGN - 1;
2242 file_offset &= ~(FILE_ALIGN - 1);
2243 virtual_offset += VIRT_ALIGN - 1;
2244 virtual_offset &= ~(VIRT_ALIGN - 1);
2246 assembly->sections [i].offset = file_offset;
2247 assembly->sections [i].rva = virtual_offset;
2249 file_offset += assembly->sections [i].size;
2250 virtual_offset += assembly->sections [i].size;
2251 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2254 file_offset += FILE_ALIGN - 1;
2255 file_offset &= ~(FILE_ALIGN - 1);
2256 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
2258 image_size += section_start + sizeof (MonoSectionTable) * nsections;
2260 /* back-patch info */
2261 msdos = (MonoMSDOSHeader*)pefile->data;
2262 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
2263 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
2264 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2266 header = (MonoDotNetHeader*)(pefile->data + header_start);
2267 header->pesig [0] = 'P';
2268 header->pesig [1] = 'E';
2270 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
2271 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2272 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2273 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2275 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2276 /* FIXME: it's a dll */
2277 /*header->coff.coff_attributes = GUINT16_FROM_LE (0x210e); */
2279 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2281 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2282 header->pe.pe_major = 6;
2283 header->pe.pe_minor = 0;
2284 size = assembly->sections [MONO_SECTION_TEXT].size;
2285 size += FILE_ALIGN - 1;
2286 size &= ~(FILE_ALIGN - 1);
2287 header->pe.pe_code_size = size;
2288 size = assembly->sections [MONO_SECTION_RSRC].size;
2289 size += FILE_ALIGN - 1;
2290 size &= ~(FILE_ALIGN - 1);
2291 header->pe.pe_data_size = size;
2292 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2293 header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
2294 header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
2295 /* pe_rva_entry_point always at the beginning of the text section */
2296 header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
2298 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2299 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2300 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2301 header->nt.pe_os_major = GUINT16_FROM_LE (4);
2302 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2303 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2304 size = section_start;
2305 size += FILE_ALIGN - 1;
2306 size &= ~(FILE_ALIGN - 1);
2307 header->nt.pe_header_size = GUINT32_FROM_LE (size);
2309 size += VIRT_ALIGN - 1;
2310 size &= ~(VIRT_ALIGN - 1);
2311 header->nt.pe_image_size = GUINT32_FROM_LE (size);
2312 header->nt.pe_subsys_required = GUINT16_FROM_LE (3); /* 3 -> cmdline app, 2 -> GUI app */
2313 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2314 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2315 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2316 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2317 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2318 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2320 /* fill data directory entries */
2322 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2323 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2325 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2326 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2328 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2329 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2330 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2331 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2332 /* patch imported function RVA name */
2333 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2334 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2336 /* the import table */
2337 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2338 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2339 /* patch imported dll RVA name and other entries in the dir */
2340 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2341 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
2342 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2343 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2344 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2345 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2347 rva = (guint32*)(assembly->code.data + assembly->ilt_offset);
2348 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset - 2);
2350 /* the CLI header info */
2351 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2352 cli_header->ch_size = GUINT32_FROM_LE (72);
2353 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
2354 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
2355 if (assemblyb->entry_point)
2356 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
2358 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
2359 cli_header->ch_metadata.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->code.index);
2360 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
2362 /* write the section tables and section content */
2363 section = (MonoSectionTable*)(pefile->data + section_start);
2364 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2365 static const char *section_names [] = {
2366 ".text", ".rsrc", ".reloc"
2368 if (!assembly->sections [i].size)
2370 strcpy (section->st_name, section_names [i]);
2371 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
2372 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
2373 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
2374 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
2375 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
2376 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
2377 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
2379 case MONO_SECTION_TEXT:
2380 /* patch entry point */
2381 rva = (guint32*)(assembly->code.data + 2);
2382 *rva = GUINT32_FROM_LE (virtual_base + assembly->text_rva + assembly->iat_offset);
2383 memcpy (pefile->data + assembly->sections [i].offset, assembly->code.data, assembly->code.index);
2384 memcpy (pefile->data + assembly->sections [i].offset + assembly->code.index, assembly->assembly.image->raw_metadata, assembly->meta_size);
2386 case MONO_SECTION_RELOC:
2387 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
2388 *rva = GUINT32_FROM_LE (assembly->text_rva);
2390 *rva = GUINT32_FROM_LE (12);
2392 data16 = (guint16*)rva;
2394 * the entrypoint is always at the start of the text section
2395 * 3 is IMAGE_REL_BASED_HIGHLOW
2396 * 2 is patch_size_rva - text_rva
2398 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
2400 *data16 = 0; /* terminate */
2402 case MONO_SECTION_RSRC:
2404 g_assert_not_reached ();
2409 /* check that the file is properly padded */
2412 FILE *f = fopen ("mypetest.exe", "w");
2413 fwrite (pefile->data, pefile->index, 1, f);
2420 * We need to return always the same object for MethodInfo, FieldInfo etc..
2421 * type uses a different hash, since it uses custom hash/equal functions.
2423 static MonoGHashTable *object_cache = NULL;
2424 static MonoGHashTable *type_cache = NULL;
2426 #define CHECK_OBJECT(t,p) \
2429 if (!object_cache) \
2430 object_cache = mono_g_hash_table_new (g_direct_hash, g_direct_equal); \
2431 if ((_obj = mono_g_hash_table_lookup (object_cache, (p)))) \
2435 #define CACHE_OBJECT(p,o) \
2437 mono_g_hash_table_insert (object_cache, p,o); \
2441 * mono_assembly_get_object:
2442 * @domain: an app domain
2443 * @assembly: an assembly
2445 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
2447 MonoReflectionAssembly*
2448 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
2450 static MonoClass *System_Reflection_Assembly;
2451 MonoReflectionAssembly *res;
2453 CHECK_OBJECT (MonoReflectionAssembly *, assembly);
2454 if (!System_Reflection_Assembly)
2455 System_Reflection_Assembly = mono_class_from_name (
2456 mono_defaults.corlib, "System.Reflection", "Assembly");
2457 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
2458 res->assembly = assembly;
2459 CACHE_OBJECT (assembly, res);
2464 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
2466 if ((t1->type != t2->type) ||
2467 (t1->byref != t2->byref))
2471 case MONO_TYPE_VOID:
2472 case MONO_TYPE_BOOLEAN:
2473 case MONO_TYPE_CHAR:
2484 case MONO_TYPE_STRING:
2487 case MONO_TYPE_OBJECT:
2489 case MONO_TYPE_VALUETYPE:
2490 case MONO_TYPE_CLASS:
2491 return t1->data.klass == t2->data.klass;
2493 case MONO_TYPE_SZARRAY:
2494 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
2495 case MONO_TYPE_ARRAY:
2496 if (t1->data.array->rank != t2->data.array->rank)
2498 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
2500 g_error ("implement type compare for %0x!", t1->type);
2508 mymono_metadata_type_hash (MonoType *t1)
2514 hash |= t1->byref << 6; /* do not collide with t1->type values */
2516 case MONO_TYPE_VALUETYPE:
2517 case MONO_TYPE_CLASS:
2518 /* check if the distribution is good enough */
2519 return hash << 7 | g_str_hash (t1->data.klass->name);
2521 case MONO_TYPE_SZARRAY:
2522 return hash << 7 | mymono_metadata_type_hash (t1->data.type);
2528 * mono_type_get_object:
2529 * @domain: an app domain
2532 * Return an System.MonoType object representing the type @type.
2535 mono_type_get_object (MonoDomain *domain, MonoType *type)
2537 MonoReflectionType *res;
2538 MonoClass *klass = mono_class_from_mono_type (type);
2541 type_cache = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
2542 (GCompareFunc)mymono_metadata_type_equal);
2543 if ((res = mono_g_hash_table_lookup (type_cache, type)))
2545 if (klass->reflection_info) {
2546 /* should this be considered an error condition? */
2548 return klass->reflection_info;
2550 mono_class_init (klass);
2551 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
2553 mono_g_hash_table_insert (type_cache, type, res);
2558 * mono_method_get_object:
2559 * @domain: an app domain
2562 * Return an System.Reflection.MonoMethod object representing the method @method.
2564 MonoReflectionMethod*
2565 mono_method_get_object (MonoDomain *domain, MonoMethod *method)
2568 * We use the same C representation for methods and constructors, but the type
2569 * name in C# is different.
2573 MonoReflectionMethod *ret;
2575 CHECK_OBJECT (MonoReflectionMethod *, method);
2576 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
2577 cname = "MonoCMethod";
2579 cname = "MonoMethod";
2580 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
2582 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
2583 ret->method = method;
2584 ret->name = mono_string_new (domain, method->name);
2585 CACHE_OBJECT (method, ret);
2590 * mono_field_get_object:
2591 * @domain: an app domain
2595 * Return an System.Reflection.MonoField object representing the field @field
2598 MonoReflectionField*
2599 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
2601 MonoReflectionField *res;
2604 CHECK_OBJECT (MonoReflectionField *, field);
2605 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
2606 res = (MonoReflectionField *)mono_object_new (domain, oklass);
2609 CACHE_OBJECT (field, res);
2614 * mono_property_get_object:
2615 * @domain: an app domain
2617 * @property: a property
2619 * Return an System.Reflection.MonoProperty object representing the property @property
2622 MonoReflectionProperty*
2623 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
2625 MonoReflectionProperty *res;
2628 CHECK_OBJECT (MonoReflectionProperty *, property);
2629 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
2630 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
2632 res->property = property;
2633 CACHE_OBJECT (property, res);
2638 * mono_event_get_object:
2639 * @domain: an app domain
2643 * Return an System.Reflection.MonoEvent object representing the event @event
2646 MonoReflectionEvent*
2647 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
2649 MonoReflectionEvent *res;
2652 CHECK_OBJECT (MonoReflectionEvent *, event);
2653 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
2654 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
2657 CACHE_OBJECT (event, res);
2662 * mono_param_get_objects:
2663 * @domain: an app domain
2666 * Return an System.Reflection.ParameterInfo array object representing the parameters
2667 * in the method @method.
2669 MonoReflectionParameter**
2670 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
2672 MonoReflectionParameter **res;
2673 MonoReflectionMethod *member;
2678 if (!method->signature->param_count)
2681 member = mono_method_get_object (domain, method);
2682 names = g_new (char *, method->signature->param_count);
2683 mono_method_get_param_names (method, (const char **) names);
2685 /* Note: the cache is based on the address of the signature into the method
2686 * since we already cache MethodInfos with the method as keys.
2688 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature));
2689 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
2691 res = GC_malloc (sizeof (MonoReflectionParameter*) * method->signature->param_count);
2693 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
2695 for (i = 0; i < method->signature->param_count; ++i) {
2696 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
2697 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
2698 res [i]->DefaultValueImpl = NULL; /* FIXME */
2699 res [i]->MemberImpl = (MonoObject*)member;
2700 res [i]->NameImpl = mono_string_new (domain, names [i]);
2701 res [i]->PositionImpl = i + 1;
2702 res [i]->AttrsImpl = method->signature->params [i]->attrs;
2705 CACHE_OBJECT (&(method->signature), res);
2710 * mono_reflection_parse_type:
2713 * Parse a type name as accepted by the GetType () method and output the info
2714 * extracted in the info structure.
2715 * the name param will be mangled, so, make a copy before passing it to this function.
2716 * The fields in info will be valid until the memory pointed to by name is valid.
2717 * Returns 0 on parse error.
2718 * See also mono_type_get_name () below.
2721 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
2723 char *start, *p, *w, *last_point;
2724 int in_modifiers = 0;
2725 int isbyref = 0, rank;
2727 start = p = w = name;
2729 info->name = info->name_space = info->assembly = NULL;
2730 info->nested = NULL;
2731 info->modifiers = NULL;
2733 /* last_point separates the namespace from the name */
2739 *p = 0; /* NULL terminate the name */
2741 /* we have parsed the nesting namespace + name */
2743 info->nested = g_list_append (info->nested, start);
2747 info->name_space = start;
2749 info->name = last_point + 1;
2751 info->name_space = (char *)"";
2776 info->nested = g_list_append (info->nested, start);
2779 info->name_space = start;
2781 info->name = last_point + 1;
2783 info->name_space = (char *)"";
2790 if (isbyref) /* only one level allowed by the spec */
2793 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
2797 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
2808 else if (*p != '*') /* '*' means unknown lower bound */
2814 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
2826 return 0; /* missing assembly name */
2833 *w = 0; /* terminate class name */
2834 if (!info->name || !*info->name)
2836 /* add other consistency checks */
2841 mono_type_get_name_recurse (MonoType *type, GString *str)
2845 switch (type->type) {
2846 case MONO_TYPE_ARRAY: {
2847 int i, rank = type->data.array->rank;
2849 mono_type_get_name_recurse (type->data.array->type, str);
2850 g_string_append_c (str, '[');
2851 for (i = 1; i < rank; i++)
2852 g_string_append_c (str, ',');
2853 g_string_append_c (str, ']');
2856 case MONO_TYPE_SZARRAY:
2857 mono_type_get_name_recurse (type->data.type, str);
2858 g_string_append (str, "[]");
2861 mono_type_get_name_recurse (type->data.type, str);
2862 g_string_append_c (str, '*');
2865 klass = mono_class_from_mono_type (type);
2866 if (klass->nested_in) {
2867 mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
2868 g_string_append_c (str, '+');
2870 if (*klass->name_space) {
2871 g_string_append (str, klass->name_space);
2872 g_string_append_c (str, '.');
2874 g_string_append (str, klass->name);
2880 * mono_type_get_name:
2883 * Returns the string representation for type as required by System.Reflection.
2884 * The inverse of mono_reflection_parse_type ().
2887 mono_type_get_name (MonoType *type)
2889 GString* result = g_string_new ("");
2890 mono_type_get_name_recurse (type, result);
2893 g_string_append_c (result, '&');
2895 return g_string_free (result, FALSE);
2899 * mono_reflection_get_type:
2900 * @image: a metadata context
2901 * @info: type description structure
2902 * @ignorecase: flag for case-insensitive string compares
2904 * Build a MonoType from the type description in @info.
2908 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
2915 image = mono_defaults.corlib;
2918 klass = mono_class_from_name_case (image, info->name_space, info->name);
2920 klass = mono_class_from_name (image, info->name_space, info->name);
2923 for (mod = info->nested; mod; mod = mod->next) {
2926 mono_class_init (klass);
2927 nested = klass->nested_classes;
2930 klass = nested->data;
2932 if (g_strcasecmp (klass->name, mod->data) == 0)
2935 if (strcmp (klass->name, mod->data) == 0)
2939 nested = nested->next;
2946 mono_class_init (klass);
2947 for (mod = info->modifiers; mod; mod = mod->next) {
2948 modval = GPOINTER_TO_UINT (mod->data);
2949 if (!modval) { /* byref: must be last modifier */
2950 return &klass->this_arg;
2951 } else if (modval == -1) {
2952 klass = mono_ptr_class_get (&klass->byval_arg);
2953 } else { /* array rank */
2954 klass = mono_array_class_get (&klass->byval_arg, modval);
2956 mono_class_init (klass);
2958 return &klass->byval_arg;
2962 * Optimization we could avoid mallocing() an little-endian archs that
2963 * don't crash with unaligned accesses.
2966 fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
2967 int len, i, slen, type;
2968 const char *p = mono_metadata_blob_heap (image, blobidx);
2970 len = mono_metadata_decode_value (p, &p);
2971 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
2976 for (i = 0; i < sig->param_count; ++i) {
2977 type = sig->params [i]->type;
2982 case MONO_TYPE_BOOLEAN: {
2983 MonoBoolean *bval = params [i] = g_malloc (sizeof (MonoBoolean));
2988 case MONO_TYPE_CHAR:
2990 case MONO_TYPE_I2: {
2991 guint16 *val = params [i] = g_malloc (sizeof (guint16));
2996 #if SIZEOF_VOID_P == 4
3002 case MONO_TYPE_I4: {
3003 guint32 *val = params [i] = g_malloc (sizeof (guint32));
3008 #if SIZEOF_VOID_P == 8
3009 case MONO_TYPE_U: /* error out instead? this should probably not happen */
3014 case MONO_TYPE_I8: {
3015 guint64 *val = params [i] = g_malloc (sizeof (guint64));
3020 case MONO_TYPE_VALUETYPE:
3021 if (sig->params [i]->data.klass->enumtype) {
3022 type = sig->params [i]->data.klass->enum_basetype->type;
3025 g_warning ("generic valutype %s not handled in custom attr value decoding", sig->params [i]->data.klass->name);
3028 case MONO_TYPE_STRING: {
3029 slen = mono_metadata_decode_value (p, &p);
3030 params [i] = mono_string_new_len (mono_domain_get (), p, slen);
3035 g_warning ("Type %02x not handled in custom attr value decoding", sig->params [i]->type);
3042 free_param_data (MonoMethodSignature *sig, void **params) {
3044 for (i = 0; i < sig->param_count; ++i) {
3045 switch (sig->params [i]->type) {
3046 case MONO_TYPE_BOOLEAN:
3047 case MONO_TYPE_CHAR:
3060 case MONO_TYPE_VALUETYPE:
3061 g_free (params [i]);
3070 * Find the method index in the metadata methodDef table.
3071 * Later put these three helper methods in metadata and export them.
3074 find_method_index (MonoMethod *method) {
3075 MonoClass *klass = method->klass;
3078 for (i = 0; i < klass->method.count; ++i) {
3079 if (method == klass->methods [i])
3080 return klass->method.first + 1 + i;
3086 * Find the field index in the metadata FieldDef table.
3089 find_field_index (MonoClass *klass, MonoClassField *field) {
3092 for (i = 0; i < klass->field.count; ++i) {
3093 if (field == &klass->fields [i])
3094 return klass->field.first + 1 + i;
3100 * Find the property index in the metadata Property table.
3103 find_property_index (MonoClass *klass, MonoProperty *property) {
3106 for (i = 0; i < klass->property.count; ++i) {
3107 if (property == &klass->properties [i])
3108 return klass->property.first + 1 + i;
3114 * Find the event index in the metadata Event table.
3117 find_event_index (MonoClass *klass, MonoEvent *event) {
3120 for (i = 0; i < klass->event.count; ++i) {
3121 if (event == &klass->events [i])
3122 return klass->event.first + 1 + i;
3128 * mono_reflection_get_custom_attrs:
3129 * @obj: a reflection object handle
3131 * Return an array with all the custom attributes defined of the
3132 * reflection handle @obj. The objects are fully build.
3135 mono_reflection_get_custom_attrs (MonoObject *obj)
3137 guint32 idx, mtoken, i, len;
3138 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
3148 klass = obj->vtable->klass;
3149 /* FIXME: need to handle: Module */
3150 if (klass == mono_defaults.monotype_class) {
3151 MonoReflectionType *rtype = (MonoReflectionType*)obj;
3152 klass = mono_class_from_mono_type (rtype->type);
3153 idx = mono_metadata_token_index (klass->type_token);
3154 idx <<= CUSTOM_ATTR_BITS;
3155 idx |= CUSTOM_ATTR_TYPEDEF;
3156 image = klass->image;
3157 } else if (strcmp ("Assembly", klass->name) == 0) {
3158 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
3159 idx = 1; /* there is only one assembly */
3160 idx <<= CUSTOM_ATTR_BITS;
3161 idx |= CUSTOM_ATTR_ASSEMBLY;
3162 image = rassembly->assembly->image;
3163 } else if (strcmp ("MonoProperty", klass->name) == 0) {
3164 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
3165 idx = find_property_index (rprop->klass, rprop->property);
3166 idx <<= CUSTOM_ATTR_BITS;
3167 idx |= CUSTOM_ATTR_PROPERTY;
3168 image = rprop->klass->image;
3169 } else if (strcmp ("MonoEvent", klass->name) == 0) {
3170 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
3171 idx = find_event_index (revent->klass, revent->event);
3172 idx <<= CUSTOM_ATTR_BITS;
3173 idx |= CUSTOM_ATTR_EVENT;
3174 image = revent->klass->image;
3175 } else if (strcmp ("MonoField", klass->name) == 0) {
3176 MonoReflectionField *rfield = (MonoReflectionField*)obj;
3177 idx = find_field_index (rfield->klass, rfield->field);
3178 idx <<= CUSTOM_ATTR_BITS;
3179 idx |= CUSTOM_ATTR_FIELDDEF;
3180 image = rfield->klass->image;
3181 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
3182 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
3183 idx = find_method_index (rmethod->method);
3184 idx <<= CUSTOM_ATTR_BITS;
3185 idx |= CUSTOM_ATTR_METHODDEF;
3186 image = rmethod->method->klass->image;
3187 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
3188 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
3189 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
3190 guint32 method_index = find_method_index (rmethod->method);
3191 guint32 param_list, param_last, param_pos, found;
3193 image = rmethod->method->klass->image;
3194 ca = &image->tables [MONO_TABLE_METHOD];
3196 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
3197 if (method_index == ca->rows) {
3198 ca = &image->tables [MONO_TABLE_PARAM];
3199 param_last = ca->rows + 1;
3201 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
3202 ca = &image->tables [MONO_TABLE_PARAM];
3205 for (i = param_list; i < param_last; ++i) {
3206 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
3207 if (param_pos == param->PositionImpl) {
3213 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
3215 idx <<= CUSTOM_ATTR_BITS;
3216 idx |= CUSTOM_ATTR_PARAMDEF;
3217 } else { /* handle other types here... */
3218 g_error ("get custom attrs not yet supported for %s", klass->name);
3221 /* at this point image and index are set correctly for searching the custom attr */
3222 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3223 /* the table is not sorted */
3224 for (i = 0; i < ca->rows; ++i) {
3225 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
3226 if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
3228 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
3229 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
3230 case CUSTOM_ATTR_TYPE_METHODDEF:
3231 mtoken |= MONO_TOKEN_METHOD_DEF;
3233 case CUSTOM_ATTR_TYPE_MEMBERREF:
3234 mtoken |= MONO_TOKEN_MEMBER_REF;
3237 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
3240 method = mono_get_method (image, mtoken, NULL);
3242 g_error ("Can't find custom attr constructor");
3243 mono_class_init (method->klass);
3244 /*g_print ("got attr %s\n", method->klass->name);*/
3245 params = g_new (void*, method->signature->param_count);
3246 fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
3247 attr = mono_object_new (mono_domain_get (), method->klass);
3248 mono_runtime_invoke (method, attr, params, NULL);
3249 list = g_list_prepend (list, attr);
3250 free_param_data (method->signature, params);
3254 len = g_list_length (list);
3256 * The return type is really object[], but System/Attribute.cs does a cast
3257 * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
3258 * probably fix that.
3260 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
3261 result = mono_array_new (mono_domain_get (), klass, len);
3262 for (i = 0; i < len; ++i) {
3263 mono_array_set (result, gpointer, i, list->data);
3266 g_list_free (g_list_first (list));
3271 static MonoMethodSignature*
3272 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
3273 MonoMethodSignature *sig;
3276 count = ctor->parameters? mono_array_length (ctor->parameters): 0;
3278 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
3280 sig->param_count = count;
3281 sig->sentinelpos = -1; /* FIXME */
3282 for (i = 0; i < count; ++i) {
3283 MonoReflectionType *pt = mono_array_get (ctor->parameters, MonoReflectionType*, i);
3284 sig->params [i] = pt->type;
3290 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
3292 MonoClass *klass = mono_object_class (prop);
3293 if (strcmp (klass->name, "PropertyBuilder") == 0) {
3294 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
3295 *name = mono_string_to_utf8 (pb->name);
3296 *type = pb->type->type;
3298 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
3299 *name = g_strdup (p->property->name);
3300 if (p->property->get)
3301 *type = p->property->get->signature->ret;
3303 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
3308 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
3310 MonoClass *klass = mono_object_class (field);
3311 if (strcmp (klass->name, "FieldBuilder") == 0) {
3312 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
3313 *name = mono_string_to_utf8 (fb->name);
3314 *type = fb->type->type;
3316 MonoReflectionField *f = (MonoReflectionField *)field;
3317 *name = g_strdup (f->field->name);
3318 *type = f->field->type;
3323 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
3324 char *name, *result;
3328 name = mono_type_get_name (type);
3329 klass = mono_class_from_mono_type (type);
3330 ta = klass->image->assembly;
3331 if (ta == ass || klass->image == mono_defaults.corlib)
3334 /* missing public key */
3335 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
3336 name, ta->aname.name,
3337 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
3338 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
3344 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
3347 MonoTypeEnum simple_type;
3349 if ((p-buffer) + 10 >= *buflen) {
3352 newbuf = g_realloc (buffer, *buflen);
3353 p = newbuf + (p-buffer);
3356 argval = ((char*)arg + sizeof (MonoObject));
3357 simple_type = type->type;
3359 switch (simple_type) {
3360 case MONO_TYPE_BOOLEAN:
3365 case MONO_TYPE_CHAR:
3368 swap_with_size (p, argval, 2, 1);
3374 swap_with_size (p, argval, 4, 1);
3380 swap_with_size (p, argval, 8, 1);
3383 case MONO_TYPE_VALUETYPE:
3384 if (type->data.klass->enumtype) {
3385 simple_type = type->data.klass->enum_basetype->type;
3388 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
3391 case MONO_TYPE_STRING: {
3392 char *str = mono_string_to_utf8 ((MonoString*)arg);
3393 guint32 slen = strlen (str);
3394 if ((p-buffer) + 10 + slen >= *buflen) {
3398 newbuf = g_realloc (buffer, *buflen);
3399 p = newbuf + (p-buffer);
3402 mono_metadata_encode_value (slen, p, &p);
3403 memcpy (p, str, slen);
3408 case MONO_TYPE_CLASS: {
3411 if (!mono_object_isinst (arg, mono_defaults.monotype_class))
3412 g_error ("only types allowed");
3414 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
3415 slen = strlen (str);
3416 if ((p-buffer) + 10 + slen >= *buflen) {
3420 newbuf = g_realloc (buffer, *buflen);
3421 p = newbuf + (p-buffer);
3424 mono_metadata_encode_value (slen, p, &p);
3425 memcpy (p, str, slen);
3430 /* it may be a boxed value or a Type */
3431 case MONO_TYPE_OBJECT: {
3432 MonoClass *klass = mono_object_class (arg);
3436 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
3439 } else if (klass->enumtype) {
3441 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
3442 *p++ = simple_type = klass->byval_arg.type;
3445 g_error ("unhandled type in custom attr");
3447 str = type_get_qualified_name (klass->enum_basetype, NULL);
3448 slen = strlen (str);
3449 if ((p-buffer) + 10 + slen >= *buflen) {
3453 newbuf = g_realloc (buffer, *buflen);
3454 p = newbuf + (p-buffer);
3457 mono_metadata_encode_value (slen, p, &p);
3458 memcpy (p, str, slen);
3461 simple_type = klass->enum_basetype->type;
3465 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
3468 *retbuffer = buffer;
3472 * mono_reflection_get_custom_attrs_blob:
3473 * @ctor: custom attribute constructor
3474 * @ctorArgs: arguments o the constructor
3480 * Creates the blob of data that needs to be saved in the metadata and that represents
3481 * the custom attributed described by @ctor, @ctorArgs etc.
3482 * Returns: a Byte array representing the blob of data.
3485 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) {
3487 MonoMethodSignature *sig;
3492 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3493 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
3495 sig = ((MonoReflectionMethod*)ctor)->method->signature;
3498 p = buffer = g_malloc (buflen);
3499 /* write the prolog */
3502 for (i = 0; i < sig->param_count; ++i) {
3503 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
3504 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
3508 i += mono_array_length (properties);
3510 i += mono_array_length (fields);
3512 *p++ = (i >> 8) & 0xff;
3515 for (i = 0; i < mono_array_length (properties); ++i) {
3520 prop = mono_array_get (properties, gpointer, i);
3521 get_prop_name_and_type (prop, &pname, &ptype);
3522 *p++ = 0x54; /* PROPERTY signature */
3523 len = strlen (pname);
3524 mono_metadata_encode_value (len, p, &p);
3525 memcpy (p, pname, len);
3527 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
3534 for (i = 0; i < mono_array_length (fields); ++i) {
3539 field = mono_array_get (fields, gpointer, i);
3540 get_field_name_and_type (field, &fname, &ftype);
3541 *p++ = 0x53; /* FIELD signature */
3542 len = strlen (fname);
3543 mono_metadata_encode_value (len, p, &p);
3544 memcpy (p, fname, len);
3546 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
3551 g_assert (p - buffer <= buflen);
3552 buflen = p - buffer;
3553 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
3554 p = mono_array_addr (result, char, 0);
3555 memcpy (p, buffer, buflen);
3557 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
3563 * mono_reflection_setup_internal_class:
3564 * @tb: a TypeBuilder object
3566 * Creates a MonoClass that represents the TypeBuilder.
3567 * This is a trick that lets us simplify a lot of reflection code
3568 * (and will allow us to support Build and Run assemblies easier).
3571 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
3573 MonoClass *klass, *parent;
3575 klass = g_new0 (MonoClass, 1);
3577 klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
3580 parent = mono_class_from_mono_type (tb->parent->type);
3584 klass->inited = 1; /* we lie to the runtime */
3585 klass->name = mono_string_to_utf8 (tb->name);
3586 klass->name_space = mono_string_to_utf8 (tb->nspace);
3587 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
3588 klass->flags = tb->attrs;
3590 klass->element_class = klass;
3591 klass->reflection_info = tb; /* need to pin. */
3594 mono_class_setup_parent (klass, parent);
3595 mono_class_setup_mono_type (klass);
3598 * FIXME: handle interfaces.
3601 tb->type.type = &klass->byval_arg;
3603 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
3607 * mono_reflection_create_internal_class:
3608 * @tb: a TypeBuilder object
3610 * Actually create the MonoClass that is associated with the TypeBuilder.
3613 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
3617 klass = mono_class_from_mono_type (tb->type.type);
3619 if (klass->enumtype && klass->enum_basetype == NULL) {
3620 MonoReflectionFieldBuilder *fb;
3622 g_assert (tb->fields != NULL);
3623 g_assert (mono_array_length (tb->fields) >= 1);
3625 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
3627 klass->enum_basetype = fb->type->type;
3628 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
3633 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
3635 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
3636 guint32 na = mono_array_length (sig->arguments);
3641 p = buf = g_malloc (10 + na * 10);
3643 mono_metadata_encode_value (0x07, p, &p);
3644 mono_metadata_encode_value (na, p, &p);
3645 for (i = 0; i < na; ++i) {
3646 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
3647 encode_reflection_type (assembly, type, p, &p);
3651 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
3652 p = mono_array_addr (result, char, 0);
3653 memcpy (p, buf, buflen);
3660 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
3662 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
3663 guint32 na = mono_array_length (sig->arguments);
3668 p = buf = g_malloc (10 + na * 10);
3670 mono_metadata_encode_value (0x06, p, &p);
3671 for (i = 0; i < na; ++i) {
3672 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
3673 encode_reflection_type (assembly, type, p, &p);
3677 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
3678 p = mono_array_addr (result, char, 0);
3679 memcpy (p, buf, buflen);