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
30 const unsigned char table_sizes [64] = {
40 MONO_INTERFACEIMPL_SIZE,
41 MONO_MEMBERREF_SIZE, /* 0x0A */
43 MONO_CUSTOM_ATTR_SIZE,
44 MONO_FIELD_MARSHAL_SIZE,
45 MONO_DECL_SECURITY_SIZE,
46 MONO_CLASS_LAYOUT_SIZE,
47 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
48 MONO_STAND_ALONE_SIGNATURE_SIZE,
52 MONO_PROPERTY_MAP_SIZE,
55 MONO_METHOD_SEMA_SIZE,
57 MONO_MODULEREF_SIZE, /* 0x1A */
63 MONO_ASSEMBLY_SIZE, /* 0x20 */
64 MONO_ASSEMBLY_PROCESSOR_SIZE,
66 MONO_ASSEMBLYREF_SIZE,
67 MONO_ASSEMBLYREFPROC_SIZE,
68 MONO_ASSEMBLYREFOS_SIZE,
72 MONO_NESTED_CLASS_SIZE,
77 alloc_table (MonoDynamicTable *table, guint nrows)
80 g_assert (table->columns);
81 table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
85 string_heap_insert (MonoStringHeap *sh, const char *str)
89 gpointer oldkey, oldval;
91 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
92 return GPOINTER_TO_UINT (oldval);
94 len = strlen (str) + 1;
96 if (idx + len > sh->alloc_size) {
97 sh->alloc_size += len + 4096;
98 sh->data = g_realloc (sh->data, sh->alloc_size);
101 * We strdup the string even if we already copy them in sh->data
102 * so that the string pointers in the hash remain valid even if
103 * we need to realloc sh->data. We may want to avoid that later.
105 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
106 memcpy (sh->data + idx, str, len);
112 string_heap_init (MonoStringHeap *sh)
115 sh->alloc_size = 4096;
116 sh->data = g_malloc (4096);
117 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
118 string_heap_insert (sh, "");
122 string_heap_free (MonoStringHeap *sh)
125 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
126 g_hash_table_destroy (sh->hash);
130 mono_image_add_stream_data (MonoDynamicStream *stream, char *data, guint32 len)
133 if (stream->alloc_size < stream->index + len) {
134 stream->alloc_size += len + 4096;
135 stream->data = g_realloc (stream->data, stream->alloc_size);
137 memcpy (stream->data + stream->index, data, len);
139 stream->index += len;
141 * align index? Not without adding an additional param that controls it since
142 * we may store a blob value in pieces.
148 encode_type (MonoType *type, char *p, char **endbuf)
152 case MONO_TYPE_BOOLEAN:
166 case MONO_TYPE_STRING:
167 case MONO_TYPE_OBJECT:
168 case MONO_TYPE_TYPEDBYREF:
169 mono_metadata_encode_value (type->type, p, endbuf);
171 case MONO_TYPE_SZARRAY:
172 mono_metadata_encode_value (type->type, p, endbuf);
173 encode_type (type->data.type, p, endbuf);
175 case MONO_TYPE_CLASS:
176 mono_metadata_encode_value (type->type, p, endbuf);
177 g_warning ("need to encode class %s", type->data.klass->name);
180 g_error ("need to encode type %x", type->type);
185 method_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionMethodBuilder *mb)
190 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
191 guint32 size = 10 + nparams * 10;
196 p = buf = g_malloc (size);
198 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
199 *p |= 0x20; /* hasthis */
201 * FIXME: set also call convention and explict_this if needed.
204 mono_metadata_encode_value (nparams, p, &p);
205 encode_type (mb->rtype->type, p, &p);
206 for (i = 0; i < nparams; ++i) {
207 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
208 encode_type (pt->type, p, &p);
211 mono_metadata_encode_value (p-buf, b, &b);
212 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
213 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
219 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
221 MonoDynamicTable *table;
224 guint32 idx, sig_idx;
225 guint nl = mono_array_length (ilgen->locals);
231 p = buf = g_malloc (10 + nl * 10);
232 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
233 idx = table->next_idx ++;
235 alloc_table (table, table->rows);
236 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
238 mono_metadata_encode_value (0x07, p, &p);
239 mono_metadata_encode_value (nl, p, &p);
240 for (i = 0; i < nl; ++i) {
241 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
242 encode_type (lb->type->type, p, &p);
244 mono_metadata_encode_value (p-buf, b, &b);
245 sig_idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
246 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
249 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
255 method_encode_code (MonoDynamicAssembly *assembly, MonoReflectionMethodBuilder *mb)
257 /* we use only tiny formats now: need to implement ILGenerator */
262 gint32 num_locals = 0;
263 gint32 num_exception = 0;
266 char fat_header [12];
269 guint32 local_sig = 0;
273 code = mb->ilgen->code;
274 code_size = mb->ilgen->code_len;
275 max_stack = mb->ilgen->max_stack;
276 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
279 code_size = mono_array_length (code);
280 max_stack = 8; /* we probably need to run a verifier on the code... */
283 /* check for exceptions, maxstack, locals */
284 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
286 if (code_size < 64 && !(code_size & 1)) {
287 flags = (code_size << 2) | 0x2;
288 } else if (code_size < 32 && (code_size & 1)) {
289 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
293 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
294 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
295 return assembly->text_rva + idx + CLI_H_SIZE;
299 local_sig = encode_locals (assembly, mb->ilgen);
301 * FIXME: need to set also the header size in fat_flags.
302 * (and more sects and init locals flags)
305 shortp = (guint16*)(fat_header);
307 shortp = (guint16*)(fat_header + 2);
309 intp = (guint32*)(fat_header + 4);
311 intp = (guint32*)(fat_header + 8);
313 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
314 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
315 return assembly->text_rva + idx + CLI_H_SIZE;
319 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
321 MonoDynamicTable *table;
325 table = &assembly->tables [MONO_TABLE_METHOD];
326 mb->table_idx = table->next_idx ++;
327 values = table->values + mb->table_idx * MONO_METHOD_SIZE;
328 name = mono_string_to_utf8 (mb->name);
329 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
331 values [MONO_METHOD_FLAGS] = mb->attrs;
332 values [MONO_METHOD_IMPLFLAGS] = 0;
333 values [MONO_METHOD_SIGNATURE] = method_encode_signature (assembly, mb);
334 values [MONO_METHOD_PARAMLIST] = 0; /* FIXME: add support later */
335 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
339 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
347 p = buf = g_malloc (64);
349 mono_metadata_encode_value (0x06, p, &p);
350 /* encode custom attributes before the type */
351 encode_type (fb->type->type, p, &p);
352 g_assert (p-buf < 64);
353 mono_metadata_encode_value (p-buf, b, &b);
354 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
355 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
361 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
363 MonoDynamicTable *table;
367 table = &assembly->tables [MONO_TABLE_FIELD];
368 fb->table_idx = table->next_idx ++;
369 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
370 name = mono_string_to_utf8 (fb->name);
371 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
373 values [MONO_FIELD_FLAGS] = fb->attrs;
374 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
378 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
384 MonoReflectionMethodBuilder *mb = fb->get_method;
387 if (mb && mb->parameters)
388 nparams = mono_array_length (mb->parameters);
389 buf = p = g_malloc (24 + nparams * 10);
392 mono_metadata_encode_value (nparams, p, &p);
394 encode_type (mb->rtype->type, p, &p);
395 for (i = 0; i < nparams; ++i) {
396 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
397 encode_type (pt->type, p, &p);
400 *p++ = 1; /* void: a property should probably not be allowed without a getter */
403 mono_metadata_encode_value (p-buf, b, &b);
404 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
405 mono_image_add_stream_data (&assembly->blob, buf, p-buf);
411 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
413 MonoDynamicTable *table;
416 guint num_methods = 0;
420 * we need to set things in the following tables:
421 * PROPERTYMAP (info already filled in _get_type_info ())
422 * PROPERTY (rows already preallocated in _get_type_info ())
423 * METHOD (method info already done with the generic method code)
426 table = &assembly->tables [MONO_TABLE_PROPERTY];
427 pb->table_idx = table->next_idx ++;
428 values = table->values + pb->table_idx * MONO_FIELD_SIZE;
429 name = mono_string_to_utf8 (pb->name);
430 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
432 values [MONO_PROPERTY_FLAGS] = pb->attrs;
433 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
435 /* FIXME: we still don't handle 'other' methods */
436 if (pb->get_method) num_methods ++;
437 if (pb->set_method) num_methods ++;
439 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
440 table->rows += num_methods;
441 alloc_table (table, table->rows);
443 if (pb->get_method) {
444 semaidx = table->next_idx ++;
445 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
446 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
447 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
448 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << 1) | 1;
450 if (pb->set_method) {
451 semaidx = table->next_idx ++;
452 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
453 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
454 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
455 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << 1) | 0;
460 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoClass *klass)
462 MonoDynamicTable *table;
466 if (!assembly->typeref)
467 assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
469 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, klass));
472 if (klass->image != mono_defaults.corlib)
473 g_error ("multiple assemblyref not yet supported");
475 table = &assembly->tables [MONO_TABLE_TYPEREF];
476 alloc_table (table, table->rows + 1);
477 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
478 values [MONO_TYPEREF_SCOPE] = (1 << 2) | 2; /* first row in assemblyref LAMESPEC, see get.c */
479 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
480 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
481 token = 1 | (table->next_idx << 2); /* typeref */
482 g_hash_table_insert (assembly->typeref, klass, GUINT_TO_POINTER(token));
488 mono_image_get_type_info (MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
490 MonoDynamicTable *table;
495 table = &assembly->tables [MONO_TABLE_TYPEDEF];
496 tb->table_idx = table->next_idx ++;
497 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
498 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
499 /* FIXME: use tb->base later */
500 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_defaults.object_class);
501 n = mono_string_to_utf8 (tb->name);
502 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
504 n = mono_string_to_utf8 (tb->nspace);
505 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
507 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
508 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
512 table = &assembly->tables [MONO_TABLE_METHOD];
513 table->rows += mono_array_length (tb->methods);
514 alloc_table (table, table->rows);
515 for (i = 0; i < mono_array_length (tb->methods); ++i)
516 mono_image_get_method_info (
517 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
522 table = &assembly->tables [MONO_TABLE_FIELD];
523 table->rows += mono_array_length (tb->fields);
524 alloc_table (table, table->rows);
525 for (i = 0; i < mono_array_length (tb->fields); ++i)
526 mono_image_get_field_info (
527 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
530 /* Do the same with properties etc.. */
531 if (tb->properties && mono_array_length (tb->properties)) {
532 table = &assembly->tables [MONO_TABLE_PROPERTY];
533 table->rows += mono_array_length (tb->properties);
534 alloc_table (table, table->rows);
535 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
537 alloc_table (table, table->rows);
538 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
539 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
540 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
541 for (i = 0; i < mono_array_length (tb->properties); ++i)
542 mono_image_get_property_info (
543 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
548 mono_image_fill_module_table (MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
550 MonoDynamicTable *table;
554 table = &assembly->tables [MONO_TABLE_MODULE];
555 mb->table_idx = table->next_idx ++;
556 name = mono_string_to_utf8 (mb->module.name);
557 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
559 /* need to set mvid? */
562 * fill-in info in other tables as well.
564 table = &assembly->tables [MONO_TABLE_TYPEDEF];
565 table->rows += mono_array_length (mb->types);
566 alloc_table (table, table->rows);
567 for (i = 0; i < mono_array_length (mb->types); ++i)
568 mono_image_get_type_info (mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
571 #define align_pointer(base,p)\
573 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
575 (p) += 4 - (__diff & 3);\
579 build_compressed_metadata (MonoDynamicAssembly *assembly)
582 guint64 valid_mask = 0;
583 guint32 heapt_size = 0;
584 guint32 meta_size = 256; /* allow for header and other stuff */
585 guint32 table_offset;
592 char *version = "mono" VERSION;
594 /* Compute table sizes */
595 meta = assembly->assembly.image = g_new0 (MonoImage, 1);
597 /* Setup the info used by compute_sizes () */
598 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
599 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
600 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
602 meta_size += assembly->blob.index;
603 meta_size += assembly->guid.index;
604 meta_size += assembly->sheap.index;
605 meta_size += assembly->us.index;
607 for (i=0; i < 64; ++i)
608 meta->tables [i].rows = assembly->tables [i].rows;
610 for (i = 0; i < 64; i++){
611 if (meta->tables [i].rows == 0)
613 valid_mask |= (guint64)1 << i;
615 meta->tables [i].row_size = mono_metadata_compute_size (
616 meta, i, &meta->tables [i].size_bitfield);
617 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
619 heapt_size += 24; /* #~ header size */
620 heapt_size += ntables * 4;
621 meta_size += heapt_size;
622 meta->raw_metadata = g_malloc0 (meta_size);
623 p = meta->raw_metadata;
624 /* the metadata signature */
625 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
626 /* version numbers and 4 bytes reserved */
627 int16val = (guint16*)p;
632 int32val = (guint32*)p;
633 *int32val = strlen (version);
635 memcpy (p, version, *int32val);
637 align_pointer (meta->raw_metadata, p);
638 int16val = (guint16*)p;
639 *int16val++ = 0; /* flags must be 0 */
640 *int16val = 5; /* number of streams */
644 * write the stream info.
646 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
648 int32val = (guint32*)p;
649 *int32val++ = assembly->tstream.offset = table_offset;
650 *int32val = heapt_size;
651 table_offset += *int32val;
655 align_pointer (meta->raw_metadata, p);
657 int32val = (guint32*)p;
658 *int32val++ = assembly->sheap.offset = table_offset;
659 *int32val = assembly->sheap.index;
660 table_offset += *int32val;
662 strcpy (p, "#Strings");
664 align_pointer (meta->raw_metadata, p);
666 int32val = (guint32*)p;
667 *int32val++ = assembly->us.offset = table_offset;
668 *int32val = assembly->us.index;
669 table_offset += *int32val;
673 align_pointer (meta->raw_metadata, p);
675 int32val = (guint32*)p;
676 *int32val++ = assembly->blob.offset = table_offset;
677 *int32val = assembly->blob.index;
678 table_offset += *int32val;
682 align_pointer (meta->raw_metadata, p);
684 int32val = (guint32*)p;
685 *int32val++ = assembly->guid.offset = table_offset;
686 *int32val = assembly->guid.index;
687 table_offset += *int32val;
691 align_pointer (meta->raw_metadata, p);
694 * now copy the data, the table stream header and contents goes first.
696 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
697 p = meta->raw_metadata + assembly->tstream.offset;
698 int32val = (guint32*)p;
699 *int32val = 0; /* reserved */
701 *p++ = 1; /* version */
703 if (meta->idx_string_wide)
705 if (meta->idx_guid_wide)
707 if (meta->idx_blob_wide)
710 *p++ = 0; /* reserved */
711 int64val = (guint64*)p;
712 *int64val++ = valid_mask;
713 *int64val++ = 0; /* bitvector of sorted tables, set to 0 for now */
715 int32val = (guint32*)p;
716 for (i = 0; i < 64; i++){
717 if (meta->tables [i].rows == 0)
719 *int32val++ = meta->tables [i].rows;
721 p = (unsigned char*)int32val;
722 /* compress the tables */
723 for (i = 0; i < 64; i++){
726 guint32 bitfield = meta->tables [i].size_bitfield;
727 if (!meta->tables [i].rows)
729 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
730 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
731 meta->tables [i].base = p;
732 for (row = 1; row <= meta->tables [i].rows; ++row) {
733 values = assembly->tables [i].values + row * assembly->tables [i].columns;
734 for (col = 0; col < assembly->tables [i].columns; ++col) {
735 switch (mono_metadata_table_size (bitfield, col)) {
740 int16val = (guint16*)p;
741 *int16val = values [col];
745 int32val = (guint32*)p;
746 *int32val = values [col];
750 g_assert_not_reached ();
754 g_assert ((p - (unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
757 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
758 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
759 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
760 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
761 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
763 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
767 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
769 MonoDynamicTable *table;
770 MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
777 * FIXME: check if metadata was already built.
779 string_heap_init (&assembly->sheap);
780 mono_image_add_stream_data (&assembly->us, "", 1);
781 mono_image_add_stream_data (&assembly->blob, "", 1);
783 assembly->text_rva = 0x00002000;
785 for (i=0; i < 64; ++i) {
786 assembly->tables [i].next_idx = 1;
787 assembly->tables [i].columns = table_sizes [i];
790 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
791 alloc_table (table, 1);
792 values = table->values + MONO_ASSEMBLY_SIZE;
793 values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
794 name = mono_string_to_utf8 (assemblyb->name);
795 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
797 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
799 assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
800 assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
802 len = mono_array_length (assemblyb->modules);
803 table = &assembly->tables [MONO_TABLE_MODULE];
804 alloc_table (table, len);
805 for (i = 0; i < len; ++i)
806 mono_image_fill_module_table (mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
808 table = &assembly->tables [MONO_TABLE_TYPEDEF];
810 * table->rows is already set above and in mono_image_fill_module_table.
812 alloc_table (table, table->rows);
814 * Set the first entry.
816 values = table->values + table->columns;
817 values [MONO_TYPEDEF_FLAGS] = 0;
818 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
819 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
820 values [MONO_TYPEDEF_EXTENDS] = 0;
821 values [MONO_TYPEDEF_FIELD_LIST] = 1;
822 values [MONO_TYPEDEF_METHOD_LIST] = 1;
824 /* later include all the assemblies referenced */
825 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
826 alloc_table (table, 1);
827 values = table->values + table->columns;
828 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "corlib");
830 build_compressed_metadata (assembly);
834 mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, int maxsize)
836 MonoMSDOSHeader *msdos;
837 MonoDotNetHeader *header;
838 MonoSectionTable *section;
839 MonoCLIHeader *cli_header;
840 guint32 header_size = TEXT_OFFSET + CLI_H_SIZE;
841 MonoDynamicAssembly *assembly;
843 static const unsigned char msheader[] = {
844 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
845 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
846 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
847 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
848 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
849 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
850 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
851 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
854 if (maxsize < header_size)
857 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
858 mono_image_build_metadata (assemblyb);
860 memset (buffer, 0, header_size);
861 memcpy (buffer, msheader, sizeof (MonoMSDOSHeader));
863 msdos = (MonoMSDOSHeader *)buffer;
864 header = (MonoDotNetHeader *)(buffer + sizeof (MonoMSDOSHeader));
865 section = (MonoSectionTable*) (buffer + sizeof (MonoMSDOSHeader) + sizeof (MonoDotNetHeader));
867 /* FIXME: ENDIAN problem: byteswap as needed */
868 msdos->pe_offset = sizeof (MonoMSDOSHeader);
870 header->pesig [0] = 'P';
871 header->pesig [1] = 'E';
872 header->pesig [2] = header->pesig [3] = 0;
874 header->coff.coff_machine = 0x14c;
875 header->coff.coff_sections = 1; /* only .text supported now */
876 header->coff.coff_time = time (NULL);
877 header->coff.coff_opt_header_size = sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4;
879 header->coff.coff_attributes = 0x010e;
881 //header->coff.coff_attributes = 0x210e;
882 header->pe.pe_magic = 0x10B;
883 header->pe.pe_major = 6;
884 header->pe.pe_minor = 0;
885 /* need to set: pe_code_size pe_data_size pe_rva_entry_point pe_rva_code_base pe_rva_data_base */
887 header->nt.pe_image_base = 0x400000;
888 header->nt.pe_section_align = 8192;
889 header->nt.pe_file_alignment = FILE_ALIGN;
890 header->nt.pe_os_major = 4;
891 header->nt.pe_os_minor = 0;
892 header->nt.pe_subsys_major = 4;
893 /* need to set pe_image_size, pe_header_size */
894 header->nt.pe_subsys_required = 3; /* 3 -> cmdline app, 2 -> GUI app */
895 header->nt.pe_stack_reserve = 0x00100000;
896 header->nt.pe_stack_commit = 0x00001000;
897 header->nt.pe_heap_reserve = 0x00100000;
898 header->nt.pe_heap_commit = 0x00001000;
899 header->nt.pe_loader_flags = 1;
900 header->nt.pe_data_dir_count = 16;
904 header->datadir.pe_import_table
909 header->datadir.pe_cli_header.size = CLI_H_SIZE;
910 header->datadir.pe_cli_header.rva = assembly->text_rva; /* we put it always at the beginning */
912 /* Write section tables */
913 strcpy (section->st_name, ".text");
914 section->st_virtual_size = 1024; /* FIXME */
915 section->st_virtual_address = assembly->text_rva;
916 section->st_raw_data_size = 1024; /* FIXME */
917 section->st_raw_data_ptr = TEXT_OFFSET;
918 section->st_flags = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
921 * align: build_compressed_metadata () assumes metadata is aligned
923 * cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
925 assembly->code.index += 3;
926 assembly->code.index &= ~3;
929 * Write the MonoCLIHeader header
931 cli_header = (MonoCLIHeader*)(buffer + TEXT_OFFSET);
932 cli_header->ch_size = CLI_H_SIZE;
933 cli_header->ch_runtime_major = 2;
934 cli_header->ch_flags = CLI_FLAGS_ILONLY;
935 if (assemblyb->entry_point)
936 cli_header->ch_entry_point = assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF;
938 cli_header->ch_entry_point = 0;
939 cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
940 cli_header->ch_metadata.size = assembly->meta_size;