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);
667 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
669 MonoDynamicTable *table;
672 ReflectionMethodBuilder rmb;
674 rmb.ilgen = mb->ilgen;
675 rmb.rtype = mb->rtype;
676 rmb.parameters = mb->parameters;
677 rmb.pinfo = mb->pinfo;
678 rmb.attrs = mb->attrs;
679 rmb.iattrs = mb->iattrs;
680 rmb.call_conv = mb->call_conv;
684 rmb.table_idx = &mb->table_idx;
685 rmb.init_locals = mb->init_locals;
687 mono_image_basic_method (&rmb, assembly);
689 if (mb->dll) { /* It's a P/Invoke method */
691 table = &assembly->tables [MONO_TABLE_IMPLMAP];
693 alloc_table (table, table->rows);
694 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
695 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
696 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
697 name = mono_string_to_utf8 (mb->dllentry);
698 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
700 name = mono_string_to_utf8 (mb->dll);
701 moduleref = string_heap_insert (&assembly->sheap, name);
703 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
704 table = &assembly->tables [MONO_TABLE_MODULEREF];
706 alloc_table (table, table->rows);
707 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
708 values [MONO_IMPLMAP_SCOPE] = table->rows;
711 if (mb->override_method) {
712 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_METHODIMPL_SIZE;
718 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
719 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
720 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
721 switch (mono_metadata_token_table (tok)) {
722 case MONO_TABLE_MEMBERREF:
723 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
725 case MONO_TABLE_METHOD:
726 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
729 g_assert_not_reached ();
731 values [MONO_METHODIMPL_DECLARATION] = tok;
736 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
738 ReflectionMethodBuilder rmb;
740 rmb.ilgen = mb->ilgen;
741 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
742 rmb.parameters = mb->parameters;
743 rmb.pinfo = mb->pinfo;
744 rmb.attrs = mb->attrs;
745 rmb.iattrs = mb->iattrs;
746 rmb.call_conv = mb->call_conv;
750 rmb.table_idx = &mb->table_idx;
751 rmb.init_locals = mb->init_locals;
753 mono_image_basic_method (&rmb, assembly);
758 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
766 p = buf = g_malloc (64);
768 mono_metadata_encode_value (0x06, p, &p);
769 /* encode custom attributes before the type */
770 encode_type (assembly, field->type, p, &p);
771 g_assert (p-buf < 64);
772 mono_metadata_encode_value (p-buf, b, &b);
773 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
774 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
780 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
788 p = buf = g_malloc (64);
790 mono_metadata_encode_value (0x06, p, &p);
791 /* encode custom attributes before the type */
792 encode_reflection_type (assembly, fb->type, p, &p);
793 g_assert (p-buf < 64);
794 mono_metadata_encode_value (p-buf, b, &b);
795 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
796 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
802 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
803 * dest may be misaligned.
806 swap_with_size (char *dest, const char* val, int len, int nelem) {
807 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
810 for (elem = 0; elem < nelem; ++elem) {
836 g_assert_not_reached ();
842 memcpy (dest, val, len * nelem);
847 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
854 p = buf = g_malloc (64);
856 box_val = ((char*)val) + sizeof (MonoObject);
857 *ret_type = val->vtable->klass->byval_arg.type;
860 case MONO_TYPE_BOOLEAN:
880 case MONO_TYPE_VALUETYPE:
881 if (val->vtable->klass->enumtype) {
882 *ret_type = val->vtable->klass->enum_basetype->type;
885 g_error ("we can't encode valuetypes");
886 case MONO_TYPE_STRING: {
887 MonoString *str = (MonoString*)val;
888 /* there is no signature */
889 len = str->length * 2;
890 mono_metadata_encode_value (len, b, &b);
891 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
892 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
894 char *swapped = g_malloc (2 * mono_string_length (str));
895 const char *p = (const char*)mono_string_chars (str);
897 swap_with_size (swapped, p, 2, mono_string_length (str));
898 mono_image_add_stream_data (&assembly->blob, swapped, len);
902 mono_image_add_stream_data (&assembly->blob, (const char*)mono_string_chars (str), len);
909 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
912 /* there is no signature */
913 mono_metadata_encode_value (len, b, &b);
914 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
915 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
916 swap_with_size (blob_size, val, len, 1);
917 mono_image_add_stream_data (&assembly->blob, blob_size, len);
919 mono_image_add_stream_data (&assembly->blob, box_val, len);
927 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo) {
933 p = buf = g_malloc (256);
935 switch (minfo->type) {
936 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
938 mono_metadata_encode_value (minfo->type, p, &p);
942 mono_metadata_encode_value (len, b, &b);
943 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
944 mono_image_add_stream_data (&assembly->blob, buf, len);
950 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
952 MonoDynamicTable *table;
956 /* maybe this fixup should be done in the C# code */
957 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
958 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
959 table = &assembly->tables [MONO_TABLE_FIELD];
960 fb->table_idx = table->next_idx ++;
961 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
962 name = mono_string_to_utf8 (fb->name);
963 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
965 values [MONO_FIELD_FLAGS] = fb->attrs;
966 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
968 if (fb->offset != -1) {
969 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
971 alloc_table (table, table->rows);
972 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
973 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
974 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
976 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
977 guint32 field_type = 0;
978 table = &assembly->tables [MONO_TABLE_CONSTANT];
980 alloc_table (table, table->rows);
981 values = table->values + table->rows * MONO_CONSTANT_SIZE;
982 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
983 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
984 values [MONO_CONSTANT_TYPE] = field_type;
985 values [MONO_CONSTANT_PADDING] = 0;
989 table = &assembly->tables [MONO_TABLE_FIELDRVA];
991 alloc_table (table, table->rows);
992 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
993 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
995 * We store it in the code section because it's simpler for now.
997 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
998 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1000 if (fb->marshal_info) {
1001 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1003 alloc_table (table, table->rows);
1004 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1005 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1006 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1011 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
1015 char *b = blob_size;
1016 guint32 nparams = 0;
1017 MonoReflectionMethodBuilder *mb = fb->get_method;
1018 guint32 idx, i, size;
1020 if (mb && mb->parameters)
1021 nparams = mono_array_length (mb->parameters);
1022 size = 24 + nparams * 10;
1023 buf = p = g_malloc (size);
1026 mono_metadata_encode_value (nparams, p, &p);
1028 encode_reflection_type (assembly, mb->rtype, p, &p);
1029 for (i = 0; i < nparams; ++i) {
1030 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1031 encode_reflection_type (assembly, pt, p, &p);
1034 *p++ = 1; /* void: a property should probably not be allowed without a getter */
1037 g_assert (p - buf < size);
1038 mono_metadata_encode_value (p-buf, b, &b);
1039 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1040 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
1046 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
1048 MonoDynamicTable *table;
1051 guint num_methods = 0;
1055 * we need to set things in the following tables:
1056 * PROPERTYMAP (info already filled in _get_type_info ())
1057 * PROPERTY (rows already preallocated in _get_type_info ())
1058 * METHOD (method info already done with the generic method code)
1061 table = &assembly->tables [MONO_TABLE_PROPERTY];
1062 pb->table_idx = table->next_idx ++;
1063 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1064 name = mono_string_to_utf8 (pb->name);
1065 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1067 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1068 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1070 /* FIXME: we still don't handle 'other' methods */
1071 if (pb->get_method) num_methods ++;
1072 if (pb->set_method) num_methods ++;
1074 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1075 table->rows += num_methods;
1076 alloc_table (table, table->rows);
1078 if (pb->get_method) {
1079 semaidx = table->next_idx ++;
1080 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1081 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1082 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1083 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1085 if (pb->set_method) {
1086 semaidx = table->next_idx ++;
1087 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1088 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1089 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1090 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1095 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
1097 MonoDynamicTable *table;
1100 guint num_methods = 0;
1104 * we need to set things in the following tables:
1105 * EVENTMAP (info already filled in _get_type_info ())
1106 * EVENT (rows already preallocated in _get_type_info ())
1107 * METHOD (method info already done with the generic method code)
1110 table = &assembly->tables [MONO_TABLE_EVENT];
1111 eb->table_idx = table->next_idx ++;
1112 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1113 name = mono_string_to_utf8 (eb->name);
1114 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1116 values [MONO_EVENT_FLAGS] = eb->attrs;
1117 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1120 * FIXME: we still don't handle 'other' methods
1122 if (eb->add_method) num_methods ++;
1123 if (eb->remove_method) num_methods ++;
1124 if (eb->raise_method) num_methods ++;
1126 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1127 table->rows += num_methods;
1128 alloc_table (table, table->rows);
1130 if (eb->add_method) {
1131 semaidx = table->next_idx ++;
1132 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1133 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1134 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1135 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1137 if (eb->remove_method) {
1138 semaidx = table->next_idx ++;
1139 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1140 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1141 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1142 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1144 if (eb->raise_method) {
1145 semaidx = table->next_idx ++;
1146 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1147 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1148 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1149 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1154 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
1156 MonoDynamicTable *table;
1159 guint32 cols [MONO_ASSEMBLY_SIZE];
1161 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1164 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1166 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1167 token = table->next_idx ++;
1169 alloc_table (table, table->rows);
1170 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1171 if (strcmp ("corlib", image->assembly_name) == 0)
1172 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1174 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1175 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1176 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1177 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1178 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1179 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1180 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1181 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1182 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1184 token <<= RESOLTION_SCOPE_BITS;
1185 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1186 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1191 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1193 MonoDynamicTable *table;
1199 char *b = blob_size;
1201 switch (type->type) {
1202 case MONO_TYPE_FNPTR:
1204 case MONO_TYPE_SZARRAY:
1205 case MONO_TYPE_ARRAY:
1206 encode_type (assembly, type, p, &p);
1212 g_assert (p-sig < 128);
1213 mono_metadata_encode_value (p-sig, b, &b);
1214 token = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1215 mono_image_add_stream_data (&assembly->blob, sig, p-sig);
1217 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1218 alloc_table (table, table->rows + 1);
1219 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1220 values [MONO_TYPESPEC_SIGNATURE] = token;
1222 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1223 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1229 * Despite the name, we handle also TypeSpec (with the above helper).
1232 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1234 MonoDynamicTable *table;
1236 guint32 token, scope, enclosing;
1239 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1242 token = create_typespec (assembly, type);
1245 klass = mono_class_from_mono_type (type);
1247 * If it's in the same module:
1249 if (klass->image == assembly->assembly.image) {
1250 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1251 return TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1254 if (klass->nested_in) {
1255 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1256 /* get the typeref idx of the enclosing type */
1257 enclosing >>= TYPEDEFORREF_BITS;
1258 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1260 scope = resolution_scope_from_image (assembly, klass->image);
1262 table = &assembly->tables [MONO_TABLE_TYPEREF];
1263 alloc_table (table, table->rows + 1);
1264 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1265 values [MONO_TYPEREF_SCOPE] = scope;
1266 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1267 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1268 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1269 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1275 * Insert a memberef row into the metadata: the token that point to the memberref
1276 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1277 * mono_image_get_fieldref_token()).
1278 * The sig param is an index to an already built signature.
1281 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1283 MonoDynamicTable *table;
1285 guint32 token, pclass;
1288 parent = mono_image_typedef_or_ref (assembly, type);
1289 switch (parent & TYPEDEFORREF_MASK) {
1290 case TYPEDEFORREF_TYPEREF:
1291 pclass = MEMBERREF_PARENT_TYPEREF;
1293 case TYPEDEFORREF_TYPESPEC:
1294 pclass = MEMBERREF_PARENT_TYPESPEC;
1296 case TYPEDEFORREF_TYPEDEF:
1297 /* should never get here */
1299 g_error ("unknow typeref or def token");
1301 /* extract the index */
1302 parent >>= TYPEDEFORREF_BITS;
1304 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1305 alloc_table (table, table->rows + 1);
1306 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1307 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1308 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1309 values [MONO_MEMBERREF_SIGNATURE] = sig;
1310 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1317 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1321 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1324 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1325 method->name, method_encode_signature (assembly, method->signature));
1326 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1331 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1335 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1338 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
1339 field->name, fieldref_encode_signature (assembly, field));
1340 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1345 reflection_cc_to_file (int call_conv) {
1346 switch (call_conv & 0x3) {
1348 case 1: return MONO_CALL_DEFAULT;
1349 case 2: return MONO_CALL_VARARG;
1351 g_assert_not_reached ();
1358 MonoMethodSignature *sig;
1364 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1369 MonoMethodSignature *sig;
1372 name = mono_string_to_utf8 (m->name);
1373 nparams = mono_array_length (m->parameters);
1374 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1376 sig->call_convention = reflection_cc_to_file (m->call_conv);
1377 sig->param_count = nparams;
1378 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1379 for (i = 0; i < nparams; ++i) {
1380 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1381 sig->params [i] = t->type;
1384 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1386 if (strcmp (name, am->name) == 0 &&
1387 mono_metadata_type_equal (am->parent, m->parent->type) &&
1388 mono_metadata_signature_equal (am->sig, sig)) {
1394 am = g_new0 (ArrayMethod, 1);
1397 am->parent = m->parent->type;
1398 am->token = mono_image_get_memberref_token (assembly, am->parent,
1399 name, method_encode_signature (assembly, sig));
1400 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1401 m->table_idx = am->token & 0xffffff;
1406 * Insert into the metadata tables all the info about the TypeBuilder tb.
1407 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1410 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1412 MonoDynamicTable *table;
1417 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1418 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1419 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1420 if (tb->parent) { /* interfaces don't have a parent */
1421 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1423 values [MONO_TYPEDEF_EXTENDS] = 0;
1424 n = mono_string_to_utf8 (tb->name);
1425 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1427 n = mono_string_to_utf8 (tb->nspace);
1428 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1430 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1431 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1434 * if we have explicitlayout or sequentiallayouts, output data in the
1435 * ClassLayout table.
1437 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1438 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1440 alloc_table (table, table->rows);
1441 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1442 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1443 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1444 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1447 /* handle interfaces */
1448 if (tb->interfaces) {
1449 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1451 table->rows += mono_array_length (tb->interfaces);
1452 alloc_table (table, table->rows);
1453 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1454 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1455 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1456 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1457 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1458 values += MONO_INTERFACEIMPL_SIZE;
1464 table = &assembly->tables [MONO_TABLE_FIELD];
1465 table->rows += mono_array_length (tb->fields);
1466 alloc_table (table, table->rows);
1467 for (i = 0; i < mono_array_length (tb->fields); ++i)
1468 mono_image_get_field_info (
1469 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1472 /* handle constructors */
1474 table = &assembly->tables [MONO_TABLE_METHOD];
1475 table->rows += mono_array_length (tb->ctors);
1476 alloc_table (table, table->rows);
1477 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1478 mono_image_get_ctor_info (domain,
1479 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1482 /* handle methods */
1484 table = &assembly->tables [MONO_TABLE_METHOD];
1485 table->rows += mono_array_length (tb->methods);
1486 alloc_table (table, table->rows);
1487 for (i = 0; i < mono_array_length (tb->methods); ++i)
1488 mono_image_get_method_info (
1489 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1492 /* Do the same with properties etc.. */
1493 if (tb->events && mono_array_length (tb->events)) {
1494 table = &assembly->tables [MONO_TABLE_EVENT];
1495 table->rows += mono_array_length (tb->events);
1496 alloc_table (table, table->rows);
1497 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1499 alloc_table (table, table->rows);
1500 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1501 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1502 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1503 for (i = 0; i < mono_array_length (tb->events); ++i)
1504 mono_image_get_event_info (
1505 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1507 if (tb->properties && mono_array_length (tb->properties)) {
1508 table = &assembly->tables [MONO_TABLE_PROPERTY];
1509 table->rows += mono_array_length (tb->properties);
1510 alloc_table (table, table->rows);
1511 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1513 alloc_table (table, table->rows);
1514 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1515 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1516 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1517 for (i = 0; i < mono_array_length (tb->properties); ++i)
1518 mono_image_get_property_info (
1519 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1522 MonoDynamicTable *ntable;
1524 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1525 table->rows += mono_array_length (tb->subtypes);
1526 alloc_table (table, table->rows);
1528 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1529 ntable->rows += mono_array_length (tb->subtypes);
1530 alloc_table (ntable, ntable->rows);
1531 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1533 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1534 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1536 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1537 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1538 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1539 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1540 mono_string_to_utf8 (tb->name), tb->table_idx,
1541 ntable->next_idx, ntable->rows);*/
1542 values += MONO_NESTED_CLASS_SIZE;
1545 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1546 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1548 mono_image_get_type_info (domain, subtype, assembly);
1554 assign_type_idx (MonoReflectionTypeBuilder *type, MonoDynamicTable *table)
1558 type->table_idx = table->next_idx ++;
1559 if (!type->subtypes)
1561 for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1562 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1563 assign_type_idx (subtype, table);
1568 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
1573 for (i = 0; i < mono_array_length (pinfo); ++i) {
1574 MonoReflectionParamBuilder *pb;
1575 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
1578 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
1583 type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
1586 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1588 for (i = 0; i < mono_array_length (tb->fields); ++i) {
1589 MonoReflectionFieldBuilder* fb;
1590 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
1591 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
1595 for (i = 0; i < mono_array_length (tb->events); ++i) {
1596 MonoReflectionEventBuilder* eb;
1597 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
1598 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1601 if (tb->properties) {
1602 for (i = 0; i < mono_array_length (tb->properties); ++i) {
1603 MonoReflectionPropertyBuilder* pb;
1604 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
1605 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
1609 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
1610 MonoReflectionCtorBuilder* cb;
1611 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
1612 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
1613 params_add_cattrs (assembly, cb->pinfo);
1618 for (i = 0; i < mono_array_length (tb->methods); ++i) {
1619 MonoReflectionMethodBuilder* mb;
1620 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
1621 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
1622 params_add_cattrs (assembly, mb->pinfo);
1627 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
1628 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
1633 module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
1636 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1638 for (i = 0; i < mono_array_length (mb->types); ++i)
1639 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
1643 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1645 MonoDynamicTable *table;
1649 table = &assembly->tables [MONO_TABLE_MODULE];
1650 mb->table_idx = table->next_idx ++;
1651 name = mono_string_to_utf8 (mb->module.name);
1652 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1654 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1657 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1658 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1659 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1662 * fill-in info in other tables as well.
1664 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1665 table->rows += mono_array_length (mb->types);
1666 alloc_table (table, table->rows);
1668 * We assign here the typedef indexes to avoid mismatches if a type that
1669 * has not yet been stored in the tables is referenced by another type.
1671 for (i = 0; i < mono_array_length (mb->types); ++i) {
1672 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1673 assign_type_idx (type, table);
1675 for (i = 0; i < mono_array_length (mb->types); ++i)
1676 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1679 #define align_pointer(base,p)\
1681 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1683 (p) += 4 - (__diff & 3);\
1687 compare_semantics (const void *a, const void *b)
1689 const guint32 *a_values = a;
1690 const guint32 *b_values = b;
1691 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
1694 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
1698 compare_custom_attrs (const void *a, const void *b)
1700 const guint32 *a_values = a;
1701 const guint32 *b_values = b;
1703 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
1707 compare_field_marshal (const void *a, const void *b)
1709 const guint32 *a_values = a;
1710 const guint32 *b_values = b;
1712 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
1716 compare_nested (const void *a, const void *b)
1718 const guint32 *a_values = a;
1719 const guint32 *b_values = b;
1721 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
1725 * build_compressed_metadata() fills in the blob of data that represents the
1726 * raw metadata as it will be saved in the PE file. The five streams are output
1727 * and the metadata tables are comnpressed from the guint32 array representation,
1728 * to the compressed on-disk format.
1731 build_compressed_metadata (MonoDynamicAssembly *assembly)
1733 MonoDynamicTable *table;
1735 guint64 valid_mask = 0;
1736 guint64 sorted_mask;
1737 guint32 heapt_size = 0;
1738 guint32 meta_size = 256; /* allow for header and other stuff */
1739 guint32 table_offset;
1740 guint32 ntables = 0;
1747 * We need to use the current ms version or the ms runtime it won't find
1748 * the support dlls. D'oh!
1749 * const char *version = "mono-" VERSION;
1751 const char *version = "v1.0.3705";
1754 MonoDynamicStream *stream;
1755 } stream_desc [] = {
1756 {"#~", &assembly->tstream},
1757 {"#Strings", &assembly->sheap},
1758 {"#US", &assembly->us},
1759 {"#Blob", &assembly->blob},
1760 {"#GUID", &assembly->guid}
1763 /* tables that are sorted */
1764 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
1765 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
1766 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
1767 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
1768 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
1769 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
1771 /* Compute table sizes */
1772 /* the MonoImage has already been created in mono_image_basic_init() */
1773 meta = assembly->assembly.image;
1775 /* Setup the info used by compute_sizes () */
1776 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1777 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1778 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1780 meta_size += assembly->blob.index;
1781 meta_size += assembly->guid.index;
1782 meta_size += assembly->sheap.index;
1783 meta_size += assembly->us.index;
1785 for (i=0; i < 64; ++i)
1786 meta->tables [i].rows = assembly->tables [i].rows;
1788 for (i = 0; i < 64; i++){
1789 if (meta->tables [i].rows == 0)
1791 valid_mask |= (guint64)1 << i;
1793 meta->tables [i].row_size = mono_metadata_compute_size (
1794 meta, i, &meta->tables [i].size_bitfield);
1795 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1797 heapt_size += 24; /* #~ header size */
1798 heapt_size += ntables * 4;
1799 meta_size += heapt_size;
1800 meta->raw_metadata = g_malloc0 (meta_size);
1801 p = meta->raw_metadata;
1802 /* the metadata signature */
1803 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1804 /* version numbers and 4 bytes reserved */
1805 int16val = (guint16*)p;
1806 *int16val++ = GUINT16_TO_LE (1);
1807 *int16val = GUINT16_TO_LE (1);
1809 /* version string */
1810 int32val = (guint32*)p;
1811 *int32val = GUINT32_TO_LE ((strlen (version) + 3) & (~3)); /* needs to be multiple of 4 */
1813 memcpy (p, version, GUINT32_FROM_LE (*int32val));
1814 p += GUINT32_FROM_LE (*int32val);
1815 align_pointer (meta->raw_metadata, p);
1816 int16val = (guint16*)p;
1817 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
1818 *int16val = GUINT16_TO_LE (5); /* number of streams */
1822 * write the stream info.
1824 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1825 table_offset += 3; table_offset &= ~3;
1827 assembly->tstream.index = heapt_size;
1828 for (i = 0; i < 5; ++i) {
1829 int32val = (guint32*)p;
1830 stream_desc [i].stream->offset = table_offset;
1831 *int32val++ = GUINT32_TO_LE (table_offset);
1832 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
1833 table_offset += GUINT32_FROM_LE (*int32val);
1834 table_offset += 3; table_offset &= ~3;
1836 strcpy (p, stream_desc [i].name);
1837 p += strlen (stream_desc [i].name) + 1;
1838 align_pointer (meta->raw_metadata, p);
1841 * now copy the data, the table stream header and contents goes first.
1843 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1844 p = meta->raw_metadata + assembly->tstream.offset;
1845 int32val = (guint32*)p;
1846 *int32val = GUINT32_TO_LE (0); /* reserved */
1848 *p++ = 1; /* version */
1850 if (meta->idx_string_wide)
1852 if (meta->idx_guid_wide)
1854 if (meta->idx_blob_wide)
1857 *p++ = 0; /* reserved */
1858 int64val = (guint64*)p;
1859 *int64val++ = GUINT64_TO_LE (valid_mask);
1860 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
1862 int32val = (guint32*)p;
1863 for (i = 0; i < 64; i++){
1864 if (meta->tables [i].rows == 0)
1866 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
1868 p = (unsigned char*)int32val;
1870 /* sort the tables that still need sorting */
1871 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1873 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
1874 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1876 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
1877 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1879 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
1880 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1882 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
1884 /* compress the tables */
1885 for (i = 0; i < 64; i++){
1888 guint32 bitfield = meta->tables [i].size_bitfield;
1889 if (!meta->tables [i].rows)
1891 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1892 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1893 meta->tables [i].base = p;
1894 for (row = 1; row <= meta->tables [i].rows; ++row) {
1895 values = assembly->tables [i].values + row * assembly->tables [i].columns;
1896 for (col = 0; col < assembly->tables [i].columns; ++col) {
1897 switch (mono_metadata_table_size (bitfield, col)) {
1899 *p++ = values [col];
1902 int16val = (guint16*)p;
1903 *int16val = GUINT16_TO_LE (values [col]);
1907 int32val = (guint32*)p;
1908 *int32val = GUINT32_TO_LE (values [col]);
1912 g_assert_not_reached ();
1916 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1919 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1920 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1921 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1922 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1923 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1925 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1929 * Some tables in metadata need to be sorted according to some criteria, but
1930 * when methods and fields are first created with reflection, they may be assigned a token
1931 * that doesn't correspond to the final token they will get assigned after the sorting.
1932 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
1933 * with the reflection objects that represent them. Once all the tables are set up, the
1934 * reflection objects will contains the correct table index. fixup_method() will fixup the
1935 * tokens for the method with ILGenerator @ilgen.
1938 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
1939 guint32 code_idx = GPOINTER_TO_UINT (value);
1940 MonoReflectionILTokenInfo *iltoken;
1941 MonoReflectionFieldBuilder *field;
1942 MonoReflectionCtorBuilder *ctor;
1943 MonoReflectionMethodBuilder *method;
1945 unsigned char *target;
1947 for (i = 0; i < ilgen->num_token_fixups; ++i) {
1948 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
1949 target = assembly->code.data + code_idx + iltoken->code_pos;
1950 switch (target [3]) {
1951 case MONO_TABLE_FIELD:
1952 if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
1953 g_assert_not_reached ();
1954 field = (MonoReflectionFieldBuilder *)iltoken->member;
1955 idx = field->table_idx;
1957 case MONO_TABLE_METHOD:
1958 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1959 method = (MonoReflectionMethodBuilder *)iltoken->member;
1960 idx = method->table_idx;
1961 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1962 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
1963 idx = ctor->table_idx;
1965 g_assert_not_reached ();
1969 g_error ("got unexpected table 0x%02x in fixup", target [3]);
1971 target [0] = idx & 0xff;
1972 target [1] = (idx >> 8) & 0xff;
1973 target [2] = (idx >> 16) & 0xff;
1978 * mono_image_build_metadata() will fill the info in all the needed metadata tables
1979 * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
1980 * and recursively outputs the info for a module. Each module will output all the info
1981 * about it's types etc.
1982 * At the end of the process, method and field tokens are fixed up and the on-disk
1983 * compressed metadata representation is created.
1986 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
1988 MonoDynamicTable *table;
1989 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
1990 MonoDomain *domain = ((MonoObject *)assemblyb)->vtable->domain;
1996 assembly->text_rva = START_TEXT_RVA;
1998 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
1999 alloc_table (table, 1);
2000 values = table->values + MONO_ASSEMBLY_SIZE;
2001 values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
2002 name = mono_string_to_utf8 (assemblyb->name);
2003 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
2005 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2006 values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
2007 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
2008 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
2009 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
2010 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
2011 values [MONO_ASSEMBLY_FLAGS] = 0;
2013 assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
2014 assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
2016 if (assemblyb->modules) {
2017 len = mono_array_length (assemblyb->modules);
2018 table = &assembly->tables [MONO_TABLE_MODULE];
2019 alloc_table (table, len);
2020 for (i = 0; i < len; ++i)
2021 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
2023 table = &assembly->tables [MONO_TABLE_MODULE];
2025 alloc_table (table, table->rows);
2026 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
2030 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2032 * table->rows is already set above and in mono_image_fill_module_table.
2034 alloc_table (table, table->rows);
2036 * Set the first entry.
2038 values = table->values + table->columns;
2039 values [MONO_TYPEDEF_FLAGS] = 0;
2040 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2041 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2042 values [MONO_TYPEDEF_EXTENDS] = 0;
2043 values [MONO_TYPEDEF_FIELD_LIST] = 1;
2044 values [MONO_TYPEDEF_METHOD_LIST] = 1;
2046 /* add all the custom attributes at the end, once all the indexes are stable */
2047 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
2049 if (assemblyb->modules) {
2050 len = mono_array_length (assemblyb->modules);
2051 for (i = 0; i < len; ++i)
2052 module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
2056 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2058 build_compressed_metadata (assembly);
2062 * mono_image_insert_string:
2063 * @assembly: assembly builder object
2066 * Insert @str into the user string stream of @assembly.
2069 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
2075 if (!assembly->dynamic_assembly)
2076 mono_image_basic_init (assembly);
2077 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
2078 idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
2079 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2081 char *swapped = g_malloc (2 * mono_string_length (str));
2082 const char *p = (const char*)mono_string_chars (str);
2084 swap_with_size (swapped, p, 2, mono_string_length (str));
2085 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2089 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2091 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2092 return MONO_TOKEN_STRING | idx;
2096 * mono_image_create_token:
2097 * @assembly: a dynamic assembly
2100 * Get a token to insert in the IL code stream for the given MemberInfo.
2101 * @obj can be one of:
2102 * ConstructorBuilder
2112 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2118 g_error ("System.Array methods not yet supported");
2120 klass = obj->vtable->klass;
2121 if (strcmp (klass->name, "MethodBuilder") == 0) {
2122 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2123 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2124 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2127 if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2128 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2129 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2130 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2133 if (strcmp (klass->name, "FieldBuilder") == 0) {
2134 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2135 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
2137 if (strcmp (klass->name, "TypeBuilder") == 0) {
2138 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2139 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
2141 if (strcmp (klass->name, "MonoType") == 0) {
2142 MonoReflectionType *tb = (MonoReflectionType *)obj;
2143 return mono_metadata_token_from_dor (
2144 mono_image_typedef_or_ref (assembly, tb->type));
2146 if (strcmp (klass->name, "MonoCMethod") == 0 ||
2147 strcmp (klass->name, "MonoMethod") == 0) {
2148 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2149 token = mono_image_get_methodref_token (assembly, m->method);
2150 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2153 if (strcmp (klass->name, "MonoField") == 0) {
2154 MonoReflectionField *f = (MonoReflectionField *)obj;
2155 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2156 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2159 if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2160 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2161 token = mono_image_get_array_token (assembly, m);
2164 g_print ("requested token for %s\n", klass->name);
2169 guint32 import_lookup_table;
2173 guint32 import_address_table_rva;
2182 * mono_image_basic_ini:
2183 * @assembly: an assembly builder object
2185 * Create the MonoImage that represents the assembly builder and setup some
2186 * of the helper hash table and the basic metadata streams.
2189 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2191 static const guchar entrycode [16] = {0xff, 0x25, 0};
2192 MonoDynamicAssembly *assembly;
2196 if (assemblyb->dynamic_assembly)
2200 assembly = assemblyb->dynamic_assembly = GC_malloc (sizeof (MonoDynamicAssembly));
2202 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2205 assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2206 assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2207 assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2209 string_heap_init (&assembly->sheap);
2210 mono_image_add_stream_data (&assembly->us, "", 1);
2211 mono_image_add_stream_data (&assembly->blob, "", 1);
2212 /* import tables... */
2213 mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2214 assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2215 assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2216 mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2217 assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2218 mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2219 assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2220 stream_data_align (&assembly->code);
2222 assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2224 for (i=0; i < 64; ++i) {
2225 assembly->tables [i].next_idx = 1;
2226 assembly->tables [i].columns = table_sizes [i];
2229 image = g_new0 (MonoImage, 1);
2231 /* keep in sync with image.c */
2232 image->name = mono_string_to_utf8 (assemblyb->name);
2233 image->assembly_name = image->name; /* they may be different */
2235 image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2236 image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2237 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2238 image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2240 assembly->assembly.image = image;
2245 calc_section_size (MonoDynamicAssembly *assembly)
2249 /* alignment constraints */
2250 assembly->code.index += 3;
2251 assembly->code.index &= ~3;
2252 assembly->meta_size += 3;
2253 assembly->meta_size &= ~3;
2255 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index;
2256 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2259 assembly->sections [MONO_SECTION_RELOC].size = 12;
2260 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2267 * mono_image_create_pefile:
2268 * @assemblyb: an assembly builder object
2270 * When we need to save an assembly, we first call this function that ensures the metadata
2271 * tables are built for all the modules in the assembly. This function creates the PE-COFF
2272 * header, the image sections, the CLI header etc. all the data is written in
2273 * assembly->pefile where it can be easily retrieved later in chunks.
2276 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
2277 MonoMSDOSHeader *msdos;
2278 MonoDotNetHeader *header;
2279 MonoSectionTable *section;
2280 MonoCLIHeader *cli_header;
2281 guint32 size, image_size, virtual_base;
2282 guint32 header_start, section_start, file_offset, virtual_offset;
2283 MonoDynamicAssembly *assembly;
2284 MonoDynamicStream *pefile;
2288 static const unsigned char msheader[] = {
2289 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2290 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2293 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2294 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2295 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2296 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2299 mono_image_basic_init (assemblyb);
2300 assembly = assemblyb->dynamic_assembly;
2302 /* already created */
2303 if (assembly->pefile.index)
2306 mono_image_build_metadata (assemblyb);
2307 nsections = calc_section_size (assembly);
2309 pefile = &assembly->pefile;
2311 /* The DOS header and stub */
2312 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2313 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
2315 /* the dotnet header */
2316 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2318 /* the section tables */
2319 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2321 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2322 virtual_offset = VIRT_ALIGN;
2325 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2326 if (!assembly->sections [i].size)
2329 file_offset += FILE_ALIGN - 1;
2330 file_offset &= ~(FILE_ALIGN - 1);
2331 virtual_offset += VIRT_ALIGN - 1;
2332 virtual_offset &= ~(VIRT_ALIGN - 1);
2334 assembly->sections [i].offset = file_offset;
2335 assembly->sections [i].rva = virtual_offset;
2337 file_offset += assembly->sections [i].size;
2338 virtual_offset += assembly->sections [i].size;
2339 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2342 file_offset += FILE_ALIGN - 1;
2343 file_offset &= ~(FILE_ALIGN - 1);
2344 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
2346 image_size += section_start + sizeof (MonoSectionTable) * nsections;
2348 /* back-patch info */
2349 msdos = (MonoMSDOSHeader*)pefile->data;
2350 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
2351 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
2352 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2354 header = (MonoDotNetHeader*)(pefile->data + header_start);
2355 header->pesig [0] = 'P';
2356 header->pesig [1] = 'E';
2358 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
2359 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2360 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2361 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2363 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2364 /* FIXME: it's a dll */
2365 /*header->coff.coff_attributes = GUINT16_FROM_LE (0x210e); */
2367 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2369 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2370 header->pe.pe_major = 6;
2371 header->pe.pe_minor = 0;
2372 size = assembly->sections [MONO_SECTION_TEXT].size;
2373 size += FILE_ALIGN - 1;
2374 size &= ~(FILE_ALIGN - 1);
2375 header->pe.pe_code_size = size;
2376 size = assembly->sections [MONO_SECTION_RSRC].size;
2377 size += FILE_ALIGN - 1;
2378 size &= ~(FILE_ALIGN - 1);
2379 header->pe.pe_data_size = size;
2380 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2381 header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
2382 header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
2383 /* pe_rva_entry_point always at the beginning of the text section */
2384 header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
2386 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2387 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2388 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2389 header->nt.pe_os_major = GUINT16_FROM_LE (4);
2390 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2391 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2392 size = section_start;
2393 size += FILE_ALIGN - 1;
2394 size &= ~(FILE_ALIGN - 1);
2395 header->nt.pe_header_size = GUINT32_FROM_LE (size);
2397 size += VIRT_ALIGN - 1;
2398 size &= ~(VIRT_ALIGN - 1);
2399 header->nt.pe_image_size = GUINT32_FROM_LE (size);
2400 header->nt.pe_subsys_required = GUINT16_FROM_LE (3); /* 3 -> cmdline app, 2 -> GUI app */
2401 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2402 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2403 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2404 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2405 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2406 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2408 /* fill data directory entries */
2410 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2411 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2413 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2414 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2416 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2417 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2418 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2419 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2420 /* patch imported function RVA name */
2421 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2422 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2424 /* the import table */
2425 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2426 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2427 /* patch imported dll RVA name and other entries in the dir */
2428 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2429 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
2430 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2431 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2432 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2433 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2435 rva = (guint32*)(assembly->code.data + assembly->ilt_offset);
2436 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset - 2);
2438 /* the CLI header info */
2439 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2440 cli_header->ch_size = GUINT32_FROM_LE (72);
2441 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
2442 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
2443 if (assemblyb->entry_point)
2444 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
2446 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
2447 cli_header->ch_metadata.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->code.index);
2448 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
2450 /* write the section tables and section content */
2451 section = (MonoSectionTable*)(pefile->data + section_start);
2452 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2453 static const char *section_names [] = {
2454 ".text", ".rsrc", ".reloc"
2456 if (!assembly->sections [i].size)
2458 strcpy (section->st_name, section_names [i]);
2459 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
2460 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
2461 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
2462 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
2463 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
2464 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
2465 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
2467 case MONO_SECTION_TEXT:
2468 /* patch entry point */
2469 rva = (guint32*)(assembly->code.data + 2);
2470 *rva = GUINT32_FROM_LE (virtual_base + assembly->text_rva + assembly->iat_offset);
2471 memcpy (pefile->data + assembly->sections [i].offset, assembly->code.data, assembly->code.index);
2472 memcpy (pefile->data + assembly->sections [i].offset + assembly->code.index, assembly->assembly.image->raw_metadata, assembly->meta_size);
2474 case MONO_SECTION_RELOC:
2475 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
2476 *rva = GUINT32_FROM_LE (assembly->text_rva);
2478 *rva = GUINT32_FROM_LE (12);
2480 data16 = (guint16*)rva;
2482 * the entrypoint is always at the start of the text section
2483 * 3 is IMAGE_REL_BASED_HIGHLOW
2484 * 2 is patch_size_rva - text_rva
2486 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
2488 *data16 = 0; /* terminate */
2490 case MONO_SECTION_RSRC:
2492 g_assert_not_reached ();
2497 /* check that the file is properly padded */
2500 FILE *f = fopen ("mypetest.exe", "w");
2501 fwrite (pefile->data, pefile->index, 1, f);
2508 * We need to return always the same object for MethodInfo, FieldInfo etc..
2509 * type uses a different hash, since it uses custom hash/equal functions.
2511 static MonoGHashTable *object_cache = NULL;
2512 static MonoGHashTable *type_cache = NULL;
2514 #define CHECK_OBJECT(t,p) \
2517 if (!object_cache) \
2518 object_cache = mono_g_hash_table_new (g_direct_hash, g_direct_equal); \
2519 if ((_obj = mono_g_hash_table_lookup (object_cache, (p)))) \
2523 #define CACHE_OBJECT(p,o) \
2525 mono_g_hash_table_insert (object_cache, p,o); \
2529 * mono_assembly_get_object:
2530 * @domain: an app domain
2531 * @assembly: an assembly
2533 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
2535 MonoReflectionAssembly*
2536 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
2538 static MonoClass *System_Reflection_Assembly;
2539 MonoReflectionAssembly *res;
2541 CHECK_OBJECT (MonoReflectionAssembly *, assembly);
2542 if (!System_Reflection_Assembly)
2543 System_Reflection_Assembly = mono_class_from_name (
2544 mono_defaults.corlib, "System.Reflection", "Assembly");
2545 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
2546 res->assembly = assembly;
2547 CACHE_OBJECT (assembly, res);
2552 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
2554 if ((t1->type != t2->type) ||
2555 (t1->byref != t2->byref))
2559 case MONO_TYPE_VOID:
2560 case MONO_TYPE_BOOLEAN:
2561 case MONO_TYPE_CHAR:
2572 case MONO_TYPE_STRING:
2575 case MONO_TYPE_OBJECT:
2577 case MONO_TYPE_VALUETYPE:
2578 case MONO_TYPE_CLASS:
2579 return t1->data.klass == t2->data.klass;
2581 case MONO_TYPE_SZARRAY:
2582 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
2583 case MONO_TYPE_ARRAY:
2584 if (t1->data.array->rank != t2->data.array->rank)
2586 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
2588 g_error ("implement type compare for %0x!", t1->type);
2596 mymono_metadata_type_hash (MonoType *t1)
2602 hash |= t1->byref << 6; /* do not collide with t1->type values */
2604 case MONO_TYPE_VALUETYPE:
2605 case MONO_TYPE_CLASS:
2606 /* check if the distribution is good enough */
2607 return hash << 7 | g_str_hash (t1->data.klass->name);
2609 case MONO_TYPE_SZARRAY:
2610 return hash << 7 | mymono_metadata_type_hash (t1->data.type);
2616 * mono_type_get_object:
2617 * @domain: an app domain
2620 * Return an System.MonoType object representing the type @type.
2623 mono_type_get_object (MonoDomain *domain, MonoType *type)
2625 MonoReflectionType *res;
2626 MonoClass *klass = mono_class_from_mono_type (type);
2629 type_cache = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
2630 (GCompareFunc)mymono_metadata_type_equal);
2631 if ((res = mono_g_hash_table_lookup (type_cache, type)))
2633 if (klass->reflection_info) {
2634 /* should this be considered an error condition? */
2636 return klass->reflection_info;
2638 mono_class_init (klass);
2639 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
2641 mono_g_hash_table_insert (type_cache, type, res);
2646 * mono_method_get_object:
2647 * @domain: an app domain
2650 * Return an System.Reflection.MonoMethod object representing the method @method.
2652 MonoReflectionMethod*
2653 mono_method_get_object (MonoDomain *domain, MonoMethod *method)
2656 * We use the same C representation for methods and constructors, but the type
2657 * name in C# is different.
2661 MonoReflectionMethod *ret;
2663 CHECK_OBJECT (MonoReflectionMethod *, method);
2664 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
2665 cname = "MonoCMethod";
2667 cname = "MonoMethod";
2668 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
2670 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
2671 ret->method = method;
2672 ret->name = mono_string_new (domain, method->name);
2673 CACHE_OBJECT (method, ret);
2678 * mono_field_get_object:
2679 * @domain: an app domain
2683 * Return an System.Reflection.MonoField object representing the field @field
2686 MonoReflectionField*
2687 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
2689 MonoReflectionField *res;
2692 CHECK_OBJECT (MonoReflectionField *, field);
2693 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
2694 res = (MonoReflectionField *)mono_object_new (domain, oklass);
2697 CACHE_OBJECT (field, res);
2702 * mono_property_get_object:
2703 * @domain: an app domain
2705 * @property: a property
2707 * Return an System.Reflection.MonoProperty object representing the property @property
2710 MonoReflectionProperty*
2711 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
2713 MonoReflectionProperty *res;
2716 CHECK_OBJECT (MonoReflectionProperty *, property);
2717 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
2718 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
2720 res->property = property;
2721 CACHE_OBJECT (property, res);
2726 * mono_event_get_object:
2727 * @domain: an app domain
2731 * Return an System.Reflection.MonoEvent object representing the event @event
2734 MonoReflectionEvent*
2735 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
2737 MonoReflectionEvent *res;
2740 CHECK_OBJECT (MonoReflectionEvent *, event);
2741 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
2742 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
2745 CACHE_OBJECT (event, res);
2750 * mono_param_get_objects:
2751 * @domain: an app domain
2754 * Return an System.Reflection.ParameterInfo array object representing the parameters
2755 * in the method @method.
2757 MonoReflectionParameter**
2758 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
2760 MonoReflectionParameter **res;
2761 MonoReflectionMethod *member;
2766 if (!method->signature->param_count)
2769 member = mono_method_get_object (domain, method);
2770 names = g_new (char *, method->signature->param_count);
2771 mono_method_get_param_names (method, (const char **) names);
2773 /* Note: the cache is based on the address of the signature into the method
2774 * since we already cache MethodInfos with the method as keys.
2776 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature));
2777 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
2779 res = GC_malloc (sizeof (MonoReflectionParameter*) * method->signature->param_count);
2781 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
2783 for (i = 0; i < method->signature->param_count; ++i) {
2784 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
2785 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
2786 res [i]->DefaultValueImpl = NULL; /* FIXME */
2787 res [i]->MemberImpl = (MonoObject*)member;
2788 res [i]->NameImpl = mono_string_new (domain, names [i]);
2789 res [i]->PositionImpl = i + 1;
2790 res [i]->AttrsImpl = method->signature->params [i]->attrs;
2793 CACHE_OBJECT (&(method->signature), res);
2798 * mono_reflection_parse_type:
2801 * Parse a type name as accepted by the GetType () method and output the info
2802 * extracted in the info structure.
2803 * the name param will be mangled, so, make a copy before passing it to this function.
2804 * The fields in info will be valid until the memory pointed to by name is valid.
2805 * Returns 0 on parse error.
2806 * See also mono_type_get_name () below.
2809 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
2811 char *start, *p, *w, *last_point, *startn;
2812 int in_modifiers = 0;
2813 int isbyref = 0, rank;
2815 start = p = w = name;
2817 info->name = info->name_space = info->assembly = NULL;
2818 info->nested = NULL;
2819 info->modifiers = NULL;
2821 /* last_point separates the namespace from the name */
2827 *p = 0; /* NULL terminate the name */
2829 /* we have parsed the nesting namespace + name */
2831 info->nested = g_list_append (info->nested, startn);
2835 info->name_space = start;
2837 info->name = last_point + 1;
2839 info->name_space = (char *)"";
2864 info->nested = g_list_append (info->nested, startn);
2867 info->name_space = start;
2869 info->name = last_point + 1;
2871 info->name_space = (char *)"";
2878 if (isbyref) /* only one level allowed by the spec */
2881 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
2885 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
2896 else if (*p != '*') /* '*' means unknown lower bound */
2902 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
2914 return 0; /* missing assembly name */
2923 *w = 0; /* terminate class name */
2924 if (!info->name || !*info->name)
2926 /* add other consistency checks */
2931 mono_type_get_name_recurse (MonoType *type, GString *str)
2935 switch (type->type) {
2936 case MONO_TYPE_ARRAY: {
2937 int i, rank = type->data.array->rank;
2939 mono_type_get_name_recurse (type->data.array->type, str);
2940 g_string_append_c (str, '[');
2941 for (i = 1; i < rank; i++)
2942 g_string_append_c (str, ',');
2943 g_string_append_c (str, ']');
2946 case MONO_TYPE_SZARRAY:
2947 mono_type_get_name_recurse (type->data.type, str);
2948 g_string_append (str, "[]");
2951 mono_type_get_name_recurse (type->data.type, str);
2952 g_string_append_c (str, '*');
2955 klass = mono_class_from_mono_type (type);
2956 if (klass->nested_in) {
2957 mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
2958 g_string_append_c (str, '+');
2960 if (*klass->name_space) {
2961 g_string_append (str, klass->name_space);
2962 g_string_append_c (str, '.');
2964 g_string_append (str, klass->name);
2970 * mono_type_get_name:
2973 * Returns the string representation for type as required by System.Reflection.
2974 * The inverse of mono_reflection_parse_type ().
2977 mono_type_get_name (MonoType *type)
2979 GString* result = g_string_new ("");
2980 mono_type_get_name_recurse (type, result);
2983 g_string_append_c (result, '&');
2985 return g_string_free (result, FALSE);
2989 * mono_reflection_get_type:
2990 * @image: a metadata context
2991 * @info: type description structure
2992 * @ignorecase: flag for case-insensitive string compares
2994 * Build a MonoType from the type description in @info.
2998 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3005 image = mono_defaults.corlib;
3008 klass = mono_class_from_name_case (image, info->name_space, info->name);
3010 klass = mono_class_from_name (image, info->name_space, info->name);
3013 for (mod = info->nested; mod; mod = mod->next) {
3016 mono_class_init (klass);
3017 nested = klass->nested_classes;
3020 klass = nested->data;
3022 if (g_strcasecmp (klass->name, mod->data) == 0)
3025 if (strcmp (klass->name, mod->data) == 0)
3029 nested = nested->next;
3036 mono_class_init (klass);
3037 for (mod = info->modifiers; mod; mod = mod->next) {
3038 modval = GPOINTER_TO_UINT (mod->data);
3039 if (!modval) { /* byref: must be last modifier */
3040 return &klass->this_arg;
3041 } else if (modval == -1) {
3042 klass = mono_ptr_class_get (&klass->byval_arg);
3043 } else { /* array rank */
3044 klass = mono_array_class_get (&klass->byval_arg, modval);
3046 mono_class_init (klass);
3048 return &klass->byval_arg;
3052 * Optimization we could avoid mallocing() an little-endian archs that
3053 * don't crash with unaligned accesses.
3056 fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
3057 int len, i, slen, type;
3058 const char *p = mono_metadata_blob_heap (image, blobidx);
3060 len = mono_metadata_decode_value (p, &p);
3061 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
3066 for (i = 0; i < sig->param_count; ++i) {
3067 type = sig->params [i]->type;
3072 case MONO_TYPE_BOOLEAN: {
3073 MonoBoolean *bval = params [i] = g_malloc (sizeof (MonoBoolean));
3078 case MONO_TYPE_CHAR:
3080 case MONO_TYPE_I2: {
3081 guint16 *val = params [i] = g_malloc (sizeof (guint16));
3086 #if SIZEOF_VOID_P == 4
3092 case MONO_TYPE_I4: {
3093 guint32 *val = params [i] = g_malloc (sizeof (guint32));
3098 #if SIZEOF_VOID_P == 8
3099 case MONO_TYPE_U: /* error out instead? this should probably not happen */
3104 case MONO_TYPE_I8: {
3105 guint64 *val = params [i] = g_malloc (sizeof (guint64));
3110 case MONO_TYPE_VALUETYPE:
3111 if (sig->params [i]->data.klass->enumtype) {
3112 type = sig->params [i]->data.klass->enum_basetype->type;
3115 g_warning ("generic valutype %s not handled in custom attr value decoding", sig->params [i]->data.klass->name);
3118 case MONO_TYPE_STRING: {
3119 slen = mono_metadata_decode_value (p, &p);
3120 params [i] = mono_string_new_len (mono_domain_get (), p, slen);
3125 g_warning ("Type %02x not handled in custom attr value decoding", sig->params [i]->type);
3132 free_param_data (MonoMethodSignature *sig, void **params) {
3134 for (i = 0; i < sig->param_count; ++i) {
3135 switch (sig->params [i]->type) {
3136 case MONO_TYPE_BOOLEAN:
3137 case MONO_TYPE_CHAR:
3150 case MONO_TYPE_VALUETYPE:
3151 g_free (params [i]);
3160 * Find the method index in the metadata methodDef table.
3161 * Later put these three helper methods in metadata and export them.
3164 find_method_index (MonoMethod *method) {
3165 MonoClass *klass = method->klass;
3168 for (i = 0; i < klass->method.count; ++i) {
3169 if (method == klass->methods [i])
3170 return klass->method.first + 1 + i;
3176 * Find the field index in the metadata FieldDef table.
3179 find_field_index (MonoClass *klass, MonoClassField *field) {
3182 for (i = 0; i < klass->field.count; ++i) {
3183 if (field == &klass->fields [i])
3184 return klass->field.first + 1 + i;
3190 * Find the property index in the metadata Property table.
3193 find_property_index (MonoClass *klass, MonoProperty *property) {
3196 for (i = 0; i < klass->property.count; ++i) {
3197 if (property == &klass->properties [i])
3198 return klass->property.first + 1 + i;
3204 * Find the event index in the metadata Event table.
3207 find_event_index (MonoClass *klass, MonoEvent *event) {
3210 for (i = 0; i < klass->event.count; ++i) {
3211 if (event == &klass->events [i])
3212 return klass->event.first + 1 + i;
3218 * mono_reflection_get_custom_attrs:
3219 * @obj: a reflection object handle
3221 * Return an array with all the custom attributes defined of the
3222 * reflection handle @obj. The objects are fully build.
3225 mono_reflection_get_custom_attrs (MonoObject *obj)
3227 guint32 idx, mtoken, i, len;
3228 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
3238 klass = obj->vtable->klass;
3239 /* FIXME: need to handle: Module */
3240 if (klass == mono_defaults.monotype_class) {
3241 MonoReflectionType *rtype = (MonoReflectionType*)obj;
3242 klass = mono_class_from_mono_type (rtype->type);
3243 idx = mono_metadata_token_index (klass->type_token);
3244 idx <<= CUSTOM_ATTR_BITS;
3245 idx |= CUSTOM_ATTR_TYPEDEF;
3246 image = klass->image;
3247 } else if (strcmp ("Assembly", klass->name) == 0) {
3248 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
3249 idx = 1; /* there is only one assembly */
3250 idx <<= CUSTOM_ATTR_BITS;
3251 idx |= CUSTOM_ATTR_ASSEMBLY;
3252 image = rassembly->assembly->image;
3253 } else if (strcmp ("MonoProperty", klass->name) == 0) {
3254 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
3255 idx = find_property_index (rprop->klass, rprop->property);
3256 idx <<= CUSTOM_ATTR_BITS;
3257 idx |= CUSTOM_ATTR_PROPERTY;
3258 image = rprop->klass->image;
3259 } else if (strcmp ("MonoEvent", klass->name) == 0) {
3260 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
3261 idx = find_event_index (revent->klass, revent->event);
3262 idx <<= CUSTOM_ATTR_BITS;
3263 idx |= CUSTOM_ATTR_EVENT;
3264 image = revent->klass->image;
3265 } else if (strcmp ("MonoField", klass->name) == 0) {
3266 MonoReflectionField *rfield = (MonoReflectionField*)obj;
3267 idx = find_field_index (rfield->klass, rfield->field);
3268 idx <<= CUSTOM_ATTR_BITS;
3269 idx |= CUSTOM_ATTR_FIELDDEF;
3270 image = rfield->klass->image;
3271 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
3272 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
3273 idx = find_method_index (rmethod->method);
3274 idx <<= CUSTOM_ATTR_BITS;
3275 idx |= CUSTOM_ATTR_METHODDEF;
3276 image = rmethod->method->klass->image;
3277 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
3278 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
3279 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
3280 guint32 method_index = find_method_index (rmethod->method);
3281 guint32 param_list, param_last, param_pos, found;
3283 image = rmethod->method->klass->image;
3284 ca = &image->tables [MONO_TABLE_METHOD];
3286 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
3287 if (method_index == ca->rows) {
3288 ca = &image->tables [MONO_TABLE_PARAM];
3289 param_last = ca->rows + 1;
3291 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
3292 ca = &image->tables [MONO_TABLE_PARAM];
3295 for (i = param_list; i < param_last; ++i) {
3296 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
3297 if (param_pos == param->PositionImpl) {
3303 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
3305 idx <<= CUSTOM_ATTR_BITS;
3306 idx |= CUSTOM_ATTR_PARAMDEF;
3307 } else { /* handle other types here... */
3308 g_error ("get custom attrs not yet supported for %s", klass->name);
3311 /* at this point image and index are set correctly for searching the custom attr */
3312 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3313 /* the table is not sorted */
3314 for (i = 0; i < ca->rows; ++i) {
3315 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
3316 if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
3318 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
3319 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
3320 case CUSTOM_ATTR_TYPE_METHODDEF:
3321 mtoken |= MONO_TOKEN_METHOD_DEF;
3323 case CUSTOM_ATTR_TYPE_MEMBERREF:
3324 mtoken |= MONO_TOKEN_MEMBER_REF;
3327 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
3330 method = mono_get_method (image, mtoken, NULL);
3332 g_error ("Can't find custom attr constructor");
3333 mono_class_init (method->klass);
3334 /*g_print ("got attr %s\n", method->klass->name);*/
3335 params = g_new (void*, method->signature->param_count);
3336 fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
3337 attr = mono_object_new (mono_domain_get (), method->klass);
3338 mono_runtime_invoke (method, attr, params, NULL);
3339 list = g_list_prepend (list, attr);
3340 free_param_data (method->signature, params);
3344 len = g_list_length (list);
3346 * The return type is really object[], but System/Attribute.cs does a cast
3347 * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
3348 * probably fix that.
3350 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
3351 result = mono_array_new (mono_domain_get (), klass, len);
3352 for (i = 0; i < len; ++i) {
3353 mono_array_set (result, gpointer, i, list->data);
3356 g_list_free (g_list_first (list));
3361 static MonoMethodSignature*
3362 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
3363 MonoMethodSignature *sig;
3366 count = ctor->parameters? mono_array_length (ctor->parameters): 0;
3368 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
3370 sig->param_count = count;
3371 sig->sentinelpos = -1; /* FIXME */
3372 for (i = 0; i < count; ++i) {
3373 MonoReflectionType *pt = mono_array_get (ctor->parameters, MonoReflectionType*, i);
3374 sig->params [i] = pt->type;
3380 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
3382 MonoClass *klass = mono_object_class (prop);
3383 if (strcmp (klass->name, "PropertyBuilder") == 0) {
3384 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
3385 *name = mono_string_to_utf8 (pb->name);
3386 *type = pb->type->type;
3388 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
3389 *name = g_strdup (p->property->name);
3390 if (p->property->get)
3391 *type = p->property->get->signature->ret;
3393 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
3398 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
3400 MonoClass *klass = mono_object_class (field);
3401 if (strcmp (klass->name, "FieldBuilder") == 0) {
3402 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
3403 *name = mono_string_to_utf8 (fb->name);
3404 *type = fb->type->type;
3406 MonoReflectionField *f = (MonoReflectionField *)field;
3407 *name = g_strdup (f->field->name);
3408 *type = f->field->type;
3413 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
3414 char *name, *result;
3418 name = mono_type_get_name (type);
3419 klass = mono_class_from_mono_type (type);
3420 ta = klass->image->assembly;
3421 if (ta == ass || klass->image == mono_defaults.corlib)
3424 /* missing public key */
3425 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
3426 name, ta->aname.name,
3427 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
3428 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
3434 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
3437 MonoTypeEnum simple_type;
3439 if ((p-buffer) + 10 >= *buflen) {
3442 newbuf = g_realloc (buffer, *buflen);
3443 p = newbuf + (p-buffer);
3446 argval = ((char*)arg + sizeof (MonoObject));
3447 simple_type = type->type;
3449 switch (simple_type) {
3450 case MONO_TYPE_BOOLEAN:
3455 case MONO_TYPE_CHAR:
3458 swap_with_size (p, argval, 2, 1);
3464 swap_with_size (p, argval, 4, 1);
3470 swap_with_size (p, argval, 8, 1);
3473 case MONO_TYPE_VALUETYPE:
3474 if (type->data.klass->enumtype) {
3475 simple_type = type->data.klass->enum_basetype->type;
3478 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
3481 case MONO_TYPE_STRING: {
3482 char *str = mono_string_to_utf8 ((MonoString*)arg);
3483 guint32 slen = strlen (str);
3484 if ((p-buffer) + 10 + slen >= *buflen) {
3488 newbuf = g_realloc (buffer, *buflen);
3489 p = newbuf + (p-buffer);
3492 mono_metadata_encode_value (slen, p, &p);
3493 memcpy (p, str, slen);
3498 case MONO_TYPE_CLASS: {
3501 if (!mono_object_isinst (arg, mono_defaults.monotype_class))
3502 g_error ("only types allowed");
3504 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
3505 slen = strlen (str);
3506 if ((p-buffer) + 10 + slen >= *buflen) {
3510 newbuf = g_realloc (buffer, *buflen);
3511 p = newbuf + (p-buffer);
3514 mono_metadata_encode_value (slen, p, &p);
3515 memcpy (p, str, slen);
3520 /* it may be a boxed value or a Type */
3521 case MONO_TYPE_OBJECT: {
3522 MonoClass *klass = mono_object_class (arg);
3526 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
3529 } else if (klass->enumtype) {
3531 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
3532 *p++ = simple_type = klass->byval_arg.type;
3535 g_error ("unhandled type in custom attr");
3537 str = type_get_qualified_name (klass->enum_basetype, NULL);
3538 slen = strlen (str);
3539 if ((p-buffer) + 10 + slen >= *buflen) {
3543 newbuf = g_realloc (buffer, *buflen);
3544 p = newbuf + (p-buffer);
3547 mono_metadata_encode_value (slen, p, &p);
3548 memcpy (p, str, slen);
3551 simple_type = klass->enum_basetype->type;
3555 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
3558 *retbuffer = buffer;
3562 * mono_reflection_get_custom_attrs_blob:
3563 * @ctor: custom attribute constructor
3564 * @ctorArgs: arguments o the constructor
3570 * Creates the blob of data that needs to be saved in the metadata and that represents
3571 * the custom attributed described by @ctor, @ctorArgs etc.
3572 * Returns: a Byte array representing the blob of data.
3575 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) {
3577 MonoMethodSignature *sig;
3582 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3583 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
3585 sig = ((MonoReflectionMethod*)ctor)->method->signature;
3588 p = buffer = g_malloc (buflen);
3589 /* write the prolog */
3592 for (i = 0; i < sig->param_count; ++i) {
3593 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
3594 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
3598 i += mono_array_length (properties);
3600 i += mono_array_length (fields);
3602 *p++ = (i >> 8) & 0xff;
3605 for (i = 0; i < mono_array_length (properties); ++i) {
3610 prop = mono_array_get (properties, gpointer, i);
3611 get_prop_name_and_type (prop, &pname, &ptype);
3612 *p++ = 0x54; /* PROPERTY signature */
3613 len = strlen (pname);
3614 mono_metadata_encode_value (len, p, &p);
3615 memcpy (p, pname, len);
3617 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
3624 for (i = 0; i < mono_array_length (fields); ++i) {
3629 field = mono_array_get (fields, gpointer, i);
3630 get_field_name_and_type (field, &fname, &ftype);
3631 *p++ = 0x53; /* FIELD signature */
3632 len = strlen (fname);
3633 mono_metadata_encode_value (len, p, &p);
3634 memcpy (p, fname, len);
3636 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
3641 g_assert (p - buffer <= buflen);
3642 buflen = p - buffer;
3643 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
3644 p = mono_array_addr (result, char, 0);
3645 memcpy (p, buffer, buflen);
3647 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
3653 * mono_reflection_setup_internal_class:
3654 * @tb: a TypeBuilder object
3656 * Creates a MonoClass that represents the TypeBuilder.
3657 * This is a trick that lets us simplify a lot of reflection code
3658 * (and will allow us to support Build and Run assemblies easier).
3661 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
3663 MonoClass *klass, *parent;
3665 klass = g_new0 (MonoClass, 1);
3667 klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
3670 parent = mono_class_from_mono_type (tb->parent->type);
3674 klass->inited = 1; /* we lie to the runtime */
3675 klass->name = mono_string_to_utf8 (tb->name);
3676 klass->name_space = mono_string_to_utf8 (tb->nspace);
3677 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
3678 klass->flags = tb->attrs;
3680 klass->element_class = klass;
3681 klass->reflection_info = tb; /* need to pin. */
3684 mono_class_setup_parent (klass, parent);
3685 mono_class_setup_mono_type (klass);
3688 * FIXME: handle interfaces.
3691 tb->type.type = &klass->byval_arg;
3693 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
3697 * mono_reflection_create_internal_class:
3698 * @tb: a TypeBuilder object
3700 * Actually create the MonoClass that is associated with the TypeBuilder.
3703 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
3707 klass = mono_class_from_mono_type (tb->type.type);
3709 if (klass->enumtype && klass->enum_basetype == NULL) {
3710 MonoReflectionFieldBuilder *fb;
3712 g_assert (tb->fields != NULL);
3713 g_assert (mono_array_length (tb->fields) >= 1);
3715 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
3717 klass->enum_basetype = fb->type->type;
3718 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
3723 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
3725 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
3726 guint32 na = mono_array_length (sig->arguments);
3731 p = buf = g_malloc (10 + na * 10);
3733 mono_metadata_encode_value (0x07, p, &p);
3734 mono_metadata_encode_value (na, p, &p);
3735 for (i = 0; i < na; ++i) {
3736 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
3737 encode_reflection_type (assembly, type, p, &p);
3741 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
3742 p = mono_array_addr (result, char, 0);
3743 memcpy (p, buf, buflen);
3750 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
3752 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
3753 guint32 na = mono_array_length (sig->arguments);
3758 p = buf = g_malloc (10 + na * 10);
3760 mono_metadata_encode_value (0x06, p, &p);
3761 for (i = 0; i < na; ++i) {
3762 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
3763 encode_reflection_type (assembly, type, p, &p);
3767 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
3768 p = mono_array_addr (result, char, 0);
3769 memcpy (p, buf, buflen);