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"
22 #include "rawbuffer.h"
23 #include "mono-endian.h"
26 #define TEXT_OFFSET 512
27 #define CLI_H_SIZE 136
28 #define FILE_ALIGN 512
31 MonoReflectionILGen *ilgen;
32 MonoReflectionType *rtype;
33 MonoArray *parameters;
38 guint32 *table_idx; /* note: it's a pointer */
42 } ReflectionMethodBuilder;
44 const unsigned char table_sizes [64] = {
54 MONO_INTERFACEIMPL_SIZE,
55 MONO_MEMBERREF_SIZE, /* 0x0A */
57 MONO_CUSTOM_ATTR_SIZE,
58 MONO_FIELD_MARSHAL_SIZE,
59 MONO_DECL_SECURITY_SIZE,
60 MONO_CLASS_LAYOUT_SIZE,
61 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
62 MONO_STAND_ALONE_SIGNATURE_SIZE,
66 MONO_PROPERTY_MAP_SIZE,
69 MONO_METHOD_SEMA_SIZE,
71 MONO_MODULEREF_SIZE, /* 0x1A */
77 MONO_ASSEMBLY_SIZE, /* 0x20 */
78 MONO_ASSEMBLY_PROCESSOR_SIZE,
80 MONO_ASSEMBLYREF_SIZE,
81 MONO_ASSEMBLYREFPROC_SIZE,
82 MONO_ASSEMBLYREFOS_SIZE,
86 MONO_NESTED_CLASS_SIZE,
90 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
91 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
94 alloc_table (MonoDynamicTable *table, guint nrows)
97 g_assert (table->columns);
98 table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
102 string_heap_insert (MonoStringHeap *sh, const char *str)
106 gpointer oldkey, oldval;
108 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
109 return GPOINTER_TO_UINT (oldval);
111 len = strlen (str) + 1;
113 if (idx + len > sh->alloc_size) {
114 sh->alloc_size += len + 4096;
115 sh->data = g_realloc (sh->data, sh->alloc_size);
118 * We strdup the string even if we already copy them in sh->data
119 * so that the string pointers in the hash remain valid even if
120 * we need to realloc sh->data. We may want to avoid that later.
122 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
123 memcpy (sh->data + idx, str, len);
129 string_heap_init (MonoStringHeap *sh)
132 sh->alloc_size = 4096;
133 sh->data = g_malloc (4096);
134 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
135 string_heap_insert (sh, "");
139 string_heap_free (MonoStringHeap *sh)
142 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
143 g_hash_table_destroy (sh->hash);
147 mono_image_add_stream_data (MonoDynamicStream *stream, char *data, guint32 len)
150 if (stream->alloc_size < stream->index + len) {
151 stream->alloc_size += len + 4096;
152 stream->data = g_realloc (stream->data, stream->alloc_size);
154 memcpy (stream->data + stream->index, data, len);
156 stream->index += len;
158 * align index? Not without adding an additional param that controls it since
159 * we may store a blob value in pieces.
165 stream_data_align (MonoDynamicStream *stream)
168 guint32 count = stream->index % 4;
170 /* we assume the stream data will be aligned */
172 mono_image_add_stream_data (stream, buf, 4 - count);
176 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
179 g_assert_not_reached ();
184 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
188 case MONO_TYPE_BOOLEAN:
202 case MONO_TYPE_STRING:
203 case MONO_TYPE_OBJECT:
204 case MONO_TYPE_TYPEDBYREF:
205 mono_metadata_encode_value (type->type, p, &p);
207 case MONO_TYPE_SZARRAY:
208 mono_metadata_encode_value (type->type, p, &p);
209 encode_type (assembly, type->data.type, p, &p);
211 case MONO_TYPE_VALUETYPE:
212 case MONO_TYPE_CLASS:
213 mono_metadata_encode_value (type->type, p, &p);
214 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
217 g_error ("need to encode type %x", type->type);
223 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
225 MonoReflectionTypeBuilder *tb;
229 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
233 encode_type (assembly, type->type, p, endbuf);
237 tb = (MonoReflectionTypeBuilder*) type;
238 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS); /* typedef */
240 /* FIXME: handle other base types (need to have also some hacks to compile corlib) ... */
241 /* FIXME: handle byref ... */
242 mono_metadata_encode_value (MONO_TYPE_CLASS, p, &p);
243 mono_metadata_encode_value (token, p, endbuf);
244 /*g_print ("encoding type %s to 0x%08x\n", mono_string_to_utf8 (tb->name), token);*/
248 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
253 guint32 nparams = sig->param_count;
254 guint32 size = 10 + nparams * 10;
259 p = buf = g_malloc (size);
261 * FIXME: vararg, explicit_this, differenc call_conv values...
263 *p = sig->call_convention;
265 *p |= 0x20; /* hasthis */
267 mono_metadata_encode_value (nparams, p, &p);
268 encode_type (assembly, sig->ret, p, &p);
269 for (i = 0; i < nparams; ++i)
270 encode_type (assembly, sig->params [i], p, &p);
272 mono_metadata_encode_value (p-buf, b, &b);
273 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
274 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
280 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
283 * FIXME: reuse code from method_encode_signature().
288 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
289 guint32 size = 10 + nparams * 10;
294 p = buf = g_malloc (size);
295 /* LAMESPEC: all the call conv spec is foobared */
296 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
297 if (mb->call_conv & 2)
298 *p |= 0x5; /* vararg */
299 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
300 *p |= 0x20; /* hasthis */
302 mono_metadata_encode_value (nparams, p, &p);
303 encode_reflection_type (assembly, mb->rtype, p, &p);
304 for (i = 0; i < nparams; ++i) {
305 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
306 encode_reflection_type (assembly, pt, p, &p);
309 mono_metadata_encode_value (p-buf, b, &b);
310 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
311 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
317 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
319 MonoDynamicTable *table;
322 guint32 idx, sig_idx;
323 guint nl = mono_array_length (ilgen->locals);
329 p = buf = g_malloc (10 + nl * 10);
330 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
331 idx = table->next_idx ++;
333 alloc_table (table, table->rows);
334 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
336 mono_metadata_encode_value (0x07, p, &p);
337 mono_metadata_encode_value (nl, p, &p);
338 for (i = 0; i < nl; ++i) {
339 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
340 encode_reflection_type (assembly, lb->type, p, &p);
342 mono_metadata_encode_value (p-buf, b, &b);
343 sig_idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
344 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
347 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
353 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
355 /* we use only tiny formats now: need to implement ILGenerator */
360 gint32 num_locals = 0;
361 gint32 num_exception = 0;
364 char fat_header [12];
367 guint32 local_sig = 0;
368 guint32 header_size = 12;
371 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
372 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
373 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
374 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
378 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
380 code = mb->ilgen->code;
381 code_size = mb->ilgen->code_len;
382 max_stack = mb->ilgen->max_stack;
383 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
384 if (mb->ilgen->ex_handlers) {
385 MonoILExceptionInfo *ex_info;
386 for (i = 0; i < mono_array_length (mb->ilgen->ex_handlers); ++i) {
387 ex_info = (MonoILExceptionInfo*)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
388 if (ex_info->handlers)
389 num_exception += mono_array_length (ex_info->handlers);
396 code_size = mono_array_length (code);
397 max_stack = 8; /* we probably need to run a verifier on the code... */
400 /* check for exceptions, maxstack, locals */
401 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
403 if (code_size < 64 && !(code_size & 1)) {
404 flags = (code_size << 2) | 0x2;
405 } else if (code_size < 32 && (code_size & 1)) {
406 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
410 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
411 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
412 return assembly->text_rva + idx + CLI_H_SIZE;
416 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
418 * FIXME: need to set also the header size in fat_flags.
419 * (and more sects and init locals flags)
423 fat_flags |= METHOD_HEADER_MORE_SECTS;
424 fat_header [0] = fat_flags;
425 fat_header [1] = (header_size / 4 ) << 4;
426 shortp = (guint16*)(fat_header + 2);
428 intp = (guint32*)(fat_header + 4);
430 intp = (guint32*)(fat_header + 8);
432 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
433 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
435 unsigned char sheader [4];
436 MonoExceptionClause clause;
437 MonoILExceptionInfo * ex_info;
438 MonoILExceptionBlock * ex_block;
441 stream_data_align (&assembly->code);
442 /* always use fat format for now */
443 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
444 num_exception *= sizeof (MonoExceptionClause);
445 sheader [1] = num_exception & 0xff;
446 sheader [2] = (num_exception >> 8) & 0xff;
447 sheader [3] = (num_exception >> 16) & 0xff;
448 mono_image_add_stream_data (&assembly->code, sheader, 4);
449 /* fat header, so we are already aligned */
451 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
452 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
453 if (ex_info->handlers) {
454 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
455 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
456 clause.flags = ex_block->type;
457 clause.try_offset = ex_info->start;
458 clause.try_len = ex_info->len;
459 clause.handler_offset = ex_block->start;
460 clause.handler_len = ex_block->len;
461 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
462 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
463 /* FIXME: ENOENDIAN */
464 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
467 g_error ("No clauses");
471 return assembly->text_rva + idx + CLI_H_SIZE;
475 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 index)
478 MonoDynamicTable *table;
481 table = &assembly->tables [table_idx];
483 g_assert (col < table->columns);
485 values = table->values + table->columns;
486 for (i = 1; i <= table->rows; ++i) {
487 if (values [col] == index)
494 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
496 MonoDynamicTable *table;
501 /* room in this table is already allocated */
502 table = &assembly->tables [MONO_TABLE_METHOD];
503 *mb->table_idx = table->next_idx ++;
504 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
506 name = mono_string_to_utf8 (mb->name);
507 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
509 } else { /* a constructor */
510 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
512 values [MONO_METHOD_FLAGS] = mb->attrs;
513 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
514 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
515 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
517 table = &assembly->tables [MONO_TABLE_PARAM];
518 values [MONO_METHOD_PARAMLIST] = table->next_idx;
522 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
523 if (mono_array_get (mb->pinfo, gpointer, i))
526 table->rows += count;
527 alloc_table (table, table->rows);
528 values = table->values + table->next_idx * MONO_PARAM_SIZE;
529 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
530 MonoReflectionParamBuilder *pb;
531 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
532 values [MONO_PARAM_FLAGS] = pb->attrs;
533 values [MONO_PARAM_SEQUENCE] = i;
534 name = mono_string_to_utf8 (pb->name);
535 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
537 values += MONO_PARAM_SIZE;
545 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
547 MonoDynamicTable *table;
550 ReflectionMethodBuilder rmb;
552 rmb.ilgen = mb->ilgen;
553 rmb.rtype = mb->rtype;
554 rmb.parameters = mb->parameters;
555 rmb.pinfo = mb->pinfo;
556 rmb.attrs = mb->attrs;
557 rmb.iattrs = mb->iattrs;
558 rmb.call_conv = mb->call_conv;
562 rmb.table_idx = &mb->table_idx;
564 mono_image_basic_method (&rmb, assembly);
566 if (mb->dll) { /* It's a P/Invoke method */
568 table = &assembly->tables [MONO_TABLE_IMPLMAP];
570 alloc_table (table, table->rows);
571 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
572 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
573 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
574 name = mono_string_to_utf8 (mb->dllentry);
575 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
577 name = mono_string_to_utf8 (mb->dll);
578 moduleref = string_heap_insert (&assembly->sheap, name);
580 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
581 table = &assembly->tables [MONO_TABLE_MODULEREF];
583 alloc_table (table, table->rows);
584 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
585 values [MONO_IMPLMAP_SCOPE] = table->rows;
588 if (mb->override_method) {
589 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
590 table = &assembly->tables [MONO_TABLE_METHODIMPL];
592 alloc_table (table, table->rows);
593 values = table->values + table->rows * MONO_MTHODIMPL_SIZE;
594 values [MONO_MTHODIMPL_CLASS] = tb->table_idx;
595 values [MONO_MTHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
596 if (mb->override_method->method)
597 values [MONO_MTHODIMPL_DECLARATION] = mono_image_get_methodref_token (assembly, mb->override_method->method);
599 MonoReflectionMethodBuilder *omb = (MonoReflectionMethodBuilder*)mb->override_method;
600 values [MONO_MTHODIMPL_DECLARATION] = METHODDEFORREF_METHODDEF | (omb->table_idx << METHODDEFORREF_BITS);
606 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
608 ReflectionMethodBuilder rmb;
610 rmb.ilgen = mb->ilgen;
611 rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
612 rmb.parameters = mb->parameters;
613 rmb.pinfo = mb->pinfo;
614 rmb.attrs = mb->attrs;
615 rmb.iattrs = mb->iattrs;
616 rmb.call_conv = mb->call_conv;
620 rmb.table_idx = &mb->table_idx;
622 mono_image_basic_method (&rmb, assembly);
627 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
635 p = buf = g_malloc (64);
637 /* No start code with field refs...
638 * mono_metadata_encode_value (0x06, p, &p);
640 /* encode custom attributes before the type */
641 encode_type (assembly, field->type, p, &p);
642 g_assert (p-buf < 64);
643 mono_metadata_encode_value (p-buf, b, &b);
644 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
645 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
651 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
659 p = buf = g_malloc (64);
661 mono_metadata_encode_value (0x06, p, &p);
662 /* encode custom attributes before the type */
663 encode_reflection_type (assembly, fb->type, p, &p);
664 g_assert (p-buf < 64);
665 mono_metadata_encode_value (p-buf, b, &b);
666 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
667 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
673 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
680 p = buf = g_malloc (64);
682 box_val = ((char*)val) + sizeof (MonoObject);
683 *ret_type = val->vtable->klass->byval_arg.type;
685 case MONO_TYPE_BOOLEAN:
705 case MONO_TYPE_STRING:
707 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
710 /* there is no signature */
711 mono_metadata_encode_value (len, b, &b);
712 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
713 /* FIXME: ENOENDIAN */
714 mono_image_add_stream_data (&assembly->blob, box_val, len);
721 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
723 MonoDynamicTable *table;
727 table = &assembly->tables [MONO_TABLE_FIELD];
728 fb->table_idx = table->next_idx ++;
729 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
730 name = mono_string_to_utf8 (fb->name);
731 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
733 values [MONO_FIELD_FLAGS] = fb->attrs;
734 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
736 if (fb->offset != -1) {
737 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
739 alloc_table (table, table->rows);
740 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
741 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
742 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
744 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
745 guint32 field_type = 0;
746 table = &assembly->tables [MONO_TABLE_CONSTANT];
748 alloc_table (table, table->rows);
749 values = table->values + table->rows * MONO_CONSTANT_SIZE;
750 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
751 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
752 values [MONO_CONSTANT_TYPE] = field_type;
753 values [MONO_CONSTANT_PADDING] = 0;
758 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
764 MonoReflectionMethodBuilder *mb = fb->get_method;
767 if (mb && mb->parameters)
768 nparams = mono_array_length (mb->parameters);
769 buf = p = g_malloc (24 + nparams * 10);
772 mono_metadata_encode_value (nparams, p, &p);
774 encode_reflection_type (assembly, mb->rtype, p, &p);
775 for (i = 0; i < nparams; ++i) {
776 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
777 encode_reflection_type (assembly, pt, p, &p);
780 *p++ = 1; /* void: a property should probably not be allowed without a getter */
783 mono_metadata_encode_value (p-buf, b, &b);
784 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
785 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
791 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
793 MonoDynamicTable *table;
796 guint num_methods = 0;
800 * we need to set things in the following tables:
801 * PROPERTYMAP (info already filled in _get_type_info ())
802 * PROPERTY (rows already preallocated in _get_type_info ())
803 * METHOD (method info already done with the generic method code)
806 table = &assembly->tables [MONO_TABLE_PROPERTY];
807 pb->table_idx = table->next_idx ++;
808 values = table->values + pb->table_idx * MONO_FIELD_SIZE;
809 name = mono_string_to_utf8 (pb->name);
810 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
812 values [MONO_PROPERTY_FLAGS] = pb->attrs;
813 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
815 /* FIXME: we still don't handle 'other' methods */
816 if (pb->get_method) num_methods ++;
817 if (pb->set_method) num_methods ++;
819 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
820 table->rows += num_methods;
821 alloc_table (table, table->rows);
823 if (pb->get_method) {
824 semaidx = table->next_idx ++;
825 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
826 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
827 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
828 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
830 if (pb->set_method) {
831 semaidx = table->next_idx ++;
832 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
833 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
834 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
835 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
840 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
842 if (image != mono_defaults.corlib)
843 g_error ("multiple assemblyref not yet supported");
844 /* first row in assemblyref */
845 return (1 << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_ASSEMBLYREF;
849 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
851 MonoDynamicTable *table;
856 if (!assembly->typeref)
857 assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
859 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
862 klass = type->data.klass;
864 * If it's in the same module:
865 * return TYPEDEFORREF_TYPEDEF | ((klass->token & 0xffffff) << TYPEDEFORREF_BITS)
868 table = &assembly->tables [MONO_TABLE_TYPEREF];
869 alloc_table (table, table->rows + 1);
870 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
871 values [MONO_TYPEREF_SCOPE] = resolution_scope_from_image (assembly, klass->image);
872 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
873 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
874 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
875 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
881 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoClass *klass, const char *name, guint32 sig)
883 MonoDynamicTable *table;
885 guint32 token, pclass;
889 * FIXME: we need to cache the token.
891 parent = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
892 switch (parent & TYPEDEFORREF_MASK) {
893 case TYPEDEFORREF_TYPEREF:
894 pclass = MEMBERREF_PARENT_TYPEREF;
896 case TYPEDEFORREF_TYPESPEC:
897 pclass = MEMBERREF_PARENT_TYPESPEC;
899 case TYPEDEFORREF_TYPEDEF:
900 /* should never get here */
902 g_error ("unknow typeref or def token");
904 /* extract the index */
905 parent >>= TYPEDEFORREF_BITS;
907 table = &assembly->tables [MONO_TABLE_MEMBERREF];
908 alloc_table (table, table->rows + 1);
909 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
910 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
911 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
912 values [MONO_MEMBERREF_SIGNATURE] = sig;
913 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
920 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
922 return mono_image_get_memberref_token (assembly, method->klass,
923 method->name, method_encode_signature (assembly, method->signature));
927 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
929 return mono_image_get_memberref_token (assembly, klass,
930 field->name, fieldref_encode_signature (assembly, field));
934 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
936 MonoDynamicTable *table;
941 table = &assembly->tables [MONO_TABLE_TYPEDEF];
942 tb->table_idx = table->next_idx ++;
943 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
944 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
945 if (tb->parent) { /* interfaces don't have a parent */
946 if (tb->parent->type)
947 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
949 MonoReflectionTypeBuilder *ptb = (MonoReflectionTypeBuilder *)tb->parent;
950 values [MONO_TYPEDEF_EXTENDS] = TYPEDEFORREF_TYPEDEF | (ptb->table_idx << TYPEDEFORREF_BITS);
953 values [MONO_TYPEDEF_EXTENDS] = 0;
954 n = mono_string_to_utf8 (tb->name);
955 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
957 n = mono_string_to_utf8 (tb->nspace);
958 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
960 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
961 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
964 * FIXME: constructors and methods need to be output in the same order
965 * as they are defined (according to table_idx).
968 /* handle constructors */
970 table = &assembly->tables [MONO_TABLE_METHOD];
971 table->rows += mono_array_length (tb->ctors);
972 alloc_table (table, table->rows);
973 for (i = 0; i < mono_array_length (tb->ctors); ++i)
974 mono_image_get_ctor_info (domain,
975 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
980 table = &assembly->tables [MONO_TABLE_METHOD];
981 table->rows += mono_array_length (tb->methods);
982 alloc_table (table, table->rows);
983 for (i = 0; i < mono_array_length (tb->methods); ++i)
984 mono_image_get_method_info (
985 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
990 table = &assembly->tables [MONO_TABLE_FIELD];
991 table->rows += mono_array_length (tb->fields);
992 alloc_table (table, table->rows);
993 for (i = 0; i < mono_array_length (tb->fields); ++i)
994 mono_image_get_field_info (
995 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
998 /* Do the same with properties etc.. */
999 if (tb->properties && mono_array_length (tb->properties)) {
1000 table = &assembly->tables [MONO_TABLE_PROPERTY];
1001 table->rows += mono_array_length (tb->properties);
1002 alloc_table (table, table->rows);
1003 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1005 alloc_table (table, table->rows);
1006 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1007 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1008 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1009 for (i = 0; i < mono_array_length (tb->properties); ++i)
1010 mono_image_get_property_info (
1011 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1014 MonoDynamicTable *ntable;
1016 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1017 table->rows += mono_array_length (tb->subtypes);
1018 alloc_table (table, table->rows);
1020 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1021 ntable->rows += mono_array_length (tb->subtypes);
1022 alloc_table (ntable, ntable->rows);
1023 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1025 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1026 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1028 mono_image_get_type_info (domain, subtype, assembly);
1029 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1030 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1031 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1032 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1033 mono_string_to_utf8 (tb->name), tb->table_idx,
1034 ntable->next_idx, ntable->rows);*/
1035 values += MONO_NESTED_CLASS_SIZE;
1042 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1044 MonoDynamicTable *table;
1048 table = &assembly->tables [MONO_TABLE_MODULE];
1049 mb->table_idx = table->next_idx ++;
1050 name = mono_string_to_utf8 (mb->module.name);
1051 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1053 /* need to set mvid? */
1056 * fill-in info in other tables as well.
1058 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1059 table->rows += mono_array_length (mb->types);
1060 alloc_table (table, table->rows);
1061 for (i = 0; i < mono_array_length (mb->types); ++i)
1062 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1065 #define align_pointer(base,p)\
1067 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1069 (p) += 4 - (__diff & 3);\
1073 build_compressed_metadata (MonoDynamicAssembly *assembly)
1076 guint64 valid_mask = 0;
1077 guint32 heapt_size = 0;
1078 guint32 meta_size = 256; /* allow for header and other stuff */
1079 guint32 table_offset;
1080 guint32 ntables = 0;
1086 char *version = "mono" VERSION;
1088 /* Compute table sizes */
1089 meta = assembly->assembly.image = g_new0 (MonoImage, 1);
1091 /* Setup the info used by compute_sizes () */
1092 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1093 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1094 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1096 meta_size += assembly->blob.index;
1097 meta_size += assembly->guid.index;
1098 meta_size += assembly->sheap.index;
1099 meta_size += assembly->us.index;
1101 for (i=0; i < 64; ++i)
1102 meta->tables [i].rows = assembly->tables [i].rows;
1104 for (i = 0; i < 64; i++){
1105 if (meta->tables [i].rows == 0)
1107 valid_mask |= (guint64)1 << i;
1109 meta->tables [i].row_size = mono_metadata_compute_size (
1110 meta, i, &meta->tables [i].size_bitfield);
1111 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1113 heapt_size += 24; /* #~ header size */
1114 heapt_size += ntables * 4;
1115 meta_size += heapt_size;
1116 meta->raw_metadata = g_malloc0 (meta_size);
1117 p = meta->raw_metadata;
1118 /* the metadata signature */
1119 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1120 /* version numbers and 4 bytes reserved */
1121 int16val = (guint16*)p;
1125 /* version string */
1126 int32val = (guint32*)p;
1127 *int32val = strlen (version);
1129 memcpy (p, version, *int32val);
1131 align_pointer (meta->raw_metadata, p);
1132 int16val = (guint16*)p;
1133 *int16val++ = 0; /* flags must be 0 */
1134 *int16val = 5; /* number of streams */
1138 * write the stream info.
1140 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1141 table_offset += 3; table_offset &= ~3;
1143 int32val = (guint32*)p;
1144 *int32val++ = assembly->tstream.offset = table_offset;
1145 *int32val = heapt_size;
1146 table_offset += *int32val;
1147 table_offset += 3; table_offset &= ~3;
1151 align_pointer (meta->raw_metadata, p);
1153 int32val = (guint32*)p;
1154 *int32val++ = assembly->sheap.offset = table_offset;
1155 *int32val = assembly->sheap.index;
1156 table_offset += *int32val;
1157 table_offset += 3; table_offset &= ~3;
1159 strcpy (p, "#Strings");
1161 align_pointer (meta->raw_metadata, p);
1163 int32val = (guint32*)p;
1164 *int32val++ = assembly->us.offset = table_offset;
1165 *int32val = assembly->us.index;
1166 table_offset += *int32val;
1167 table_offset += 3; table_offset &= ~3;
1171 align_pointer (meta->raw_metadata, p);
1173 int32val = (guint32*)p;
1174 *int32val++ = assembly->blob.offset = table_offset;
1175 *int32val = assembly->blob.index;
1176 table_offset += *int32val;
1177 table_offset += 3; table_offset &= ~3;
1179 strcpy (p, "#Blob");
1181 align_pointer (meta->raw_metadata, p);
1183 int32val = (guint32*)p;
1184 *int32val++ = assembly->guid.offset = table_offset;
1185 *int32val = assembly->guid.index;
1186 table_offset += *int32val;
1187 table_offset += 3; table_offset &= ~3;
1189 strcpy (p, "#GUID");
1191 align_pointer (meta->raw_metadata, p);
1194 * now copy the data, the table stream header and contents goes first.
1196 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1197 p = meta->raw_metadata + assembly->tstream.offset;
1198 int32val = (guint32*)p;
1199 *int32val = 0; /* reserved */
1201 *p++ = 1; /* version */
1203 if (meta->idx_string_wide)
1205 if (meta->idx_guid_wide)
1207 if (meta->idx_blob_wide)
1210 *p++ = 0; /* reserved */
1211 int64val = (guint64*)p;
1212 *int64val++ = valid_mask;
1213 *int64val++ = 0; /* bitvector of sorted tables, set to 0 for now */
1215 int32val = (guint32*)p;
1216 for (i = 0; i < 64; i++){
1217 if (meta->tables [i].rows == 0)
1219 *int32val++ = meta->tables [i].rows;
1221 p = (unsigned char*)int32val;
1222 /* compress the tables */
1223 for (i = 0; i < 64; i++){
1226 guint32 bitfield = meta->tables [i].size_bitfield;
1227 if (!meta->tables [i].rows)
1229 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1230 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1231 meta->tables [i].base = p;
1232 for (row = 1; row <= meta->tables [i].rows; ++row) {
1233 values = assembly->tables [i].values + row * assembly->tables [i].columns;
1234 for (col = 0; col < assembly->tables [i].columns; ++col) {
1235 switch (mono_metadata_table_size (bitfield, col)) {
1237 *p++ = values [col];
1240 int16val = (guint16*)p;
1241 *int16val = values [col];
1245 int32val = (guint32*)p;
1246 *int32val = values [col];
1250 g_assert_not_reached ();
1254 g_assert ((p - (unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1257 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1258 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1259 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1260 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1261 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1263 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1267 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
1269 MonoDynamicTable *table;
1270 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
1271 MonoDomain *domain = ((MonoObject *)assemblyb)->vtable->domain;
1277 assembly->text_rva = 0x00002000;
1279 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
1280 alloc_table (table, 1);
1281 values = table->values + MONO_ASSEMBLY_SIZE;
1282 values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
1283 name = mono_string_to_utf8 (assemblyb->name);
1284 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
1286 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
1287 values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
1288 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1289 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1290 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1291 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1293 assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
1294 assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
1296 len = mono_array_length (assemblyb->modules);
1297 table = &assembly->tables [MONO_TABLE_MODULE];
1298 alloc_table (table, len);
1299 for (i = 0; i < len; ++i)
1300 mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
1302 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1304 * table->rows is already set above and in mono_image_fill_module_table.
1306 alloc_table (table, table->rows);
1308 * Set the first entry.
1310 values = table->values + table->columns;
1311 values [MONO_TYPEDEF_FLAGS] = 0;
1312 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
1313 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
1314 values [MONO_TYPEDEF_EXTENDS] = 0;
1315 values [MONO_TYPEDEF_FIELD_LIST] = 1;
1316 values [MONO_TYPEDEF_METHOD_LIST] = 1;
1318 /* later include all the assemblies referenced */
1319 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1320 alloc_table (table, 1);
1321 values = table->values + table->columns;
1322 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "corlib");
1323 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 0;
1324 values [MONO_ASSEMBLYREF_MINOR_VERSION] = 0;
1325 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 0;
1326 values [MONO_ASSEMBLYREF_REV_NUMBER] = 0;
1327 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1328 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1329 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1330 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1332 build_compressed_metadata (assembly);
1336 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
1342 if (!assembly->dynamic_assembly)
1343 mono_image_basic_init (assembly);
1344 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
1345 index = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
1346 /* FIXME: ENOENDIAN */
1347 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (char*)mono_string_chars (str), str->length * 2);
1348 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
1349 return MONO_TOKEN_STRING | index;
1353 * Get a token to insert in the IL code stream for the given MemberInfo.
1355 * ConstructorBuilder
1365 mono_image_create_token (MonoReflectionAssemblyBuilder *assembly, MonoObject *obj)
1367 MonoClass *klass = obj->vtable->klass;
1370 mono_image_basic_init (assembly);
1372 if (strcmp (klass->name, "MethodBuilder") == 0) {
1373 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
1374 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1375 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1378 if (strcmp (klass->name, "ConstructorBuilder") == 0) {
1379 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
1380 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1381 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1384 if (strcmp (klass->name, "FieldBuilder") == 0) {
1385 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
1386 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
1388 if (strcmp (klass->name, "TypeBuilder") == 0) {
1389 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
1390 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
1392 if (strcmp (klass->name, "MonoType") == 0) {
1393 MonoReflectionType *tb = (MonoReflectionType *)obj;
1394 return mono_metadata_token_from_dor (
1395 mono_image_typedef_or_ref (assembly->dynamic_assembly, tb->type));
1397 if (strcmp (klass->name, "MonoCMethod") == 0 ||
1398 strcmp (klass->name, "MonoMethod") == 0) {
1399 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
1400 token = mono_image_get_methodref_token (assembly->dynamic_assembly, m->method);
1401 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1404 if (strcmp (klass->name, "MonoField") == 0) {
1405 MonoReflectionField *f = (MonoReflectionField *)obj;
1406 token = mono_image_get_fieldref_token (assembly->dynamic_assembly, f->field, f->klass);
1407 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1410 g_print ("requested token for %s\n", klass->name);
1415 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1417 MonoDynamicAssembly *assembly;
1420 if (assemblyb->dynamic_assembly)
1423 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1425 string_heap_init (&assembly->sheap);
1426 mono_image_add_stream_data (&assembly->us, "", 1);
1427 mono_image_add_stream_data (&assembly->blob, "", 1);
1429 for (i=0; i < 64; ++i) {
1430 assembly->tables [i].next_idx = 1;
1431 assembly->tables [i].columns = table_sizes [i];
1437 mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, int maxsize)
1439 MonoMSDOSHeader *msdos;
1440 MonoDotNetHeader *header;
1441 MonoSectionTable *section;
1442 MonoCLIHeader *cli_header;
1443 guint32 header_size = TEXT_OFFSET + CLI_H_SIZE;
1444 MonoDynamicAssembly *assembly;
1446 static const unsigned char msheader[] = {
1447 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
1448 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
1451 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
1452 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
1453 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
1454 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1457 if (maxsize < header_size)
1460 mono_image_basic_init (assemblyb);
1461 assembly = assemblyb->dynamic_assembly;
1463 mono_image_build_metadata (assemblyb);
1465 memset (buffer, 0, header_size);
1466 memcpy (buffer, msheader, sizeof (MonoMSDOSHeader));
1468 msdos = (MonoMSDOSHeader *)buffer;
1469 header = (MonoDotNetHeader *)(buffer + sizeof (MonoMSDOSHeader));
1470 section = (MonoSectionTable*) (buffer + sizeof (MonoMSDOSHeader) + sizeof (MonoDotNetHeader));
1472 /* FIXME: ENDIAN problem: byteswap as needed */
1473 msdos->pe_offset = sizeof (MonoMSDOSHeader);
1475 header->pesig [0] = 'P';
1476 header->pesig [1] = 'E';
1477 header->pesig [2] = header->pesig [3] = 0;
1479 header->coff.coff_machine = 0x14c;
1480 header->coff.coff_sections = 1; /* only .text supported now */
1481 header->coff.coff_time = time (NULL);
1482 header->coff.coff_opt_header_size = sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4;
1484 header->coff.coff_attributes = 0x010e;
1486 //header->coff.coff_attributes = 0x210e;
1487 header->pe.pe_magic = 0x10B;
1488 header->pe.pe_major = 6;
1489 header->pe.pe_minor = 0;
1490 /* need to set: pe_code_size pe_data_size pe_rva_entry_point pe_rva_code_base pe_rva_data_base */
1492 header->nt.pe_image_base = 0x400000;
1493 header->nt.pe_section_align = 8192;
1494 header->nt.pe_file_alignment = FILE_ALIGN;
1495 header->nt.pe_os_major = 4;
1496 header->nt.pe_os_minor = 0;
1497 header->nt.pe_subsys_major = 4;
1498 /* need to set pe_image_size, pe_header_size */
1499 header->nt.pe_subsys_required = 3; /* 3 -> cmdline app, 2 -> GUI app */
1500 header->nt.pe_stack_reserve = 0x00100000;
1501 header->nt.pe_stack_commit = 0x00001000;
1502 header->nt.pe_heap_reserve = 0x00100000;
1503 header->nt.pe_heap_commit = 0x00001000;
1504 header->nt.pe_loader_flags = 1;
1505 header->nt.pe_data_dir_count = 16;
1509 header->datadir.pe_import_table
1514 header->datadir.pe_cli_header.size = CLI_H_SIZE;
1515 header->datadir.pe_cli_header.rva = assembly->text_rva; /* we put it always at the beginning */
1517 /* Write section tables */
1518 strcpy (section->st_name, ".text");
1519 section->st_virtual_size = 1024; /* FIXME */
1520 section->st_virtual_address = assembly->text_rva;
1521 section->st_raw_data_size = 1024; /* FIXME */
1522 section->st_raw_data_ptr = TEXT_OFFSET;
1523 section->st_flags = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
1526 * align: build_compressed_metadata () assumes metadata is aligned
1528 * cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1530 assembly->code.index += 3;
1531 assembly->code.index &= ~3;
1534 * Write the MonoCLIHeader header
1536 cli_header = (MonoCLIHeader*)(buffer + TEXT_OFFSET);
1537 cli_header->ch_size = CLI_H_SIZE;
1538 cli_header->ch_runtime_major = 2;
1539 cli_header->ch_flags = CLI_FLAGS_ILONLY;
1540 if (assemblyb->entry_point)
1541 cli_header->ch_entry_point = assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF;
1543 cli_header->ch_entry_point = 0;
1544 cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1545 cli_header->ch_metadata.size = assembly->meta_size;
1551 * We need to return always the same object for Type, MethodInfo, FieldInfo etc..
1553 static GHashTable *object_cache = NULL;
1555 #define CHECK_OBJECT(t,p) \
1558 if (!object_cache) \
1559 object_cache = g_hash_table_new (g_direct_hash, g_direct_equal); \
1560 if ((_obj = g_hash_table_lookup (object_cache, (p)))) \
1564 #define CACHE_OBJECT(p,o) \
1566 g_hash_table_insert (object_cache, p,o); \
1569 MonoReflectionAssembly*
1570 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
1572 static MonoClass *System_Reflection_Assembly;
1573 MonoReflectionAssembly *res;
1575 CHECK_OBJECT (MonoReflectionAssembly *, assembly);
1576 if (!System_Reflection_Assembly)
1577 System_Reflection_Assembly = mono_class_from_name (
1578 mono_defaults.corlib, "System.Reflection", "Assembly");
1579 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
1580 res->assembly = assembly;
1581 CACHE_OBJECT (assembly, res);
1586 mono_type_get_object (MonoDomain *domain, MonoType *type)
1588 MonoReflectionType *res;
1592 * FIXME: type may come from the cache in metadata.c, we hand out only
1593 * the types from a MonoClass structure: the long term fix is to just
1594 * load corlib always and remove the cache in metadata.c altogether.
1595 * Or we may still handle it this way so we can store in MonoType additional info
1598 klass = mono_class_from_mono_type (type);
1599 if ((type != &klass->byval_arg) && (type != &klass->this_arg)) {
1601 type = &klass->this_arg;
1603 type = &klass->byval_arg;
1605 CHECK_OBJECT (MonoReflectionType *, type);
1606 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
1608 CACHE_OBJECT (type, res);
1612 MonoReflectionMethod*
1613 mono_method_get_object (MonoDomain *domain, MonoMethod *method)
1616 * We use the same C representation for methods and constructors, but the type
1617 * name in C# is different.
1621 MonoReflectionMethod *ret;
1623 CHECK_OBJECT (MonoReflectionMethod *, method);
1624 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
1625 cname = "MonoCMethod";
1627 cname = "MonoMethod";
1628 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
1630 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
1631 ret->method = method;
1632 CACHE_OBJECT (method, ret);
1636 MonoReflectionField*
1637 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
1639 MonoReflectionField *res;
1642 CHECK_OBJECT (MonoReflectionField *, field);
1643 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
1644 res = (MonoReflectionField *)mono_object_new (domain, oklass);
1647 CACHE_OBJECT (field, res);
1651 MonoReflectionProperty*
1652 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
1654 MonoReflectionProperty *res;
1657 CHECK_OBJECT (MonoReflectionProperty *, property);
1658 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
1659 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
1661 res->property = property;
1662 CACHE_OBJECT (property, res);
1666 MonoReflectionParameter**
1667 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
1669 MonoReflectionParameter **res;
1670 MonoReflectionMethod *member;
1675 if (!method->signature->param_count)
1678 member = mono_method_get_object (domain, method);
1679 names = g_new (char*, method->signature->param_count);
1680 mono_method_get_param_names (method, names);
1682 /* Note: the cache is based on the address of the signature into the method
1683 * since we already cache MethodInfos with the method as keys.
1685 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature));
1686 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
1687 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
1688 for (i = 0; i < method->signature->param_count; ++i) {
1689 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
1690 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
1691 res [i]->DefaultValueImpl = NULL; /* FIXME */
1692 res [i]->MemberImpl = (MonoObject*)member;
1693 res [i]->NameImpl = mono_string_new (domain, names [i]);
1694 res [i]->PositionImpl = i + 1;
1695 res [i]->AttrsImpl = method->signature->params [i]->attrs;
1698 CACHE_OBJECT (&(method->signature), res);
1703 * Parse a type name as accepted by the GetType () method and output the info
1704 * extracted in the info structure.
1705 * the name param will be mangled, so, make a copy before passing it to this function.
1706 * The fields in info will be valid until the memory pointed to by name is valid.
1707 * Returns 0 on parse error.
1710 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
1712 char *start, *p, *w, *last_point;
1713 int in_modifiers = 0;
1715 start = p = w = name;
1717 info->name = info->name_space = info->assembly = NULL;
1718 info->nest_name = info->nest_name_space = NULL;
1719 info->rank = info->isbyref = info->ispointer = 0;
1726 /* we have parsed the nesting namespace + name */
1728 info->nest_name_space = start;
1730 info->nest_name = last_point + 1;
1732 info->nest_name_space = "";
1733 info->nest_name = start;
1735 *p = 0; /* NULL terminate */
1760 info->name_space = start;
1762 info->name = last_point + 1;
1764 info->name_space = "";
1767 /* FIXME: we don't mainatin an order for byref, pointer and array... */
1775 info->ispointer = 1;
1801 return 0; /* missing assembly name */
1808 *w = 0; /* terminate class name */
1809 if (!info->name || !*info->name)
1811 if (info->nest_name && !*info->nest_name)
1813 /* add other consistency checks */