3 * reflection.c: Routines for creating an image at runtime.
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2001 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 (MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
608 ReflectionMethodBuilder rmb;
610 rmb.ilgen = mb->ilgen;
611 rmb.rtype = mono_type_get_object (&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->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 (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 (
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 (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 (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 (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;
1276 assembly->text_rva = 0x00002000;
1278 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
1279 alloc_table (table, 1);
1280 values = table->values + MONO_ASSEMBLY_SIZE;
1281 values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
1282 name = mono_string_to_utf8 (assemblyb->name);
1283 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
1285 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
1286 values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
1287 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1288 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1289 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1290 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1292 assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
1293 assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
1295 len = mono_array_length (assemblyb->modules);
1296 table = &assembly->tables [MONO_TABLE_MODULE];
1297 alloc_table (table, len);
1298 for (i = 0; i < len; ++i)
1299 mono_image_fill_module_table (mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
1301 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1303 * table->rows is already set above and in mono_image_fill_module_table.
1305 alloc_table (table, table->rows);
1307 * Set the first entry.
1309 values = table->values + table->columns;
1310 values [MONO_TYPEDEF_FLAGS] = 0;
1311 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
1312 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
1313 values [MONO_TYPEDEF_EXTENDS] = 0;
1314 values [MONO_TYPEDEF_FIELD_LIST] = 1;
1315 values [MONO_TYPEDEF_METHOD_LIST] = 1;
1317 /* later include all the assemblies referenced */
1318 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1319 alloc_table (table, 1);
1320 values = table->values + table->columns;
1321 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "corlib");
1322 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 0;
1323 values [MONO_ASSEMBLYREF_MINOR_VERSION] = 0;
1324 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 0;
1325 values [MONO_ASSEMBLYREF_REV_NUMBER] = 0;
1326 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1327 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1328 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1329 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1331 build_compressed_metadata (assembly);
1335 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
1341 if (!assembly->dynamic_assembly)
1342 mono_image_basic_init (assembly);
1343 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
1344 index = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
1345 /* FIXME: ENOENDIAN */
1346 mono_image_add_stream_data (&assembly->dynamic_assembly->us, (char*)mono_string_chars (str), str->length * 2);
1347 mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
1348 return MONO_TOKEN_STRING | index;
1352 * Get a token to insert in the IL code stream for the given MemberInfo.
1354 * ConstructorBuilder
1364 mono_image_create_token (MonoReflectionAssemblyBuilder *assembly, MonoObject *obj)
1366 MonoClass *klass = obj->klass;
1369 mono_image_basic_init (assembly);
1371 if (strcmp (klass->name, "MethodBuilder") == 0) {
1372 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
1373 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1374 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1377 if (strcmp (klass->name, "ConstructorBuilder") == 0) {
1378 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
1379 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1380 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1383 if (strcmp (klass->name, "FieldBuilder") == 0) {
1384 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
1385 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
1387 if (strcmp (klass->name, "TypeBuilder") == 0) {
1388 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
1389 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
1391 if (strcmp (klass->name, "MonoType") == 0) {
1392 MonoReflectionType *tb = (MonoReflectionType *)obj;
1393 return mono_metadata_token_from_dor (
1394 mono_image_typedef_or_ref (assembly->dynamic_assembly, tb->type));
1396 if (strcmp (klass->name, "MonoCMethod") == 0 ||
1397 strcmp (klass->name, "MonoMethod") == 0) {
1398 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
1399 token = mono_image_get_methodref_token (assembly->dynamic_assembly, m->method);
1400 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1403 if (strcmp (klass->name, "MonoField") == 0) {
1404 MonoReflectionField *f = (MonoReflectionField *)obj;
1405 token = mono_image_get_fieldref_token (assembly->dynamic_assembly, f->field, f->klass);
1406 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1409 g_print ("requested token for %s\n", klass->name);
1414 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1416 MonoDynamicAssembly *assembly;
1419 if (assemblyb->dynamic_assembly)
1422 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1424 string_heap_init (&assembly->sheap);
1425 mono_image_add_stream_data (&assembly->us, "", 1);
1426 mono_image_add_stream_data (&assembly->blob, "", 1);
1428 for (i=0; i < 64; ++i) {
1429 assembly->tables [i].next_idx = 1;
1430 assembly->tables [i].columns = table_sizes [i];
1436 mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, int maxsize)
1438 MonoMSDOSHeader *msdos;
1439 MonoDotNetHeader *header;
1440 MonoSectionTable *section;
1441 MonoCLIHeader *cli_header;
1442 guint32 header_size = TEXT_OFFSET + CLI_H_SIZE;
1443 MonoDynamicAssembly *assembly;
1445 static const unsigned char msheader[] = {
1446 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
1447 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
1450 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
1451 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
1452 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
1453 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1456 if (maxsize < header_size)
1459 mono_image_basic_init (assemblyb);
1460 assembly = assemblyb->dynamic_assembly;
1462 mono_image_build_metadata (assemblyb);
1464 memset (buffer, 0, header_size);
1465 memcpy (buffer, msheader, sizeof (MonoMSDOSHeader));
1467 msdos = (MonoMSDOSHeader *)buffer;
1468 header = (MonoDotNetHeader *)(buffer + sizeof (MonoMSDOSHeader));
1469 section = (MonoSectionTable*) (buffer + sizeof (MonoMSDOSHeader) + sizeof (MonoDotNetHeader));
1471 /* FIXME: ENDIAN problem: byteswap as needed */
1472 msdos->pe_offset = sizeof (MonoMSDOSHeader);
1474 header->pesig [0] = 'P';
1475 header->pesig [1] = 'E';
1476 header->pesig [2] = header->pesig [3] = 0;
1478 header->coff.coff_machine = 0x14c;
1479 header->coff.coff_sections = 1; /* only .text supported now */
1480 header->coff.coff_time = time (NULL);
1481 header->coff.coff_opt_header_size = sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4;
1483 header->coff.coff_attributes = 0x010e;
1485 //header->coff.coff_attributes = 0x210e;
1486 header->pe.pe_magic = 0x10B;
1487 header->pe.pe_major = 6;
1488 header->pe.pe_minor = 0;
1489 /* need to set: pe_code_size pe_data_size pe_rva_entry_point pe_rva_code_base pe_rva_data_base */
1491 header->nt.pe_image_base = 0x400000;
1492 header->nt.pe_section_align = 8192;
1493 header->nt.pe_file_alignment = FILE_ALIGN;
1494 header->nt.pe_os_major = 4;
1495 header->nt.pe_os_minor = 0;
1496 header->nt.pe_subsys_major = 4;
1497 /* need to set pe_image_size, pe_header_size */
1498 header->nt.pe_subsys_required = 3; /* 3 -> cmdline app, 2 -> GUI app */
1499 header->nt.pe_stack_reserve = 0x00100000;
1500 header->nt.pe_stack_commit = 0x00001000;
1501 header->nt.pe_heap_reserve = 0x00100000;
1502 header->nt.pe_heap_commit = 0x00001000;
1503 header->nt.pe_loader_flags = 1;
1504 header->nt.pe_data_dir_count = 16;
1508 header->datadir.pe_import_table
1513 header->datadir.pe_cli_header.size = CLI_H_SIZE;
1514 header->datadir.pe_cli_header.rva = assembly->text_rva; /* we put it always at the beginning */
1516 /* Write section tables */
1517 strcpy (section->st_name, ".text");
1518 section->st_virtual_size = 1024; /* FIXME */
1519 section->st_virtual_address = assembly->text_rva;
1520 section->st_raw_data_size = 1024; /* FIXME */
1521 section->st_raw_data_ptr = TEXT_OFFSET;
1522 section->st_flags = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
1525 * align: build_compressed_metadata () assumes metadata is aligned
1527 * cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1529 assembly->code.index += 3;
1530 assembly->code.index &= ~3;
1533 * Write the MonoCLIHeader header
1535 cli_header = (MonoCLIHeader*)(buffer + TEXT_OFFSET);
1536 cli_header->ch_size = CLI_H_SIZE;
1537 cli_header->ch_runtime_major = 2;
1538 cli_header->ch_flags = CLI_FLAGS_ILONLY;
1539 if (assemblyb->entry_point)
1540 cli_header->ch_entry_point = assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF;
1542 cli_header->ch_entry_point = 0;
1543 cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1544 cli_header->ch_metadata.size = assembly->meta_size;
1550 * We need to return always the same object for Type, MethodInfo, FieldInfo etc..
1552 static GHashTable *object_cache = NULL;
1554 #define CHECK_OBJECT(t,p) \
1557 if (!object_cache) \
1558 object_cache = g_hash_table_new (g_direct_hash, g_direct_equal); \
1559 if ((_obj = g_hash_table_lookup (object_cache, (p)))) \
1563 #define CACHE_OBJECT(p,o) \
1565 g_hash_table_insert (object_cache, p,o); \
1568 MonoReflectionAssembly*
1569 mono_assembly_get_object (MonoAssembly *assembly)
1572 MonoReflectionAssembly *res;
1574 CHECK_OBJECT (MonoReflectionAssembly *, assembly);
1575 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
1576 res = (MonoReflectionAssembly *)mono_object_new (klass);
1577 res->assembly = assembly;
1578 CACHE_OBJECT (assembly, res);
1583 mono_type_get_object (MonoType *type)
1585 MonoReflectionType *res;
1589 * FIXME: type may come from the cache in metadata.c, we hand out only
1590 * the types from a MonoClass structure: the long term fix is to just
1591 * load corlib always and remove the cache in metadata.c altogether.
1592 * Or we may still handle it this way so we can store in MonoType additional info
1595 klass = mono_class_from_mono_type (type);
1596 if ((type != &klass->byval_arg) && (type != &klass->this_arg)) {
1598 type = &klass->this_arg;
1600 type = &klass->byval_arg;
1602 CHECK_OBJECT (MonoReflectionType *, type);
1603 res = (MonoReflectionType *)mono_object_new (mono_defaults.monotype_class);
1605 CACHE_OBJECT (type, res);
1609 MonoReflectionMethod*
1610 mono_method_get_object (MonoMethod *method)
1613 * We use the same C representation for methods and constructors, but the type
1614 * name in C# is different.
1618 MonoReflectionMethod *ret;
1620 CHECK_OBJECT (MonoReflectionMethod *, method);
1621 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
1622 cname = "MonoCMethod";
1624 cname = "MonoMethod";
1625 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
1627 ret = (MonoReflectionMethod*)mono_object_new (klass);
1628 ret->method = method;
1629 CACHE_OBJECT (method, ret);
1633 MonoReflectionField*
1634 mono_field_get_object (MonoClass *klass, MonoClassField *field)
1636 MonoReflectionField *res;
1639 CHECK_OBJECT (MonoReflectionField *, field);
1640 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
1641 res = (MonoReflectionField *)mono_object_new (oklass);
1644 CACHE_OBJECT (field, res);
1648 MonoReflectionProperty*
1649 mono_property_get_object (MonoClass *klass, MonoProperty *property)
1651 MonoReflectionProperty *res;
1654 CHECK_OBJECT (MonoReflectionProperty *, property);
1655 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
1656 res = (MonoReflectionProperty *)mono_object_new (oklass);
1658 res->property = property;
1659 CACHE_OBJECT (property, res);
1663 MonoReflectionParameter**
1664 mono_param_get_objects (MonoMethod *method)
1666 MonoReflectionParameter **res;
1667 MonoReflectionMethod *member;
1672 if (!method->signature->param_count)
1675 member = mono_method_get_object (method);
1676 names = g_new (char*, method->signature->param_count);
1677 mono_method_get_param_names (method, names);
1679 /* Note: the cache is based on the address of the signature into the method
1680 * since we already cache MethodInfos with the method as keys.
1682 CHECK_OBJECT (MonoReflectionParameter**, &(method->signature));
1683 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
1684 res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
1685 for (i = 0; i < method->signature->param_count; ++i) {
1686 res [i] = (MonoReflectionParameter *)mono_object_new (oklass);
1687 res [i]->ClassImpl = mono_type_get_object (method->signature->params [i]);
1688 res [i]->DefaultValueImpl = NULL; /* FIXME */
1689 res [i]->MemberImpl = (MonoObject*)member;
1690 res [i]->NameImpl = mono_string_new (names [i]);
1691 res [i]->PositionImpl = i + 1;
1692 res [i]->AttrsImpl = method->signature->params [i]->attrs;
1695 CACHE_OBJECT (&(method->signature), res);