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"
25 #include "rawbuffer.h"
26 #include "mono-endian.h"
32 #define TEXT_OFFSET 512
33 #define CLI_H_SIZE 136
34 #define FILE_ALIGN 512
35 #define VIRT_ALIGN 8192
36 #define START_TEXT_RVA 0x00002000
39 MonoReflectionILGen *ilgen;
40 MonoReflectionType *rtype;
41 MonoArray *parameters;
46 guint32 *table_idx; /* note: it's a pointer */
50 MonoBoolean init_locals;
51 } ReflectionMethodBuilder;
53 const unsigned char table_sizes [64] = {
63 MONO_INTERFACEIMPL_SIZE,
64 MONO_MEMBERREF_SIZE, /* 0x0A */
66 MONO_CUSTOM_ATTR_SIZE,
67 MONO_FIELD_MARSHAL_SIZE,
68 MONO_DECL_SECURITY_SIZE,
69 MONO_CLASS_LAYOUT_SIZE,
70 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
71 MONO_STAND_ALONE_SIGNATURE_SIZE,
75 MONO_PROPERTY_MAP_SIZE,
78 MONO_METHOD_SEMA_SIZE,
80 MONO_MODULEREF_SIZE, /* 0x1A */
86 MONO_ASSEMBLY_SIZE, /* 0x20 */
87 MONO_ASSEMBLY_PROCESSOR_SIZE,
89 MONO_ASSEMBLYREF_SIZE,
90 MONO_ASSEMBLYREFPROC_SIZE,
91 MONO_ASSEMBLYREFOS_SIZE,
95 MONO_NESTED_CLASS_SIZE,
99 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
100 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
101 static guint32 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo);
104 alloc_table (MonoDynamicTable *table, guint nrows)
107 g_assert (table->columns);
108 table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
112 string_heap_insert (MonoDynamicStream *sh, const char *str)
116 gpointer oldkey, oldval;
118 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
119 return GPOINTER_TO_UINT (oldval);
121 len = strlen (str) + 1;
123 if (idx + len > sh->alloc_size) {
124 sh->alloc_size += len + 4096;
125 sh->data = g_realloc (sh->data, sh->alloc_size);
128 * We strdup the string even if we already copy them in sh->data
129 * so that the string pointers in the hash remain valid even if
130 * we need to realloc sh->data. We may want to avoid that later.
132 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
133 memcpy (sh->data + idx, str, len);
139 string_heap_init (MonoDynamicStream *sh)
142 sh->alloc_size = 4096;
143 sh->data = g_malloc (4096);
144 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
145 string_heap_insert (sh, "");
148 #if 0 /* never used */
150 string_heap_free (MonoDynamicStream *sh)
153 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
154 g_hash_table_destroy (sh->hash);
159 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
162 if (stream->alloc_size < stream->index + len) {
163 stream->alloc_size += len + 4096;
164 stream->data = g_realloc (stream->data, stream->alloc_size);
166 memcpy (stream->data + stream->index, data, len);
168 stream->index += len;
170 * align index? Not without adding an additional param that controls it since
171 * we may store a blob value in pieces.
177 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
180 if (stream->alloc_size < stream->index + len) {
181 stream->alloc_size += len + 4096;
182 stream->data = g_realloc (stream->data, stream->alloc_size);
184 memset (stream->data + stream->index, 0, len);
186 stream->index += len;
191 stream_data_align (MonoDynamicStream *stream)
194 guint32 count = stream->index % 4;
196 /* we assume the stream data will be aligned */
198 mono_image_add_stream_data (stream, buf, 4 - count);
201 /* modified version needed to handle building corlib */
203 my_mono_class_from_mono_type (MonoType *type) {
204 switch (type->type) {
205 case MONO_TYPE_ARRAY:
207 case MONO_TYPE_SZARRAY:
208 return mono_class_from_mono_type (type);
210 /* should be always valid when we reach this case... */
211 return type->data.klass;
216 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
219 g_assert_not_reached ();
224 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
228 case MONO_TYPE_BOOLEAN:
242 case MONO_TYPE_STRING:
243 case MONO_TYPE_OBJECT:
244 case MONO_TYPE_TYPEDBYREF:
245 mono_metadata_encode_value (type->type, p, &p);
248 case MONO_TYPE_SZARRAY:
249 mono_metadata_encode_value (type->type, p, &p);
250 encode_type (assembly, type->data.type, p, &p);
252 case MONO_TYPE_VALUETYPE:
253 case MONO_TYPE_CLASS:
254 mono_metadata_encode_value (type->type, p, &p);
255 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
258 case MONO_TYPE_VALUETYPE:
259 case MONO_TYPE_CLASS: {
260 MonoClass *k = mono_class_from_mono_type (type);
261 mono_metadata_encode_value (type->type, p, &p);
262 /* ensure only non-byref gets passed to mono_image_typedef_or_ref() */
263 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
267 case MONO_TYPE_ARRAY:
268 mono_metadata_encode_value (type->type, p, &p);
269 encode_type (assembly, type->data.array->type, p, &p);
270 mono_metadata_encode_value (type->data.array->rank, p, &p);
271 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
272 mono_metadata_encode_value (0, p, &p);
275 g_error ("need to encode type %x", type->type);
281 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
284 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
288 encode_type (assembly, type->type, p, endbuf);
292 g_assert_not_reached ();
297 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
302 guint32 nparams = sig->param_count;
303 guint32 size = 10 + nparams * 10;
308 p = buf = g_malloc (size);
310 * FIXME: vararg, explicit_this, differenc call_conv values...
312 *p = sig->call_convention;
314 *p |= 0x20; /* hasthis */
316 mono_metadata_encode_value (nparams, p, &p);
317 encode_type (assembly, sig->ret, p, &p);
318 for (i = 0; i < nparams; ++i)
319 encode_type (assembly, sig->params [i], p, &p);
321 g_assert (p - buf < size);
322 mono_metadata_encode_value (p-buf, b, &b);
323 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
324 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
330 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
333 * FIXME: reuse code from method_encode_signature().
338 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
339 guint32 size = 10 + nparams * 10;
344 p = buf = g_malloc (size);
345 /* LAMESPEC: all the call conv spec is foobared */
346 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
347 if (mb->call_conv & 2)
348 *p |= 0x5; /* vararg */
349 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
350 *p |= 0x20; /* hasthis */
352 mono_metadata_encode_value (nparams, p, &p);
353 encode_reflection_type (assembly, mb->rtype, p, &p);
354 for (i = 0; i < nparams; ++i) {
355 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
356 encode_reflection_type (assembly, pt, p, &p);
359 g_assert (p - buf < size);
360 mono_metadata_encode_value (p-buf, b, &b);
361 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
362 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
368 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
370 MonoDynamicTable *table;
373 guint32 idx, sig_idx, size;
374 guint nl = mono_array_length (ilgen->locals);
381 p = buf = g_malloc (size);
382 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
383 idx = table->next_idx ++;
385 alloc_table (table, table->rows);
386 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
388 mono_metadata_encode_value (0x07, p, &p);
389 mono_metadata_encode_value (nl, p, &p);
390 for (i = 0; i < nl; ++i) {
391 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
392 encode_reflection_type (assembly, lb->type, p, &p);
394 g_assert (p - buf < size);
395 mono_metadata_encode_value (p-buf, b, &b);
396 sig_idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
397 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
400 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
406 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
412 gint32 num_locals = 0;
413 gint32 num_exception = 0;
416 char fat_header [12];
419 guint32 local_sig = 0;
420 guint32 header_size = 12;
423 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
424 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
425 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
426 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
430 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
432 code = mb->ilgen->code;
433 code_size = mb->ilgen->code_len;
434 max_stack = mb->ilgen->max_stack;
435 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
436 if (mb->ilgen->ex_handlers) {
437 MonoILExceptionInfo *ex_info;
438 for (i = 0; i < mono_array_length (mb->ilgen->ex_handlers); ++i) {
439 ex_info = (MonoILExceptionInfo*)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
440 if (ex_info->handlers)
441 num_exception += mono_array_length (ex_info->handlers);
448 code_size = mono_array_length (code);
449 max_stack = 8; /* we probably need to run a verifier on the code... */
452 /* check for exceptions, maxstack, locals */
453 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
455 if (code_size < 64 && !(code_size & 1)) {
456 flags = (code_size << 2) | 0x2;
457 } else if (code_size < 32 && (code_size & 1)) {
458 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
462 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
463 /* add to the fixup todo list */
464 if (mb->ilgen && mb->ilgen->num_token_fixups)
465 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
466 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
467 return assembly->text_rva + idx;
471 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
473 * FIXME: need to set also the header size in fat_flags.
474 * (and more sects and init locals flags)
478 fat_flags |= METHOD_HEADER_MORE_SECTS;
480 fat_flags |= METHOD_HEADER_INIT_LOCALS;
481 fat_header [0] = fat_flags;
482 fat_header [1] = (header_size / 4 ) << 4;
483 shortp = (guint16*)(fat_header + 2);
484 *shortp = GUINT16_TO_LE (max_stack);
485 intp = (guint32*)(fat_header + 4);
486 *intp = GUINT32_TO_LE (code_size);
487 intp = (guint32*)(fat_header + 8);
488 *intp = GUINT32_TO_LE (local_sig);
489 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
490 /* add to the fixup todo list */
491 if (mb->ilgen && mb->ilgen->num_token_fixups)
492 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
494 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
496 unsigned char sheader [4];
497 MonoExceptionClause clause;
498 MonoILExceptionInfo * ex_info;
499 MonoILExceptionBlock * ex_block;
502 stream_data_align (&assembly->code);
503 /* always use fat format for now */
504 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
505 num_exception *= sizeof (MonoExceptionClause);
506 sheader [1] = num_exception & 0xff;
507 sheader [2] = (num_exception >> 8) & 0xff;
508 sheader [3] = (num_exception >> 16) & 0xff;
509 mono_image_add_stream_data (&assembly->code, sheader, 4);
510 /* fat header, so we are already aligned */
512 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
513 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
514 if (ex_info->handlers) {
515 int finally_start = ex_info->start + ex_info->len;
516 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
517 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
518 clause.flags = GUINT32_TO_LE (ex_block->type);
519 clause.try_offset = GUINT32_TO_LE (ex_info->start);
520 /* need fault, too, probably */
521 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
522 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
524 clause.try_len = GUINT32_TO_LE (ex_info->len);
525 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
526 clause.handler_len = GUINT32_TO_LE (ex_block->len);
527 finally_start = ex_block->start + ex_block->len;
528 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
529 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
530 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
531 /*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",
532 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);*/
533 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
536 g_error ("No clauses for ex info block %d", i);
540 return assembly->text_rva + idx;
544 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 token)
547 MonoDynamicTable *table;
550 table = &assembly->tables [table_idx];
552 g_assert (col < table->columns);
554 values = table->values + table->columns;
555 for (i = 1; i <= table->rows; ++i) {
556 if (values [col] == token)
563 * idx is the table index of the object
564 * type is one of CUSTOM_ATTR_*
567 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
569 MonoDynamicTable *table;
570 MonoReflectionCustomAttr *cattr;
572 guint32 count, i, token;
576 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
579 count = mono_array_length (cattrs);
580 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
581 table->rows += count;
582 alloc_table (table, table->rows);
583 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
584 idx <<= CUSTOM_ATTR_BITS;
586 for (i = 0; i < count; ++i) {
587 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
588 values [MONO_CUSTOM_ATTR_PARENT] = idx;
589 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
590 type = mono_metadata_token_index (token);
591 type <<= CUSTOM_ATTR_TYPE_BITS;
592 switch (mono_metadata_token_table (token)) {
593 case MONO_TABLE_METHOD:
594 type |= CUSTOM_ATTR_TYPE_METHODDEF;
596 case MONO_TABLE_MEMBERREF:
597 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
600 g_warning ("got wrong token in custom attr");
603 values [MONO_CUSTOM_ATTR_TYPE] = type;
605 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
606 values [MONO_CUSTOM_ATTR_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, p - blob_size);
607 mono_image_add_stream_data (&assembly->blob,
608 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
609 values += MONO_CUSTOM_ATTR_SIZE;
616 * Fill in the MethodDef and ParamDef tables for a method.
617 * This is used for both normal methods and constructors.
620 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
622 MonoDynamicTable *table;
627 /* room in this table is already allocated */
628 table = &assembly->tables [MONO_TABLE_METHOD];
629 *mb->table_idx = table->next_idx ++;
630 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
632 name = mono_string_to_utf8 (mb->name);
633 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
635 } else { /* a constructor */
636 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
638 values [MONO_METHOD_FLAGS] = mb->attrs;
639 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
640 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
641 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
643 table = &assembly->tables [MONO_TABLE_PARAM];
644 values [MONO_METHOD_PARAMLIST] = table->next_idx;
647 MonoDynamicTable *mtable;
650 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
651 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
654 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
655 if (mono_array_get (mb->pinfo, gpointer, i))
658 table->rows += count;
659 alloc_table (table, table->rows);
660 values = table->values + table->next_idx * MONO_PARAM_SIZE;
661 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
662 MonoReflectionParamBuilder *pb;
663 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
664 values [MONO_PARAM_FLAGS] = pb->attrs;
665 values [MONO_PARAM_SEQUENCE] = i;
666 name = mono_string_to_utf8 (pb->name);
667 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
669 values += MONO_PARAM_SIZE;
670 if (pb->marshal_info) {
672 alloc_table (mtable, mtable->rows);
673 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
674 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
675 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
677 pb->table_idx = table->next_idx++;
684 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
686 MonoDynamicTable *table;
689 ReflectionMethodBuilder rmb;
691 rmb.ilgen = mb->ilgen;
692 rmb.rtype = mb->rtype;
693 rmb.parameters = mb->parameters;
694 rmb.pinfo = mb->pinfo;
695 rmb.attrs = mb->attrs;
696 rmb.iattrs = mb->iattrs;
697 rmb.call_conv = mb->call_conv;
701 rmb.table_idx = &mb->table_idx;
702 rmb.init_locals = mb->init_locals;
704 mono_image_basic_method (&rmb, assembly);
706 if (mb->dll) { /* It's a P/Invoke method */
708 table = &assembly->tables [MONO_TABLE_IMPLMAP];
710 alloc_table (table, table->rows);
711 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
712 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
713 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
714 name = mono_string_to_utf8 (mb->dllentry);
715 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
717 name = mono_string_to_utf8 (mb->dll);
718 moduleref = string_heap_insert (&assembly->sheap, name);
720 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
721 table = &assembly->tables [MONO_TABLE_MODULEREF];
723 alloc_table (table, table->rows);
724 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
725 values [MONO_IMPLMAP_SCOPE] = table->rows;
728 if (mb->override_method) {
729 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
731 table = &assembly->tables [MONO_TABLE_METHODIMPL];
733 alloc_table (table, table->rows);
734 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
735 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
736 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
737 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
738 switch (mono_metadata_token_table (tok)) {
739 case MONO_TABLE_MEMBERREF:
740 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
742 case MONO_TABLE_METHOD:
743 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
746 g_assert_not_reached ();
748 values [MONO_METHODIMPL_DECLARATION] = tok;
753 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
755 ReflectionMethodBuilder rmb;
757 rmb.ilgen = mb->ilgen;
758 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
759 rmb.parameters = mb->parameters;
760 rmb.pinfo = mb->pinfo;
761 rmb.attrs = mb->attrs;
762 rmb.iattrs = mb->iattrs;
763 rmb.call_conv = mb->call_conv;
767 rmb.table_idx = &mb->table_idx;
768 rmb.init_locals = mb->init_locals;
770 mono_image_basic_method (&rmb, assembly);
775 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
783 p = buf = g_malloc (64);
785 mono_metadata_encode_value (0x06, p, &p);
786 /* encode custom attributes before the type */
787 encode_type (assembly, field->type, p, &p);
788 g_assert (p-buf < 64);
789 mono_metadata_encode_value (p-buf, b, &b);
790 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
791 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
797 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
805 p = buf = g_malloc (64);
807 mono_metadata_encode_value (0x06, p, &p);
808 /* encode custom attributes before the type */
809 encode_reflection_type (assembly, fb->type, p, &p);
810 g_assert (p-buf < 64);
811 mono_metadata_encode_value (p-buf, b, &b);
812 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
813 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
819 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
820 * dest may be misaligned.
823 swap_with_size (char *dest, const char* val, int len, int nelem) {
824 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
827 for (elem = 0; elem < nelem; ++elem) {
853 g_assert_not_reached ();
859 memcpy (dest, val, len * nelem);
864 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
871 p = buf = g_malloc (64);
873 box_val = ((char*)val) + sizeof (MonoObject);
874 *ret_type = val->vtable->klass->byval_arg.type;
877 case MONO_TYPE_BOOLEAN:
897 case MONO_TYPE_VALUETYPE:
898 if (val->vtable->klass->enumtype) {
899 *ret_type = val->vtable->klass->enum_basetype->type;
902 g_error ("we can't encode valuetypes");
903 case MONO_TYPE_STRING: {
904 MonoString *str = (MonoString*)val;
905 /* there is no signature */
906 len = str->length * 2;
907 mono_metadata_encode_value (len, b, &b);
908 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
909 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
911 char *swapped = g_malloc (2 * mono_string_length (str));
912 const char *p = (const char*)mono_string_chars (str);
914 swap_with_size (swapped, p, 2, mono_string_length (str));
915 mono_image_add_stream_data (&assembly->blob, swapped, len);
919 mono_image_add_stream_data (&assembly->blob, (const char*)mono_string_chars (str), len);
926 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
929 /* there is no signature */
930 mono_metadata_encode_value (len, b, &b);
931 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
932 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
933 swap_with_size (blob_size, box_val, len, 1);
934 mono_image_add_stream_data (&assembly->blob, blob_size, len);
936 mono_image_add_stream_data (&assembly->blob, box_val, len);
944 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo) {
950 p = buf = g_malloc (256);
952 switch (minfo->type) {
953 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
955 mono_metadata_encode_value (minfo->type, p, &p);
959 mono_metadata_encode_value (len, b, &b);
960 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
961 mono_image_add_stream_data (&assembly->blob, buf, len);
967 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
969 MonoDynamicTable *table;
973 /* maybe this fixup should be done in the C# code */
974 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
975 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
976 table = &assembly->tables [MONO_TABLE_FIELD];
977 fb->table_idx = table->next_idx ++;
978 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
979 name = mono_string_to_utf8 (fb->name);
980 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
982 values [MONO_FIELD_FLAGS] = fb->attrs;
983 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
985 if (fb->offset != -1) {
986 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
988 alloc_table (table, table->rows);
989 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
990 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
991 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
993 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
994 guint32 field_type = 0;
995 table = &assembly->tables [MONO_TABLE_CONSTANT];
997 alloc_table (table, table->rows);
998 values = table->values + table->rows * MONO_CONSTANT_SIZE;
999 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1000 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1001 values [MONO_CONSTANT_TYPE] = field_type;
1002 values [MONO_CONSTANT_PADDING] = 0;
1006 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1008 alloc_table (table, table->rows);
1009 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1010 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1012 * We store it in the code section because it's simpler for now.
1014 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1015 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1017 if (fb->marshal_info) {
1018 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1020 alloc_table (table, table->rows);
1021 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1022 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1023 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1028 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
1032 char *b = blob_size;
1033 guint32 nparams = 0;
1034 MonoReflectionMethodBuilder *mb = fb->get_method;
1035 MonoReflectionMethodBuilder *smb = fb->set_method;
1036 guint32 idx, i, size;
1038 if (mb && mb->parameters)
1039 nparams = mono_array_length (mb->parameters);
1040 if (!mb && smb && smb->parameters)
1041 nparams = mono_array_length (smb->parameters) - 1;
1042 size = 24 + nparams * 10;
1043 buf = p = g_malloc (size);
1046 mono_metadata_encode_value (nparams, p, &p);
1048 encode_reflection_type (assembly, mb->rtype, p, &p);
1049 for (i = 0; i < nparams; ++i) {
1050 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1051 encode_reflection_type (assembly, pt, p, &p);
1054 /* the property type is the last param */
1055 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1056 for (i = 0; i < nparams; ++i) {
1057 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1058 encode_reflection_type (assembly, pt, p, &p);
1062 g_assert (p - buf < size);
1063 mono_metadata_encode_value (p-buf, b, &b);
1064 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1065 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
1071 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
1073 MonoDynamicTable *table;
1076 guint num_methods = 0;
1080 * we need to set things in the following tables:
1081 * PROPERTYMAP (info already filled in _get_type_info ())
1082 * PROPERTY (rows already preallocated in _get_type_info ())
1083 * METHOD (method info already done with the generic method code)
1086 table = &assembly->tables [MONO_TABLE_PROPERTY];
1087 pb->table_idx = table->next_idx ++;
1088 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1089 name = mono_string_to_utf8 (pb->name);
1090 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1092 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1093 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1095 /* FIXME: we still don't handle 'other' methods */
1096 if (pb->get_method) num_methods ++;
1097 if (pb->set_method) num_methods ++;
1099 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1100 table->rows += num_methods;
1101 alloc_table (table, table->rows);
1103 if (pb->get_method) {
1104 semaidx = table->next_idx ++;
1105 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1106 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1107 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1108 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1110 if (pb->set_method) {
1111 semaidx = table->next_idx ++;
1112 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1113 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1114 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1115 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1120 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
1122 MonoDynamicTable *table;
1125 guint num_methods = 0;
1129 * we need to set things in the following tables:
1130 * EVENTMAP (info already filled in _get_type_info ())
1131 * EVENT (rows already preallocated in _get_type_info ())
1132 * METHOD (method info already done with the generic method code)
1135 table = &assembly->tables [MONO_TABLE_EVENT];
1136 eb->table_idx = table->next_idx ++;
1137 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1138 name = mono_string_to_utf8 (eb->name);
1139 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1141 values [MONO_EVENT_FLAGS] = eb->attrs;
1142 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1145 * FIXME: we still don't handle 'other' methods
1147 if (eb->add_method) num_methods ++;
1148 if (eb->remove_method) num_methods ++;
1149 if (eb->raise_method) num_methods ++;
1151 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1152 table->rows += num_methods;
1153 alloc_table (table, table->rows);
1155 if (eb->add_method) {
1156 semaidx = table->next_idx ++;
1157 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1158 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1159 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1160 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1162 if (eb->remove_method) {
1163 semaidx = table->next_idx ++;
1164 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1165 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1166 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1167 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1169 if (eb->raise_method) {
1170 semaidx = table->next_idx ++;
1171 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1172 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1173 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1174 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1179 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
1181 MonoDynamicTable *table;
1184 guint32 cols [MONO_ASSEMBLY_SIZE];
1186 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1189 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1191 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1192 token = table->next_idx ++;
1194 alloc_table (table, table->rows);
1195 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1196 if (strcmp ("corlib", image->assembly_name) == 0)
1197 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1199 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1200 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1201 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1202 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1203 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1204 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1205 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1206 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1207 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1209 token <<= RESOLTION_SCOPE_BITS;
1210 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1211 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1216 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1218 MonoDynamicTable *table;
1224 char *b = blob_size;
1226 switch (type->type) {
1227 case MONO_TYPE_FNPTR:
1229 case MONO_TYPE_SZARRAY:
1230 case MONO_TYPE_ARRAY:
1231 encode_type (assembly, type, p, &p);
1237 g_assert (p-sig < 128);
1238 mono_metadata_encode_value (p-sig, b, &b);
1239 token = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1240 mono_image_add_stream_data (&assembly->blob, sig, p-sig);
1242 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1243 alloc_table (table, table->rows + 1);
1244 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1245 values [MONO_TYPESPEC_SIGNATURE] = token;
1247 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1248 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1254 * Despite the name, we handle also TypeSpec (with the above helper).
1257 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1259 MonoDynamicTable *table;
1261 guint32 token, scope, enclosing;
1264 #define COMPILE_CORLIB 0
1266 /* nasty hack, need to find the proper solution */
1267 if (type->type == MONO_TYPE_OBJECT)
1268 return TYPEDEFORREF_TYPEDEF | (2 << TYPEDEFORREF_BITS);
1270 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1273 token = create_typespec (assembly, type);
1276 klass = my_mono_class_from_mono_type (type);
1278 * If it's in the same module:
1280 if (klass->image == assembly->assembly.image) {
1281 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1282 return TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1285 if (klass->nested_in) {
1286 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1287 /* get the typeref idx of the enclosing type */
1288 enclosing >>= TYPEDEFORREF_BITS;
1289 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1291 scope = resolution_scope_from_image (assembly, klass->image);
1293 table = &assembly->tables [MONO_TABLE_TYPEREF];
1294 alloc_table (table, table->rows + 1);
1295 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1296 values [MONO_TYPEREF_SCOPE] = scope;
1297 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1298 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1299 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1300 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1306 * Insert a memberef row into the metadata: the token that point to the memberref
1307 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1308 * mono_image_get_fieldref_token()).
1309 * The sig param is an index to an already built signature.
1312 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
1314 MonoDynamicTable *table;
1316 guint32 token, pclass;
1319 parent = mono_image_typedef_or_ref (assembly, type);
1320 switch (parent & TYPEDEFORREF_MASK) {
1321 case TYPEDEFORREF_TYPEREF:
1322 pclass = MEMBERREF_PARENT_TYPEREF;
1324 case TYPEDEFORREF_TYPESPEC:
1325 pclass = MEMBERREF_PARENT_TYPESPEC;
1327 case TYPEDEFORREF_TYPEDEF:
1328 /* should never get here */
1330 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
1333 /* extract the index */
1334 parent >>= TYPEDEFORREF_BITS;
1336 table = &assembly->tables [MONO_TABLE_MEMBERREF];
1337 alloc_table (table, table->rows + 1);
1338 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1339 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1340 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1341 values [MONO_MEMBERREF_SIGNATURE] = sig;
1342 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1349 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1353 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1356 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
1357 method->name, method_encode_signature (assembly, method->signature));
1358 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1363 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1367 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1370 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
1371 field->name, fieldref_encode_signature (assembly, field));
1372 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1377 reflection_cc_to_file (int call_conv) {
1378 switch (call_conv & 0x3) {
1380 case 1: return MONO_CALL_DEFAULT;
1381 case 2: return MONO_CALL_VARARG;
1383 g_assert_not_reached ();
1390 MonoMethodSignature *sig;
1396 mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
1401 MonoMethodSignature *sig;
1404 name = mono_string_to_utf8 (m->name);
1405 nparams = mono_array_length (m->parameters);
1406 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
1408 sig->call_convention = reflection_cc_to_file (m->call_conv);
1409 sig->param_count = nparams;
1410 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
1411 for (i = 0; i < nparams; ++i) {
1412 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
1413 sig->params [i] = t->type;
1416 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
1418 if (strcmp (name, am->name) == 0 &&
1419 mono_metadata_type_equal (am->parent, m->parent->type) &&
1420 mono_metadata_signature_equal (am->sig, sig)) {
1426 am = g_new0 (ArrayMethod, 1);
1429 am->parent = m->parent->type;
1430 am->token = mono_image_get_memberref_token (assembly, am->parent,
1431 name, method_encode_signature (assembly, sig));
1432 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
1433 m->table_idx = am->token & 0xffffff;
1438 * Insert into the metadata tables all the info about the TypeBuilder tb.
1439 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1442 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1444 MonoDynamicTable *table;
1446 int i, is_object = 0, is_system = 0;
1449 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1450 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1451 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1452 n = mono_string_to_utf8 (tb->name);
1453 if (strcmp (n, "Object") == 0)
1455 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1457 n = mono_string_to_utf8 (tb->nspace);
1458 if (strcmp (n, "System") == 0)
1460 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1462 if (tb->parent && !(is_system && is_object)) { /* interfaces don't have a parent */
1463 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1465 values [MONO_TYPEDEF_EXTENDS] = 0;
1466 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1467 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1470 * if we have explicitlayout or sequentiallayouts, output data in the
1471 * ClassLayout table.
1473 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
1474 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1476 alloc_table (table, table->rows);
1477 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1478 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1479 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1480 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1483 /* handle interfaces */
1484 if (tb->interfaces) {
1485 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1487 table->rows += mono_array_length (tb->interfaces);
1488 alloc_table (table, table->rows);
1489 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1490 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1491 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1492 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1493 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1494 values += MONO_INTERFACEIMPL_SIZE;
1500 table = &assembly->tables [MONO_TABLE_FIELD];
1501 table->rows += mono_array_length (tb->fields);
1502 alloc_table (table, table->rows);
1503 for (i = 0; i < mono_array_length (tb->fields); ++i)
1504 mono_image_get_field_info (
1505 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1508 /* handle constructors */
1510 table = &assembly->tables [MONO_TABLE_METHOD];
1511 table->rows += mono_array_length (tb->ctors);
1512 alloc_table (table, table->rows);
1513 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1514 mono_image_get_ctor_info (domain,
1515 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1518 /* handle methods */
1520 table = &assembly->tables [MONO_TABLE_METHOD];
1521 table->rows += mono_array_length (tb->methods);
1522 alloc_table (table, table->rows);
1523 for (i = 0; i < mono_array_length (tb->methods); ++i)
1524 mono_image_get_method_info (
1525 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1528 /* Do the same with properties etc.. */
1529 if (tb->events && mono_array_length (tb->events)) {
1530 table = &assembly->tables [MONO_TABLE_EVENT];
1531 table->rows += mono_array_length (tb->events);
1532 alloc_table (table, table->rows);
1533 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1535 alloc_table (table, table->rows);
1536 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1537 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1538 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1539 for (i = 0; i < mono_array_length (tb->events); ++i)
1540 mono_image_get_event_info (
1541 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1543 if (tb->properties && mono_array_length (tb->properties)) {
1544 table = &assembly->tables [MONO_TABLE_PROPERTY];
1545 table->rows += mono_array_length (tb->properties);
1546 alloc_table (table, table->rows);
1547 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1549 alloc_table (table, table->rows);
1550 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1551 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1552 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1553 for (i = 0; i < mono_array_length (tb->properties); ++i)
1554 mono_image_get_property_info (
1555 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1558 MonoDynamicTable *ntable;
1560 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1561 table->rows += mono_array_length (tb->subtypes);
1562 alloc_table (table, table->rows);
1564 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1565 ntable->rows += mono_array_length (tb->subtypes);
1566 alloc_table (ntable, ntable->rows);
1567 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1569 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1570 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1572 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1573 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1574 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1575 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1576 mono_string_to_utf8 (tb->name), tb->table_idx,
1577 ntable->next_idx, ntable->rows);*/
1578 values += MONO_NESTED_CLASS_SIZE;
1581 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1582 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1584 mono_image_get_type_info (domain, subtype, assembly);
1590 assign_type_idx (MonoReflectionTypeBuilder *type, MonoDynamicTable *table)
1594 type->table_idx = table->next_idx ++;
1595 if (!type->subtypes)
1597 for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1598 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1599 assign_type_idx (subtype, table);
1604 params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
1609 for (i = 0; i < mono_array_length (pinfo); ++i) {
1610 MonoReflectionParamBuilder *pb;
1611 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
1614 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
1619 type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
1622 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1624 for (i = 0; i < mono_array_length (tb->fields); ++i) {
1625 MonoReflectionFieldBuilder* fb;
1626 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
1627 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
1631 for (i = 0; i < mono_array_length (tb->events); ++i) {
1632 MonoReflectionEventBuilder* eb;
1633 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
1634 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1637 if (tb->properties) {
1638 for (i = 0; i < mono_array_length (tb->properties); ++i) {
1639 MonoReflectionPropertyBuilder* pb;
1640 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
1641 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
1645 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
1646 MonoReflectionCtorBuilder* cb;
1647 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
1648 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
1649 params_add_cattrs (assembly, cb->pinfo);
1654 for (i = 0; i < mono_array_length (tb->methods); ++i) {
1655 MonoReflectionMethodBuilder* mb;
1656 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
1657 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
1658 params_add_cattrs (assembly, mb->pinfo);
1663 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
1664 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
1669 module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
1672 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1674 for (i = 0; i < mono_array_length (mb->types); ++i)
1675 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
1679 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1681 MonoDynamicTable *table;
1685 table = &assembly->tables [MONO_TABLE_MODULE];
1686 mb->table_idx = table->next_idx ++;
1687 name = mono_string_to_utf8 (mb->module.name);
1688 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1690 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1693 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1694 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1695 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1698 * fill-in info in other tables as well.
1700 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1701 table->rows += mono_array_length (mb->types);
1702 alloc_table (table, table->rows);
1704 * We assign here the typedef indexes to avoid mismatches if a type that
1705 * has not yet been stored in the tables is referenced by another type.
1707 for (i = 0; i < mono_array_length (mb->types); ++i) {
1708 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1709 assign_type_idx (type, table);
1711 for (i = 0; i < mono_array_length (mb->types); ++i)
1712 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1715 #define align_pointer(base,p)\
1717 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1719 (p) += 4 - (__diff & 3);\
1723 compare_semantics (const void *a, const void *b)
1725 const guint32 *a_values = a;
1726 const guint32 *b_values = b;
1727 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
1730 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
1734 compare_custom_attrs (const void *a, const void *b)
1736 const guint32 *a_values = a;
1737 const guint32 *b_values = b;
1739 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
1743 compare_field_marshal (const void *a, const void *b)
1745 const guint32 *a_values = a;
1746 const guint32 *b_values = b;
1748 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
1752 compare_nested (const void *a, const void *b)
1754 const guint32 *a_values = a;
1755 const guint32 *b_values = b;
1757 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
1761 * build_compressed_metadata() fills in the blob of data that represents the
1762 * raw metadata as it will be saved in the PE file. The five streams are output
1763 * and the metadata tables are comnpressed from the guint32 array representation,
1764 * to the compressed on-disk format.
1767 build_compressed_metadata (MonoDynamicAssembly *assembly)
1769 MonoDynamicTable *table;
1771 guint64 valid_mask = 0;
1772 guint64 sorted_mask;
1773 guint32 heapt_size = 0;
1774 guint32 meta_size = 256; /* allow for header and other stuff */
1775 guint32 table_offset;
1776 guint32 ntables = 0;
1783 * We need to use the current ms version or the ms runtime it won't find
1784 * the support dlls. D'oh!
1785 * const char *version = "mono-" VERSION;
1787 const char *version = "v1.0.3705";
1790 MonoDynamicStream *stream;
1791 } stream_desc [] = {
1792 {"#~", &assembly->tstream},
1793 {"#Strings", &assembly->sheap},
1794 {"#US", &assembly->us},
1795 {"#Blob", &assembly->blob},
1796 {"#GUID", &assembly->guid}
1799 /* tables that are sorted */
1800 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
1801 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
1802 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
1803 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
1804 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
1805 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
1807 /* Compute table sizes */
1808 /* the MonoImage has already been created in mono_image_basic_init() */
1809 meta = assembly->assembly.image;
1811 /* Setup the info used by compute_sizes () */
1812 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1813 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1814 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1816 meta_size += assembly->blob.index;
1817 meta_size += assembly->guid.index;
1818 meta_size += assembly->sheap.index;
1819 meta_size += assembly->us.index;
1821 for (i=0; i < 64; ++i)
1822 meta->tables [i].rows = assembly->tables [i].rows;
1824 for (i = 0; i < 64; i++){
1825 if (meta->tables [i].rows == 0)
1827 valid_mask |= (guint64)1 << i;
1829 meta->tables [i].row_size = mono_metadata_compute_size (
1830 meta, i, &meta->tables [i].size_bitfield);
1831 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1833 heapt_size += 24; /* #~ header size */
1834 heapt_size += ntables * 4;
1835 meta_size += heapt_size;
1836 meta->raw_metadata = g_malloc0 (meta_size);
1837 p = meta->raw_metadata;
1838 /* the metadata signature */
1839 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1840 /* version numbers and 4 bytes reserved */
1841 int16val = (guint16*)p;
1842 *int16val++ = GUINT16_TO_LE (1);
1843 *int16val = GUINT16_TO_LE (1);
1845 /* version string */
1846 int32val = (guint32*)p;
1847 *int32val = GUINT32_TO_LE ((strlen (version) + 3) & (~3)); /* needs to be multiple of 4 */
1849 memcpy (p, version, GUINT32_FROM_LE (*int32val));
1850 p += GUINT32_FROM_LE (*int32val);
1851 align_pointer (meta->raw_metadata, p);
1852 int16val = (guint16*)p;
1853 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
1854 *int16val = GUINT16_TO_LE (5); /* number of streams */
1858 * write the stream info.
1860 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1861 table_offset += 3; table_offset &= ~3;
1863 assembly->tstream.index = heapt_size;
1864 for (i = 0; i < 5; ++i) {
1865 int32val = (guint32*)p;
1866 stream_desc [i].stream->offset = table_offset;
1867 *int32val++ = GUINT32_TO_LE (table_offset);
1868 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
1869 table_offset += GUINT32_FROM_LE (*int32val);
1870 table_offset += 3; table_offset &= ~3;
1872 strcpy (p, stream_desc [i].name);
1873 p += strlen (stream_desc [i].name) + 1;
1874 align_pointer (meta->raw_metadata, p);
1877 * now copy the data, the table stream header and contents goes first.
1879 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1880 p = meta->raw_metadata + assembly->tstream.offset;
1881 int32val = (guint32*)p;
1882 *int32val = GUINT32_TO_LE (0); /* reserved */
1884 *p++ = 1; /* version */
1886 if (meta->idx_string_wide)
1888 if (meta->idx_guid_wide)
1890 if (meta->idx_blob_wide)
1893 *p++ = 0; /* reserved */
1894 int64val = (guint64*)p;
1895 *int64val++ = GUINT64_TO_LE (valid_mask);
1896 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
1898 int32val = (guint32*)p;
1899 for (i = 0; i < 64; i++){
1900 if (meta->tables [i].rows == 0)
1902 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
1904 p = (unsigned char*)int32val;
1906 /* sort the tables that still need sorting */
1907 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1909 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
1910 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1912 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
1913 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1915 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
1916 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1918 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
1920 /* compress the tables */
1921 for (i = 0; i < 64; i++){
1924 guint32 bitfield = meta->tables [i].size_bitfield;
1925 if (!meta->tables [i].rows)
1927 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1928 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1929 meta->tables [i].base = p;
1930 for (row = 1; row <= meta->tables [i].rows; ++row) {
1931 values = assembly->tables [i].values + row * assembly->tables [i].columns;
1932 for (col = 0; col < assembly->tables [i].columns; ++col) {
1933 switch (mono_metadata_table_size (bitfield, col)) {
1935 *p++ = values [col];
1938 int16val = (guint16*)p;
1939 *int16val = GUINT16_TO_LE (values [col]);
1943 int32val = (guint32*)p;
1944 *int32val = GUINT32_TO_LE (values [col]);
1948 g_assert_not_reached ();
1952 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1955 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1956 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1957 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1958 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1959 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1961 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1965 * Some tables in metadata need to be sorted according to some criteria, but
1966 * when methods and fields are first created with reflection, they may be assigned a token
1967 * that doesn't correspond to the final token they will get assigned after the sorting.
1968 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
1969 * with the reflection objects that represent them. Once all the tables are set up, the
1970 * reflection objects will contains the correct table index. fixup_method() will fixup the
1971 * tokens for the method with ILGenerator @ilgen.
1974 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
1975 guint32 code_idx = GPOINTER_TO_UINT (value);
1976 MonoReflectionILTokenInfo *iltoken;
1977 MonoReflectionFieldBuilder *field;
1978 MonoReflectionCtorBuilder *ctor;
1979 MonoReflectionMethodBuilder *method;
1980 MonoReflectionTypeBuilder *tb;
1982 unsigned char *target;
1984 for (i = 0; i < ilgen->num_token_fixups; ++i) {
1985 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
1986 target = assembly->code.data + code_idx + iltoken->code_pos;
1987 switch (target [3]) {
1988 case MONO_TABLE_FIELD:
1989 if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
1990 g_assert_not_reached ();
1991 field = (MonoReflectionFieldBuilder *)iltoken->member;
1992 idx = field->table_idx;
1994 case MONO_TABLE_METHOD:
1995 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1996 method = (MonoReflectionMethodBuilder *)iltoken->member;
1997 idx = method->table_idx;
1998 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1999 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
2000 idx = ctor->table_idx;
2002 g_assert_not_reached ();
2005 case MONO_TABLE_TYPEDEF:
2006 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
2007 g_assert_not_reached ();
2008 tb = (MonoReflectionTypeBuilder *)iltoken->member;
2009 idx = tb->table_idx;
2012 g_error ("got unexpected table 0x%02x in fixup", target [3]);
2014 target [0] = idx & 0xff;
2015 target [1] = (idx >> 8) & 0xff;
2016 target [2] = (idx >> 16) & 0xff;
2021 * mono_image_build_metadata() will fill the info in all the needed metadata tables
2022 * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
2023 * and recursively outputs the info for a module. Each module will output all the info
2024 * about it's types etc.
2025 * At the end of the process, method and field tokens are fixed up and the on-disk
2026 * compressed metadata representation is created.
2029 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
2031 MonoDynamicTable *table;
2032 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
2033 MonoDomain *domain = ((MonoObject *)assemblyb)->vtable->domain;
2039 assembly->text_rva = START_TEXT_RVA;
2041 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2042 alloc_table (table, 1);
2043 values = table->values + MONO_ASSEMBLY_SIZE;
2044 values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
2045 name = mono_string_to_utf8 (assemblyb->name);
2046 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
2048 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2049 values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
2050 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
2051 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
2052 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
2053 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
2054 values [MONO_ASSEMBLY_FLAGS] = 0;
2056 assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
2057 assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
2059 if (assemblyb->modules) {
2060 len = mono_array_length (assemblyb->modules);
2061 table = &assembly->tables [MONO_TABLE_MODULE];
2062 alloc_table (table, len);
2063 for (i = 0; i < len; ++i)
2064 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
2066 table = &assembly->tables [MONO_TABLE_MODULE];
2068 alloc_table (table, table->rows);
2069 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
2073 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2075 * table->rows is already set above and in mono_image_fill_module_table.
2077 alloc_table (table, table->rows);
2079 * Set the first entry.
2081 values = table->values + table->columns;
2082 values [MONO_TYPEDEF_FLAGS] = 0;
2083 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2084 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2085 values [MONO_TYPEDEF_EXTENDS] = 0;
2086 values [MONO_TYPEDEF_FIELD_LIST] = 1;
2087 values [MONO_TYPEDEF_METHOD_LIST] = 1;
2089 /* add all the custom attributes at the end, once all the indexes are stable */
2090 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
2092 if (assemblyb->modules) {
2093 len = mono_array_length (assemblyb->modules);
2094 for (i = 0; i < len; ++i)
2095 module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
2099 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2101 build_compressed_metadata (assembly);
2105 * mono_image_insert_string:
2106 * @assembly: assembly builder object
2109 * Insert @str into the user string stream of @assembly.
2112 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
2118 if (!assembly->dynamic_assembly)
2119 mono_image_basic_init (assembly);
2120 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
2121 idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
2122 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2124 char *swapped = g_malloc (2 * mono_string_length (str));
2125 const char *p = (const char*)mono_string_chars (str);
2127 swap_with_size (swapped, p, 2, mono_string_length (str));
2128 mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
2132 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
2134 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
2135 return MONO_TOKEN_STRING | idx;
2139 * mono_image_create_token:
2140 * @assembly: a dynamic assembly
2143 * Get a token to insert in the IL code stream for the given MemberInfo.
2144 * @obj can be one of:
2145 * ConstructorBuilder
2155 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
2161 g_error ("System.Array methods not yet supported");
2163 klass = obj->vtable->klass;
2164 if (strcmp (klass->name, "MethodBuilder") == 0) {
2165 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2166 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2167 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2170 if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2171 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2172 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2173 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
2176 if (strcmp (klass->name, "FieldBuilder") == 0) {
2177 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
2178 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
2180 if (strcmp (klass->name, "TypeBuilder") == 0) {
2181 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2182 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
2184 if (strcmp (klass->name, "MonoType") == 0) {
2185 MonoReflectionType *tb = (MonoReflectionType *)obj;
2186 return mono_metadata_token_from_dor (
2187 mono_image_typedef_or_ref (assembly, tb->type));
2189 if (strcmp (klass->name, "MonoCMethod") == 0 ||
2190 strcmp (klass->name, "MonoMethod") == 0) {
2191 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2192 token = mono_image_get_methodref_token (assembly, m->method);
2193 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
2196 if (strcmp (klass->name, "MonoField") == 0) {
2197 MonoReflectionField *f = (MonoReflectionField *)obj;
2198 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
2199 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
2202 if (strcmp (klass->name, "MonoArrayMethod") == 0) {
2203 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
2204 token = mono_image_get_array_token (assembly, m);
2207 g_print ("requested token for %s\n", klass->name);
2212 guint32 import_lookup_table;
2216 guint32 import_address_table_rva;
2225 * mono_image_basic_ini:
2226 * @assembly: an assembly builder object
2228 * Create the MonoImage that represents the assembly builder and setup some
2229 * of the helper hash table and the basic metadata streams.
2232 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
2234 static const guchar entrycode [16] = {0xff, 0x25, 0};
2235 MonoDynamicAssembly *assembly;
2239 if (assemblyb->dynamic_assembly)
2243 assembly = assemblyb->dynamic_assembly = GC_malloc (sizeof (MonoDynamicAssembly));
2245 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
2248 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
2249 assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
2250 assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
2251 assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
2253 string_heap_init (&assembly->sheap);
2254 mono_image_add_stream_data (&assembly->us, "", 1);
2255 mono_image_add_stream_data (&assembly->blob, "", 1);
2256 /* import tables... */
2257 mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
2258 assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
2259 assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
2260 mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
2261 assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
2262 mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
2263 assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
2264 stream_data_align (&assembly->code);
2266 assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
2268 for (i=0; i < 64; ++i) {
2269 assembly->tables [i].next_idx = 1;
2270 assembly->tables [i].columns = table_sizes [i];
2273 image = g_new0 (MonoImage, 1);
2275 /* keep in sync with image.c */
2276 assembly->assembly.aname.name = image->name = mono_string_to_utf8 (assemblyb->name);
2277 image->assembly_name = image->name; /* they may be different */
2279 image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2280 image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2281 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2282 image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
2284 assembly->assembly.image = image;
2289 calc_section_size (MonoDynamicAssembly *assembly)
2293 /* alignment constraints */
2294 assembly->code.index += 3;
2295 assembly->code.index &= ~3;
2296 assembly->meta_size += 3;
2297 assembly->meta_size &= ~3;
2299 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index;
2300 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2303 assembly->sections [MONO_SECTION_RELOC].size = 12;
2304 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2311 * mono_image_create_pefile:
2312 * @assemblyb: an assembly builder object
2314 * When we need to save an assembly, we first call this function that ensures the metadata
2315 * tables are built for all the modules in the assembly. This function creates the PE-COFF
2316 * header, the image sections, the CLI header etc. all the data is written in
2317 * assembly->pefile where it can be easily retrieved later in chunks.
2320 mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
2321 MonoMSDOSHeader *msdos;
2322 MonoDotNetHeader *header;
2323 MonoSectionTable *section;
2324 MonoCLIHeader *cli_header;
2325 guint32 size, image_size, virtual_base;
2326 guint32 header_start, section_start, file_offset, virtual_offset;
2327 MonoDynamicAssembly *assembly;
2328 MonoDynamicStream *pefile;
2332 static const unsigned char msheader[] = {
2333 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2334 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2337 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2338 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2339 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2340 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2343 mono_image_basic_init (assemblyb);
2344 assembly = assemblyb->dynamic_assembly;
2346 /* already created */
2347 if (assembly->pefile.index)
2350 mono_image_build_metadata (assemblyb);
2351 nsections = calc_section_size (assembly);
2353 pefile = &assembly->pefile;
2355 /* The DOS header and stub */
2356 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2357 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
2359 /* the dotnet header */
2360 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2362 /* the section tables */
2363 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2365 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2366 virtual_offset = VIRT_ALIGN;
2369 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2370 if (!assembly->sections [i].size)
2373 file_offset += FILE_ALIGN - 1;
2374 file_offset &= ~(FILE_ALIGN - 1);
2375 virtual_offset += VIRT_ALIGN - 1;
2376 virtual_offset &= ~(VIRT_ALIGN - 1);
2378 assembly->sections [i].offset = file_offset;
2379 assembly->sections [i].rva = virtual_offset;
2381 file_offset += assembly->sections [i].size;
2382 virtual_offset += assembly->sections [i].size;
2383 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2386 file_offset += FILE_ALIGN - 1;
2387 file_offset &= ~(FILE_ALIGN - 1);
2388 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
2390 image_size += section_start + sizeof (MonoSectionTable) * nsections;
2392 /* back-patch info */
2393 msdos = (MonoMSDOSHeader*)pefile->data;
2394 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
2395 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
2396 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2398 header = (MonoDotNetHeader*)(pefile->data + header_start);
2399 header->pesig [0] = 'P';
2400 header->pesig [1] = 'E';
2402 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
2403 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2404 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2405 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2407 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2408 /* FIXME: it's a dll */
2409 /*header->coff.coff_attributes = GUINT16_FROM_LE (0x210e); */
2411 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2413 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2414 header->pe.pe_major = 6;
2415 header->pe.pe_minor = 0;
2416 size = assembly->sections [MONO_SECTION_TEXT].size;
2417 size += FILE_ALIGN - 1;
2418 size &= ~(FILE_ALIGN - 1);
2419 header->pe.pe_code_size = size;
2420 size = assembly->sections [MONO_SECTION_RSRC].size;
2421 size += FILE_ALIGN - 1;
2422 size &= ~(FILE_ALIGN - 1);
2423 header->pe.pe_data_size = size;
2424 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2425 header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
2426 header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
2427 /* pe_rva_entry_point always at the beginning of the text section */
2428 header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
2430 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2431 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2432 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2433 header->nt.pe_os_major = GUINT16_FROM_LE (4);
2434 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2435 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2436 size = section_start;
2437 size += FILE_ALIGN - 1;
2438 size &= ~(FILE_ALIGN - 1);
2439 header->nt.pe_header_size = GUINT32_FROM_LE (size);
2441 size += VIRT_ALIGN - 1;
2442 size &= ~(VIRT_ALIGN - 1);
2443 header->nt.pe_image_size = GUINT32_FROM_LE (size);
2444 header->nt.pe_subsys_required = GUINT16_FROM_LE (3); /* 3 -> cmdline app, 2 -> GUI app */
2445 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2446 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2447 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2448 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2449 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2450 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2452 /* fill data directory entries */
2454 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2455 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2457 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2458 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2460 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2461 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2462 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2463 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2464 /* patch imported function RVA name */
2465 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2466 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2468 /* the import table */
2469 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2470 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2471 /* patch imported dll RVA name and other entries in the dir */
2472 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2473 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
2474 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2475 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2476 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2477 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2479 rva = (guint32*)(assembly->code.data + assembly->ilt_offset);
2480 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset - 2);
2482 /* the CLI header info */
2483 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2484 cli_header->ch_size = GUINT32_FROM_LE (72);
2485 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
2486 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
2487 if (assemblyb->entry_point)
2488 cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
2490 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
2491 cli_header->ch_metadata.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->code.index);
2492 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
2494 /* write the section tables and section content */
2495 section = (MonoSectionTable*)(pefile->data + section_start);
2496 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2497 static const char *section_names [] = {
2498 ".text", ".rsrc", ".reloc"
2500 if (!assembly->sections [i].size)
2502 strcpy (section->st_name, section_names [i]);
2503 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
2504 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
2505 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
2506 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
2507 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
2508 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
2509 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
2511 case MONO_SECTION_TEXT:
2512 /* patch entry point */
2513 rva = (guint32*)(assembly->code.data + 2);
2514 *rva = GUINT32_FROM_LE (virtual_base + assembly->text_rva + assembly->iat_offset);
2515 memcpy (pefile->data + assembly->sections [i].offset, assembly->code.data, assembly->code.index);
2516 memcpy (pefile->data + assembly->sections [i].offset + assembly->code.index, assembly->assembly.image->raw_metadata, assembly->meta_size);
2518 case MONO_SECTION_RELOC:
2519 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
2520 *rva = GUINT32_FROM_LE (assembly->text_rva);
2522 *rva = GUINT32_FROM_LE (12);
2524 data16 = (guint16*)rva;
2526 * the entrypoint is always at the start of the text section
2527 * 3 is IMAGE_REL_BASED_HIGHLOW
2528 * 2 is patch_size_rva - text_rva
2530 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
2532 *data16 = 0; /* terminate */
2534 case MONO_SECTION_RSRC:
2536 g_assert_not_reached ();
2541 /* check that the file is properly padded */
2544 FILE *f = fopen ("mypetest.exe", "w");
2545 fwrite (pefile->data, pefile->index, 1, f);
2552 * We need to return always the same object for MethodInfo, FieldInfo etc..
2553 * type uses a different hash, since it uses custom hash/equal functions.
2555 static MonoGHashTable *object_cache = NULL;
2556 static MonoGHashTable *type_cache = NULL;
2558 #define CHECK_OBJECT(t,p) \
2561 if (!object_cache) \
2562 object_cache = mono_g_hash_table_new (g_direct_hash, g_direct_equal); \
2563 if ((_obj = mono_g_hash_table_lookup (object_cache, (p)))) \
2567 #define CACHE_OBJECT(p,o) \
2569 mono_g_hash_table_insert (object_cache, p,o); \
2573 * mono_assembly_get_object:
2574 * @domain: an app domain
2575 * @assembly: an assembly
2577 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
2579 MonoReflectionAssembly*
2580 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
2582 static MonoClass *System_Reflection_Assembly;
2583 MonoReflectionAssembly *res;
2585 CHECK_OBJECT (MonoReflectionAssembly *, assembly);
2586 if (!System_Reflection_Assembly)
2587 System_Reflection_Assembly = mono_class_from_name (
2588 mono_defaults.corlib, "System.Reflection", "Assembly");
2589 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
2590 res->assembly = assembly;
2591 CACHE_OBJECT (assembly, res);
2596 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
2598 if ((t1->type != t2->type) ||
2599 (t1->byref != t2->byref))
2603 case MONO_TYPE_VOID:
2604 case MONO_TYPE_BOOLEAN:
2605 case MONO_TYPE_CHAR:
2616 case MONO_TYPE_STRING:
2619 case MONO_TYPE_OBJECT:
2621 case MONO_TYPE_VALUETYPE:
2622 case MONO_TYPE_CLASS:
2623 return t1->data.klass == t2->data.klass;
2625 case MONO_TYPE_SZARRAY:
2626 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
2627 case MONO_TYPE_ARRAY:
2628 if (t1->data.array->rank != t2->data.array->rank)
2630 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
2632 g_error ("implement type compare for %0x!", t1->type);
2640 mymono_metadata_type_hash (MonoType *t1)
2646 hash |= t1->byref << 6; /* do not collide with t1->type values */
2648 case MONO_TYPE_VALUETYPE:
2649 case MONO_TYPE_CLASS:
2650 /* check if the distribution is good enough */
2651 return hash << 7 | g_str_hash (t1->data.klass->name);
2653 case MONO_TYPE_SZARRAY:
2654 return hash << 7 | mymono_metadata_type_hash (t1->data.type);
2660 * mono_type_get_object:
2661 * @domain: an app domain
2664 * Return an System.MonoType object representing the type @type.
2667 mono_type_get_object (MonoDomain *domain, MonoType *type)
2669 MonoReflectionType *res;
2670 MonoClass *klass = mono_class_from_mono_type (type);
2673 type_cache = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
2674 (GCompareFunc)mymono_metadata_type_equal);
2675 if ((res = mono_g_hash_table_lookup (type_cache, type)))
2677 if (klass->reflection_info) {
2678 /* should this be considered an error condition? */
2680 return klass->reflection_info;
2682 mono_class_init (klass);
2683 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
2685 mono_g_hash_table_insert (type_cache, type, res);
2690 * mono_method_get_object:
2691 * @domain: an app domain
2694 * Return an System.Reflection.MonoMethod object representing the method @method.
2696 MonoReflectionMethod*
2697 mono_method_get_object (MonoDomain *domain, MonoMethod *method)
2700 * We use the same C representation for methods and constructors, but the type
2701 * name in C# is different.
2705 MonoReflectionMethod *ret;
2707 CHECK_OBJECT (MonoReflectionMethod *, method);
2708 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
2709 cname = "MonoCMethod";
2711 cname = "MonoMethod";
2712 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
2714 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
2715 ret->method = method;
2716 ret->name = mono_string_new (domain, method->name);
2717 CACHE_OBJECT (method, ret);
2722 * mono_field_get_object:
2723 * @domain: an app domain
2727 * Return an System.Reflection.MonoField object representing the field @field
2730 MonoReflectionField*
2731 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
2733 MonoReflectionField *res;
2736 CHECK_OBJECT (MonoReflectionField *, field);
2737 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
2738 res = (MonoReflectionField *)mono_object_new (domain, oklass);
2741 CACHE_OBJECT (field, res);
2746 * mono_property_get_object:
2747 * @domain: an app domain
2749 * @property: a property
2751 * Return an System.Reflection.MonoProperty object representing the property @property
2754 MonoReflectionProperty*
2755 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
2757 MonoReflectionProperty *res;
2760 CHECK_OBJECT (MonoReflectionProperty *, property);
2761 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
2762 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
2764 res->property = property;
2765 CACHE_OBJECT (property, res);
2770 * mono_event_get_object:
2771 * @domain: an app domain
2775 * Return an System.Reflection.MonoEvent object representing the event @event
2778 MonoReflectionEvent*
2779 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
2781 MonoReflectionEvent *res;
2784 CHECK_OBJECT (MonoReflectionEvent *, event);
2785 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
2786 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
2789 CACHE_OBJECT (event, res);
2794 * mono_param_get_objects:
2795 * @domain: an app domain
2798 * Return an System.Reflection.ParameterInfo array object representing the parameters
2799 * in the method @method.
2801 MonoReflectionParameter**
2802 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
2804 MonoReflectionParameter **res;
2805 MonoReflectionMethod *member;
2810 if (!method->signature->param_count)
2813 member = mono_method_get_object (domain, method);
2814 names = g_new (char *, method->signature->param_count);
2815 mono_method_get_param_names (method, (const char **) names);
2817 /* Note: the cache is based on the address of the signature into the method
2818 * since we already cache MethodInfos with the method as keys.
2820 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature));
2821 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
2823 res = GC_malloc (sizeof (MonoReflectionParameter*) * method->signature->param_count);
2825 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
2827 for (i = 0; i < method->signature->param_count; ++i) {
2828 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
2829 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
2830 res [i]->DefaultValueImpl = NULL; /* FIXME */
2831 res [i]->MemberImpl = (MonoObject*)member;
2832 res [i]->NameImpl = mono_string_new (domain, names [i]);
2833 res [i]->PositionImpl = i + 1;
2834 res [i]->AttrsImpl = method->signature->params [i]->attrs;
2837 CACHE_OBJECT (&(method->signature), res);
2842 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
2846 memset (assembly, 0, sizeof (MonoAssemblyName));
2848 assembly->culture = "";
2850 while (*p && (isalnum (*p) || *p == '.'))
2855 while (*p == ' ' || *p == ',') {
2864 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
2866 assembly->major = strtoul (p, &s, 10);
2867 if (s == p || *s != '.')
2870 assembly->minor = strtoul (p, &s, 10);
2871 if (s == p || *s != '.')
2874 assembly->build = strtoul (p, &s, 10);
2875 if (s == p || *s != '.')
2878 assembly->revision = strtoul (p, &s, 10);
2881 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
2883 if (strncmp (p, "neutral", 7) == 0) {
2884 assembly->culture = "";
2887 assembly->culture = p;
2888 while (*p && *p != ',') {
2892 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
2895 while (*s && isxdigit (*s)) {
2899 assembly->hash_len = s - p;
2900 if (!(s-p) || ((s-p) & 1))
2902 assembly->hash_value = s = p;
2903 while (*s && isxdigit (*s)) {
2905 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
2908 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
2916 while (*p == ' ' || *p == ',') {
2930 * mono_reflection_parse_type:
2933 * Parse a type name as accepted by the GetType () method and output the info
2934 * extracted in the info structure.
2935 * the name param will be mangled, so, make a copy before passing it to this function.
2936 * The fields in info will be valid until the memory pointed to by name is valid.
2937 * Returns 0 on parse error.
2938 * See also mono_type_get_name () below.
2941 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
2943 char *start, *p, *w, *last_point, *startn;
2944 int in_modifiers = 0;
2945 int isbyref = 0, rank;
2947 start = p = w = name;
2949 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
2950 info->name = info->name_space = NULL;
2951 info->nested = NULL;
2952 info->modifiers = NULL;
2954 /* last_point separates the namespace from the name */
2960 *p = 0; /* NULL terminate the name */
2962 /* we have parsed the nesting namespace + name */
2964 info->nested = g_list_append (info->nested, startn);
2968 info->name_space = start;
2970 info->name = last_point + 1;
2972 info->name_space = (char *)"";
2997 info->nested = g_list_append (info->nested, startn);
3000 info->name_space = start;
3002 info->name = last_point + 1;
3004 info->name_space = (char *)"";
3011 if (isbyref) /* only one level allowed by the spec */
3014 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
3018 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
3029 else if (*p != '*') /* '*' means unknown lower bound */
3035 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
3047 return 0; /* missing assembly name */
3048 if (!assembly_name_to_aname (&info->assembly, p))
3054 if (info->assembly.name)
3057 *w = 0; /* terminate class name */
3058 if (!info->name || !*info->name)
3060 /* add other consistency checks */
3065 mono_type_get_name_recurse (MonoType *type, GString *str)
3069 switch (type->type) {
3070 case MONO_TYPE_ARRAY: {
3071 int i, rank = type->data.array->rank;
3073 mono_type_get_name_recurse (type->data.array->type, str);
3074 g_string_append_c (str, '[');
3075 for (i = 1; i < rank; i++)
3076 g_string_append_c (str, ',');
3077 g_string_append_c (str, ']');
3080 case MONO_TYPE_SZARRAY:
3081 mono_type_get_name_recurse (type->data.type, str);
3082 g_string_append (str, "[]");
3085 mono_type_get_name_recurse (type->data.type, str);
3086 g_string_append_c (str, '*');
3089 klass = mono_class_from_mono_type (type);
3090 if (klass->nested_in) {
3091 mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
3092 g_string_append_c (str, '+');
3094 if (*klass->name_space) {
3095 g_string_append (str, klass->name_space);
3096 g_string_append_c (str, '.');
3098 g_string_append (str, klass->name);
3104 * mono_type_get_name:
3107 * Returns the string representation for type as required by System.Reflection.
3108 * The inverse of mono_reflection_parse_type ().
3111 mono_type_get_name (MonoType *type)
3113 GString* result = g_string_new ("");
3114 mono_type_get_name_recurse (type, result);
3117 g_string_append_c (result, '&');
3119 return g_string_free (result, FALSE);
3123 * mono_reflection_get_type:
3124 * @image: a metadata context
3125 * @info: type description structure
3126 * @ignorecase: flag for case-insensitive string compares
3128 * Build a MonoType from the type description in @info.
3132 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
3139 image = mono_defaults.corlib;
3142 klass = mono_class_from_name_case (image, info->name_space, info->name);
3144 klass = mono_class_from_name (image, info->name_space, info->name);
3147 for (mod = info->nested; mod; mod = mod->next) {
3150 mono_class_init (klass);
3151 nested = klass->nested_classes;
3154 klass = nested->data;
3156 if (g_strcasecmp (klass->name, mod->data) == 0)
3159 if (strcmp (klass->name, mod->data) == 0)
3163 nested = nested->next;
3170 mono_class_init (klass);
3171 for (mod = info->modifiers; mod; mod = mod->next) {
3172 modval = GPOINTER_TO_UINT (mod->data);
3173 if (!modval) { /* byref: must be last modifier */
3174 return &klass->this_arg;
3175 } else if (modval == -1) {
3176 klass = mono_ptr_class_get (&klass->byval_arg);
3177 } else { /* array rank */
3178 klass = mono_array_class_get (&klass->byval_arg, modval);
3180 mono_class_init (klass);
3182 return &klass->byval_arg;
3186 * mono_reflection_type_from_name:
3188 * @image: a metadata context (can be NULL).
3190 * Retrieves a MonoType from its @name. If the name is not fully qualified,
3191 * it defaults to get the type from @image or, if @image is NULL or loading
3192 * from it fails, uses corlib.
3196 mono_reflection_type_from_name (char *name, MonoImage *image)
3199 MonoTypeNameParse info;
3201 /*g_print ("requested type %s\n", str);*/
3202 if (!mono_reflection_parse_type (name, &info)) {
3203 g_list_free (info.modifiers);
3204 g_list_free (info.nested);
3208 if (info.assembly.name) {
3209 image = mono_image_loaded (info.assembly.name);
3210 /* do we need to load if it's not already loaded? */
3212 g_list_free (info.modifiers);
3213 g_list_free (info.nested);
3216 } else if (image == NULL) {
3217 image = mono_defaults.corlib;
3220 type = mono_reflection_get_type (image, &info, FALSE);
3221 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
3222 image = mono_defaults.corlib;
3223 type = mono_reflection_get_type (image, &info, FALSE);
3226 g_list_free (info.modifiers);
3227 g_list_free (info.nested);
3232 * Optimization we could avoid mallocing() an little-endian archs that
3233 * don't crash with unaligned accesses.
3236 fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
3237 int len, i, slen, type;
3238 const char *p = mono_metadata_blob_heap (image, blobidx);
3240 len = mono_metadata_decode_value (p, &p);
3241 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
3246 for (i = 0; i < sig->param_count; ++i) {
3247 type = sig->params [i]->type;
3252 case MONO_TYPE_BOOLEAN: {
3253 MonoBoolean *bval = params [i] = g_malloc (sizeof (MonoBoolean));
3258 case MONO_TYPE_CHAR:
3260 case MONO_TYPE_I2: {
3261 guint16 *val = params [i] = g_malloc (sizeof (guint16));
3266 #if SIZEOF_VOID_P == 4
3272 case MONO_TYPE_I4: {
3273 guint32 *val = params [i] = g_malloc (sizeof (guint32));
3278 #if SIZEOF_VOID_P == 8
3279 case MONO_TYPE_U: /* error out instead? this should probably not happen */
3284 case MONO_TYPE_I8: {
3285 guint64 *val = params [i] = g_malloc (sizeof (guint64));
3290 case MONO_TYPE_VALUETYPE:
3291 if (sig->params [i]->data.klass->enumtype) {
3292 type = sig->params [i]->data.klass->enum_basetype->type;
3295 g_warning ("generic valutype %s not handled in custom attr value decoding", sig->params [i]->data.klass->name);
3298 case MONO_TYPE_STRING: {
3299 slen = mono_metadata_decode_value (p, &p);
3300 params [i] = mono_string_new_len (mono_domain_get (), p, slen);
3304 case MONO_TYPE_CLASS: {
3307 slen = mono_metadata_decode_value (p, &p);
3308 n = g_memdup (p, slen + 1);
3310 t = mono_reflection_type_from_name (n, image);
3312 g_warning ("Cannot load type '%s'", n);
3314 params [i] = mono_type_get_object (mono_domain_get (), t);
3318 g_warning ("Type 0x%02x not handled in custom attr value decoding", sig->params [i]->type);
3325 free_param_data (MonoMethodSignature *sig, void **params) {
3327 for (i = 0; i < sig->param_count; ++i) {
3328 switch (sig->params [i]->type) {
3329 case MONO_TYPE_BOOLEAN:
3330 case MONO_TYPE_CHAR:
3343 case MONO_TYPE_VALUETYPE:
3344 g_free (params [i]);
3353 * Find the method index in the metadata methodDef table.
3354 * Later put these three helper methods in metadata and export them.
3357 find_method_index (MonoMethod *method) {
3358 MonoClass *klass = method->klass;
3361 for (i = 0; i < klass->method.count; ++i) {
3362 if (method == klass->methods [i])
3363 return klass->method.first + 1 + i;
3369 * Find the field index in the metadata FieldDef table.
3372 find_field_index (MonoClass *klass, MonoClassField *field) {
3375 for (i = 0; i < klass->field.count; ++i) {
3376 if (field == &klass->fields [i])
3377 return klass->field.first + 1 + i;
3383 * Find the property index in the metadata Property table.
3386 find_property_index (MonoClass *klass, MonoProperty *property) {
3389 for (i = 0; i < klass->property.count; ++i) {
3390 if (property == &klass->properties [i])
3391 return klass->property.first + 1 + i;
3397 * Find the event index in the metadata Event table.
3400 find_event_index (MonoClass *klass, MonoEvent *event) {
3403 for (i = 0; i < klass->event.count; ++i) {
3404 if (event == &klass->events [i])
3405 return klass->event.first + 1 + i;
3411 * mono_reflection_get_custom_attrs:
3412 * @obj: a reflection object handle
3414 * Return an array with all the custom attributes defined of the
3415 * reflection handle @obj. The objects are fully build.
3418 mono_reflection_get_custom_attrs (MonoObject *obj)
3420 guint32 idx, mtoken, i, len;
3421 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
3431 klass = obj->vtable->klass;
3432 /* FIXME: need to handle: Module */
3433 if (klass == mono_defaults.monotype_class) {
3434 MonoReflectionType *rtype = (MonoReflectionType*)obj;
3435 klass = mono_class_from_mono_type (rtype->type);
3436 idx = mono_metadata_token_index (klass->type_token);
3437 idx <<= CUSTOM_ATTR_BITS;
3438 idx |= CUSTOM_ATTR_TYPEDEF;
3439 image = klass->image;
3440 } else if (strcmp ("Assembly", klass->name) == 0) {
3441 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
3442 idx = 1; /* there is only one assembly */
3443 idx <<= CUSTOM_ATTR_BITS;
3444 idx |= CUSTOM_ATTR_ASSEMBLY;
3445 image = rassembly->assembly->image;
3446 } else if (strcmp ("MonoProperty", klass->name) == 0) {
3447 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
3448 idx = find_property_index (rprop->klass, rprop->property);
3449 idx <<= CUSTOM_ATTR_BITS;
3450 idx |= CUSTOM_ATTR_PROPERTY;
3451 image = rprop->klass->image;
3452 } else if (strcmp ("MonoEvent", klass->name) == 0) {
3453 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
3454 idx = find_event_index (revent->klass, revent->event);
3455 idx <<= CUSTOM_ATTR_BITS;
3456 idx |= CUSTOM_ATTR_EVENT;
3457 image = revent->klass->image;
3458 } else if (strcmp ("MonoField", klass->name) == 0) {
3459 MonoReflectionField *rfield = (MonoReflectionField*)obj;
3460 idx = find_field_index (rfield->klass, rfield->field);
3461 idx <<= CUSTOM_ATTR_BITS;
3462 idx |= CUSTOM_ATTR_FIELDDEF;
3463 image = rfield->klass->image;
3464 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
3465 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
3466 idx = find_method_index (rmethod->method);
3467 idx <<= CUSTOM_ATTR_BITS;
3468 idx |= CUSTOM_ATTR_METHODDEF;
3469 image = rmethod->method->klass->image;
3470 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
3471 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
3472 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
3473 guint32 method_index = find_method_index (rmethod->method);
3474 guint32 param_list, param_last, param_pos, found;
3476 image = rmethod->method->klass->image;
3477 ca = &image->tables [MONO_TABLE_METHOD];
3479 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
3480 if (method_index == ca->rows) {
3481 ca = &image->tables [MONO_TABLE_PARAM];
3482 param_last = ca->rows + 1;
3484 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
3485 ca = &image->tables [MONO_TABLE_PARAM];
3488 for (i = param_list; i < param_last; ++i) {
3489 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
3490 if (param_pos == param->PositionImpl) {
3496 return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
3498 idx <<= CUSTOM_ATTR_BITS;
3499 idx |= CUSTOM_ATTR_PARAMDEF;
3500 } else { /* handle other types here... */
3501 g_error ("get custom attrs not yet supported for %s", klass->name);
3504 /* at this point image and index are set correctly for searching the custom attr */
3505 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3506 /* the table is not sorted */
3507 for (i = 0; i < ca->rows; ++i) {
3508 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
3509 if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
3511 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
3512 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
3513 case CUSTOM_ATTR_TYPE_METHODDEF:
3514 mtoken |= MONO_TOKEN_METHOD_DEF;
3516 case CUSTOM_ATTR_TYPE_MEMBERREF:
3517 mtoken |= MONO_TOKEN_MEMBER_REF;
3520 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
3523 method = mono_get_method (image, mtoken, NULL);
3525 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
3526 mono_class_init (method->klass);
3527 /*g_print ("got attr %s\n", method->klass->name);*/
3528 params = g_new (void*, method->signature->param_count);
3529 fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
3530 attr = mono_object_new (mono_domain_get (), method->klass);
3531 mono_runtime_invoke (method, attr, params, NULL);
3532 list = g_list_prepend (list, attr);
3533 free_param_data (method->signature, params);
3537 len = g_list_length (list);
3539 * The return type is really object[], but System/Attribute.cs does a cast
3540 * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
3541 * probably fix that.
3543 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
3544 result = mono_array_new (mono_domain_get (), klass, len);
3545 for (i = 0; i < len; ++i) {
3546 mono_array_set (result, gpointer, i, list->data);
3549 g_list_free (g_list_first (list));
3554 static MonoMethodSignature*
3555 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
3556 MonoMethodSignature *sig;
3559 count = ctor->parameters? mono_array_length (ctor->parameters): 0;
3561 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
3563 sig->param_count = count;
3564 sig->sentinelpos = -1; /* FIXME */
3565 for (i = 0; i < count; ++i) {
3566 MonoReflectionType *pt = mono_array_get (ctor->parameters, MonoReflectionType*, i);
3567 sig->params [i] = pt->type;
3573 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
3575 MonoClass *klass = mono_object_class (prop);
3576 if (strcmp (klass->name, "PropertyBuilder") == 0) {
3577 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
3578 *name = mono_string_to_utf8 (pb->name);
3579 *type = pb->type->type;
3581 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
3582 *name = g_strdup (p->property->name);
3583 if (p->property->get)
3584 *type = p->property->get->signature->ret;
3586 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
3591 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
3593 MonoClass *klass = mono_object_class (field);
3594 if (strcmp (klass->name, "FieldBuilder") == 0) {
3595 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
3596 *name = mono_string_to_utf8 (fb->name);
3597 *type = fb->type->type;
3599 MonoReflectionField *f = (MonoReflectionField *)field;
3600 *name = g_strdup (f->field->name);
3601 *type = f->field->type;
3606 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
3607 char *name, *result;
3611 name = mono_type_get_name (type);
3612 klass = my_mono_class_from_mono_type (type);
3613 ta = klass->image->assembly;
3614 if (ta == ass || klass->image == mono_defaults.corlib)
3617 /* missing public key */
3618 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
3619 name, ta->aname.name,
3620 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
3621 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
3627 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
3630 MonoTypeEnum simple_type;
3632 if ((p-buffer) + 10 >= *buflen) {
3635 newbuf = g_realloc (buffer, *buflen);
3636 p = newbuf + (p-buffer);
3639 argval = ((char*)arg + sizeof (MonoObject));
3640 simple_type = type->type;
3642 switch (simple_type) {
3643 case MONO_TYPE_BOOLEAN:
3648 case MONO_TYPE_CHAR:
3651 swap_with_size (p, argval, 2, 1);
3657 swap_with_size (p, argval, 4, 1);
3663 swap_with_size (p, argval, 8, 1);
3666 case MONO_TYPE_VALUETYPE:
3667 if (type->data.klass->enumtype) {
3668 simple_type = type->data.klass->enum_basetype->type;
3671 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
3674 case MONO_TYPE_STRING: {
3675 char *str = mono_string_to_utf8 ((MonoString*)arg);
3676 guint32 slen = strlen (str);
3677 if ((p-buffer) + 10 + slen >= *buflen) {
3681 newbuf = g_realloc (buffer, *buflen);
3682 p = newbuf + (p-buffer);
3685 mono_metadata_encode_value (slen, p, &p);
3686 memcpy (p, str, slen);
3691 case MONO_TYPE_CLASS: {
3694 MonoClass *k = mono_object_class (arg);
3695 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
3696 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
3697 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
3699 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
3700 slen = strlen (str);
3701 if ((p-buffer) + 10 + slen >= *buflen) {
3705 newbuf = g_realloc (buffer, *buflen);
3706 p = newbuf + (p-buffer);
3709 mono_metadata_encode_value (slen, p, &p);
3710 memcpy (p, str, slen);
3715 /* it may be a boxed value or a Type */
3716 case MONO_TYPE_OBJECT: {
3717 MonoClass *klass = mono_object_class (arg);
3721 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
3724 } else if (klass->enumtype) {
3726 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
3727 *p++ = simple_type = klass->byval_arg.type;
3730 g_error ("unhandled type in custom attr");
3732 str = type_get_qualified_name (klass->enum_basetype, NULL);
3733 slen = strlen (str);
3734 if ((p-buffer) + 10 + slen >= *buflen) {
3738 newbuf = g_realloc (buffer, *buflen);
3739 p = newbuf + (p-buffer);
3742 mono_metadata_encode_value (slen, p, &p);
3743 memcpy (p, str, slen);
3746 simple_type = klass->enum_basetype->type;
3750 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
3753 *retbuffer = buffer;
3757 * mono_reflection_get_custom_attrs_blob:
3758 * @ctor: custom attribute constructor
3759 * @ctorArgs: arguments o the constructor
3765 * Creates the blob of data that needs to be saved in the metadata and that represents
3766 * the custom attributed described by @ctor, @ctorArgs etc.
3767 * Returns: a Byte array representing the blob of data.
3770 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) {
3772 MonoMethodSignature *sig;
3777 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3778 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
3780 sig = ((MonoReflectionMethod*)ctor)->method->signature;
3783 p = buffer = g_malloc (buflen);
3784 /* write the prolog */
3787 for (i = 0; i < sig->param_count; ++i) {
3788 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
3789 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
3793 i += mono_array_length (properties);
3795 i += mono_array_length (fields);
3797 *p++ = (i >> 8) & 0xff;
3800 for (i = 0; i < mono_array_length (properties); ++i) {
3805 prop = mono_array_get (properties, gpointer, i);
3806 get_prop_name_and_type (prop, &pname, &ptype);
3807 *p++ = 0x54; /* PROPERTY signature */
3808 len = strlen (pname);
3809 mono_metadata_encode_value (len, p, &p);
3810 memcpy (p, pname, len);
3812 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
3819 for (i = 0; i < mono_array_length (fields); ++i) {
3824 field = mono_array_get (fields, gpointer, i);
3825 get_field_name_and_type (field, &fname, &ftype);
3826 *p++ = 0x53; /* FIELD signature */
3827 len = strlen (fname);
3828 mono_metadata_encode_value (len, p, &p);
3829 memcpy (p, fname, len);
3831 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
3836 g_assert (p - buffer <= buflen);
3837 buflen = p - buffer;
3838 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
3839 p = mono_array_addr (result, char, 0);
3840 memcpy (p, buffer, buflen);
3842 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
3848 * mono_reflection_setup_internal_class:
3849 * @tb: a TypeBuilder object
3851 * Creates a MonoClass that represents the TypeBuilder.
3852 * This is a trick that lets us simplify a lot of reflection code
3853 * (and will allow us to support Build and Run assemblies easier).
3856 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
3858 MonoClass *klass, *parent;
3860 klass = g_new0 (MonoClass, 1);
3862 klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
3865 /* check so we can compile corlib correctly */
3866 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
3867 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
3868 parent = tb->parent->type->data.klass;
3870 parent = my_mono_class_from_mono_type (tb->parent->type);
3874 klass->inited = 1; /* we lie to the runtime */
3875 klass->name = mono_string_to_utf8 (tb->name);
3876 klass->name_space = mono_string_to_utf8 (tb->nspace);
3877 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
3878 klass->flags = tb->attrs;
3880 klass->element_class = klass;
3881 klass->reflection_info = tb; /* need to pin. */
3884 mono_class_setup_parent (klass, parent);
3885 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
3886 const char *old_n = klass->name;
3887 /* trick to get relative numbering right when compiling corlib */
3888 klass->name = "BuildingObject";
3889 mono_class_setup_parent (klass, mono_defaults.object_class);
3890 klass->name = old_n;
3892 mono_class_setup_mono_type (klass);
3895 * FIXME: handle interfaces.
3898 tb->type.type = &klass->byval_arg;
3900 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
3904 * mono_reflection_create_internal_class:
3905 * @tb: a TypeBuilder object
3907 * Actually create the MonoClass that is associated with the TypeBuilder.
3910 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
3914 klass = my_mono_class_from_mono_type (tb->type.type);
3916 if (klass->enumtype && klass->enum_basetype == NULL) {
3917 MonoReflectionFieldBuilder *fb;
3919 g_assert (tb->fields != NULL);
3920 g_assert (mono_array_length (tb->fields) >= 1);
3922 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
3924 klass->enum_basetype = fb->type->type;
3925 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
3930 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
3932 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
3933 guint32 na = mono_array_length (sig->arguments);
3938 p = buf = g_malloc (10 + na * 10);
3940 mono_metadata_encode_value (0x07, p, &p);
3941 mono_metadata_encode_value (na, p, &p);
3942 for (i = 0; i < na; ++i) {
3943 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
3944 encode_reflection_type (assembly, type, p, &p);
3948 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
3949 p = mono_array_addr (result, char, 0);
3950 memcpy (p, buf, buflen);
3957 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
3959 MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
3960 guint32 na = mono_array_length (sig->arguments);
3965 p = buf = g_malloc (10 + na * 10);
3967 mono_metadata_encode_value (0x06, p, &p);
3968 for (i = 0; i < na; ++i) {
3969 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
3970 encode_reflection_type (assembly, type, p, &p);
3974 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
3975 p = mono_array_addr (result, char, 0);
3976 memcpy (p, buf, buflen);