3 * Creation of object files or assembly files using the same interface.
6 * Dietmar Maurer (dietmar@ximian.com)
7 * Zoltan Varga (vargaz@gmail.com)
8 * Paolo Molaro (lupus@ximian.com)
9 * Johan Lorensson (lateralusx.github@gmail.com)
11 * (C) 2002 Ximian, Inc.
15 #include <sys/types.h>
34 #include <limits.h> /* for PAGESIZE */
39 #include "image-writer.h"
42 #include <mono/utils/freebsd-elf32.h>
43 #include <mono/utils/freebsd-elf64.h>
48 #define TV_DECLARE(name) gint64 name
49 #define TV_GETTIME(tv) tv = mono_100ns_ticks ()
50 #define TV_ELAPSED(start,end) (((end) - (start)) / 10)
53 * The used assembler dialect
54 * TARGET_ASM_APPLE == apple assembler on OSX
55 * TARGET_ASM_GAS == GNU assembler
57 #if !defined(TARGET_ASM_APPLE) && !defined(TARGET_ASM_GAS)
58 #if defined(TARGET_MACH)
59 #define TARGET_ASM_APPLE
61 #define TARGET_ASM_GAS
66 * Defines for the directives used by different assemblers
68 #if defined(TARGET_POWERPC) || defined(TARGET_MACH)
69 #define AS_STRING_DIRECTIVE ".asciz"
71 #define AS_STRING_DIRECTIVE ".string"
74 #define AS_INT32_DIRECTIVE ".long"
75 #define AS_INT64_DIRECTIVE ".quad"
77 #if (defined(TARGET_AMD64) || defined(TARGET_POWERPC64)) && !defined(MONO_ARCH_ILP32)
78 #define AS_POINTER_DIRECTIVE ".quad"
79 #elif defined(TARGET_ARM64)
81 #ifdef MONO_ARCH_ILP32
82 #define AS_POINTER_DIRECTIVE AS_INT32_DIRECTIVE
84 #ifdef TARGET_ASM_APPLE
85 #define AS_POINTER_DIRECTIVE ".quad"
87 #define AS_POINTER_DIRECTIVE ".xword"
92 #define AS_POINTER_DIRECTIVE ".long"
95 #if defined(TARGET_ASM_APPLE)
96 #define AS_INT16_DIRECTIVE ".short"
97 #elif defined(TARGET_ASM_GAS) && defined(TARGET_WIN32)
98 #define AS_INT16_DIRECTIVE ".word"
99 #elif defined(TARGET_ASM_GAS)
100 #define AS_INT16_DIRECTIVE ".hword"
102 #define AS_INT16_DIRECTIVE ".word"
105 #if defined(TARGET_ASM_APPLE)
106 #define AS_SKIP_DIRECTIVE ".space"
108 #define AS_SKIP_DIRECTIVE ".skip"
111 #if defined(TARGET_ASM_APPLE)
112 #define AS_GLOBAL_PREFIX "_"
114 #define AS_GLOBAL_PREFIX ""
117 #ifdef TARGET_ASM_APPLE
118 #define AS_TEMP_LABEL_PREFIX "L"
120 #define AS_TEMP_LABEL_PREFIX ".L"
123 #define ROUND_DOWN(VALUE,SIZE) ((VALUE) & ~((SIZE) - 1))
125 #ifdef USE_BIN_WRITER
127 typedef struct _BinSymbol BinSymbol
;
128 typedef struct _BinReloc BinReloc
;
129 typedef struct _BinSection BinSection
;
141 struct _MonoImageWriter
{
142 MonoMemPool
*mempool
;
144 gboolean use_bin_writer
;
145 const char *current_section
;
146 int current_subsection
;
147 const char *section_stack
[16];
148 int subsection_stack
[16];
152 #ifdef USE_BIN_WRITER
154 BinSection
*sections
;
155 BinSection
*cur_section
;
156 BinReloc
*relocations
;
160 int out_buf_size
, out_buf_pos
;
164 int mode
; /* emit mode */
165 int col_count
; /* bytes emitted per .byte line */
169 static G_GNUC_UNUSED
int
170 ilog2(register int value
)
173 while (value
& ~0xf) count
+= 4, value
>>= 4;
174 while (value
) count
++, value
>>= 1;
178 #ifdef USE_BIN_WRITER
180 typedef struct _BinLabel BinLabel
;
191 BinSection
*val2_section
;
204 gboolean is_function
;
225 bin_writer_emit_start (MonoImageWriter
*acfg
)
227 acfg
->labels
= g_hash_table_new (g_str_hash
, g_str_equal
);
231 bin_writer_emit_section_change (MonoImageWriter
*acfg
, const char *section_name
, int subsection_index
)
235 if (acfg
->cur_section
&& acfg
->cur_section
->subsection
== subsection_index
236 && strcmp (acfg
->cur_section
->name
, section_name
) == 0)
238 for (section
= acfg
->sections
; section
; section
= section
->next
) {
239 if (section
->subsection
== subsection_index
&& strcmp (section
->name
, section_name
) == 0) {
240 acfg
->cur_section
= section
;
245 section
= g_new0 (BinSection
, 1);
246 section
->name
= g_strdup (section_name
);
247 section
->subsection
= subsection_index
;
248 section
->next
= acfg
->sections
;
249 acfg
->sections
= section
;
250 acfg
->cur_section
= section
;
255 bin_writer_set_section_addr (MonoImageWriter
*acfg
, guint64 addr
)
257 acfg
->cur_section
->addr
= addr
;
258 acfg
->cur_section
->has_addr
= TRUE
;
262 bin_writer_emit_symbol_inner (MonoImageWriter
*acfg
, const char *name
, const char *end_label
, gboolean is_global
, gboolean func
)
264 BinSymbol
*symbol
= g_new0 (BinSymbol
, 1);
265 symbol
->name
= g_strdup (name
);
267 symbol
->end_label
= g_strdup (end_label
);
268 symbol
->is_function
= func
;
269 symbol
->is_global
= is_global
;
270 symbol
->section
= acfg
->cur_section
;
271 /* FIXME: we align after this call... */
272 symbol
->offset
= symbol
->section
->cur_offset
;
273 symbol
->next
= acfg
->symbols
;
274 acfg
->symbols
= symbol
;
278 bin_writer_emit_global (MonoImageWriter
*acfg
, const char *name
, gboolean func
)
280 bin_writer_emit_symbol_inner (acfg
, name
, NULL
, TRUE
, func
);
284 bin_writer_emit_local_symbol (MonoImageWriter
*acfg
, const char *name
, const char *end_label
, gboolean func
)
286 bin_writer_emit_symbol_inner (acfg
, name
, end_label
, FALSE
, func
);
290 bin_writer_emit_label (MonoImageWriter
*acfg
, const char *name
)
292 BinLabel
*label
= g_new0 (BinLabel
, 1);
293 label
->name
= g_strdup (name
);
294 label
->section
= acfg
->cur_section
;
295 label
->offset
= acfg
->cur_section
->cur_offset
;
296 g_hash_table_insert (acfg
->labels
, label
->name
, label
);
300 bin_writer_emit_ensure_buffer (BinSection
*section
, int size
)
302 int new_offset
= section
->cur_offset
+ size
;
303 if (new_offset
>= section
->data_len
) {
304 int new_size
= section
->data_len
? section
->data_len
* 2: 256;
306 while (new_size
<= new_offset
)
308 data
= (guint8
*)g_malloc0 (new_size
);
309 memcpy (data
, section
->data
, section
->data_len
);
310 g_free (section
->data
);
311 section
->data
= data
;
312 section
->data_len
= new_size
;
317 bin_writer_emit_bytes (MonoImageWriter
*acfg
, const guint8
* buf
, int size
)
319 bin_writer_emit_ensure_buffer (acfg
->cur_section
, size
);
320 memcpy (acfg
->cur_section
->data
+ acfg
->cur_section
->cur_offset
, buf
, size
);
321 acfg
->cur_section
->cur_offset
+= size
;
325 bin_writer_emit_string (MonoImageWriter
*acfg
, const char *value
)
327 int size
= strlen (value
) + 1;
328 bin_writer_emit_bytes (acfg
, (const guint8
*)value
, size
);
332 bin_writer_emit_line (MonoImageWriter
*acfg
)
334 /* Nothing to do in binary writer */
338 bin_writer_emit_alignment (MonoImageWriter
*acfg
, int size
)
340 int offset
= acfg
->cur_section
->cur_offset
;
342 offset
+= (size
- 1);
343 offset
&= ~(size
- 1);
344 add
= offset
- acfg
->cur_section
->cur_offset
;
346 bin_writer_emit_ensure_buffer (acfg
->cur_section
, add
);
347 acfg
->cur_section
->cur_offset
+= add
;
352 bin_writer_emit_pointer_unaligned (MonoImageWriter
*acfg
, const char *target
)
357 acfg
->cur_section
->cur_offset
+= sizeof (gpointer
);
361 reloc
= g_new0 (BinReloc
, 1);
362 reloc
->val1
= g_strdup (target
);
363 reloc
->section
= acfg
->cur_section
;
364 reloc
->section_offset
= acfg
->cur_section
->cur_offset
;
365 reloc
->next
= acfg
->relocations
;
366 acfg
->relocations
= reloc
;
367 if (strcmp (reloc
->section
->name
, ".data") == 0) {
369 //g_print ("reloc: %s at %d\n", target, acfg->cur_section->cur_offset);
371 acfg
->cur_section
->cur_offset
+= sizeof (gpointer
);
375 bin_writer_emit_pointer (MonoImageWriter
*acfg
, const char *target
)
377 bin_writer_emit_alignment (acfg
, sizeof (gpointer
));
378 bin_writer_emit_pointer_unaligned (acfg
, target
);
382 bin_writer_emit_int16 (MonoImageWriter
*acfg
, int value
)
385 bin_writer_emit_ensure_buffer (acfg
->cur_section
, 2);
386 data
= acfg
->cur_section
->data
+ acfg
->cur_section
->cur_offset
;
387 acfg
->cur_section
->cur_offset
+= 2;
388 /* FIXME: little endian */
390 data
[1] = value
>> 8;
394 bin_writer_emit_int32 (MonoImageWriter
*acfg
, int value
)
397 bin_writer_emit_ensure_buffer (acfg
->cur_section
, 4);
398 data
= acfg
->cur_section
->data
+ acfg
->cur_section
->cur_offset
;
399 acfg
->cur_section
->cur_offset
+= 4;
400 /* FIXME: little endian */
402 data
[1] = value
>> 8;
403 data
[2] = value
>> 16;
404 data
[3] = value
>> 24;
408 create_reloc (MonoImageWriter
*acfg
, const char *end
, const char* start
, int offset
)
411 reloc
= (BinReloc
*)mono_mempool_alloc0 (acfg
->mempool
, sizeof (BinReloc
));
412 reloc
->val1
= mono_mempool_strdup (acfg
->mempool
, end
);
415 if (strcmp (start
, ".") == 0) {
416 reloc
->val2_section
= acfg
->cur_section
;
417 reloc
->val2_offset
= acfg
->cur_section
->cur_offset
;
419 reloc
->val2
= mono_mempool_strdup (acfg
->mempool
, start
);
422 reloc
->offset
= offset
;
423 reloc
->section
= acfg
->cur_section
;
424 reloc
->section_offset
= acfg
->cur_section
->cur_offset
;
425 reloc
->next
= acfg
->relocations
;
426 acfg
->relocations
= reloc
;
431 bin_writer_emit_symbol (MonoImageWriter
*acfg
, const char *symbol
)
433 create_reloc (acfg
, symbol
, NULL
, 0);
434 acfg
->cur_section
->cur_offset
+= 4;
438 bin_writer_emit_symbol_diff (MonoImageWriter
*acfg
, const char *end
, const char* start
, int offset
)
440 create_reloc (acfg
, end
, start
, offset
);
441 acfg
->cur_section
->cur_offset
+= 4;
442 /*if (strcmp (reloc->section->name, ".data") == 0) {
444 g_print ("reloc: %s - %s + %d at %d\n", end, start, offset, acfg->cur_section->cur_offset - 4);
449 * Emit a relocation entry of type RELOC_TYPE against symbol SYMBOL at the current PC.
452 static G_GNUC_UNUSED
void
453 bin_writer_emit_reloc (MonoImageWriter
*acfg
, int reloc_type
, const char *symbol
, int addend
)
455 BinReloc
*reloc
= create_reloc (acfg
, symbol
, ".", addend
);
456 reloc
->reloc_type
= reloc_type
;
460 bin_writer_emit_zero_bytes (MonoImageWriter
*acfg
, int num
)
462 bin_writer_emit_ensure_buffer (acfg
->cur_section
, num
);
463 acfg
->cur_section
->cur_offset
+= num
;
467 bin_writer_fwrite (MonoImageWriter
*acfg
, void *val
, size_t size
, size_t nmemb
)
470 fwrite (val
, size
, nmemb
, acfg
->fp
);
472 g_assert (acfg
->out_buf_pos
+ (size
* nmemb
) <= acfg
->out_buf_size
);
473 memcpy (acfg
->out_buf
+ acfg
->out_buf_pos
, val
, size
* nmemb
);
474 acfg
->out_buf_pos
+= (size
* nmemb
);
479 bin_writer_fseek (MonoImageWriter
*acfg
, int offset
)
482 fseek (acfg
->fp
, offset
, SEEK_SET
);
484 acfg
->out_buf_pos
= offset
;
487 #ifdef USE_MACH_WRITER
490 * This is a minimal implementation designed to support xdebug on 32 bit osx
491 * FIXME: 64 bit support
494 #include <mach-o/loader.h>
497 get_label_addr (MonoImageWriter
*acfg
, const char *name
)
504 lab
= g_hash_table_lookup (acfg
->labels
, name
);
506 g_error ("Undefined label: '%s'.\n", name
);
507 section
= lab
->section
;
508 offset
= lab
->offset
;
509 if (section
->parent
) {
510 value
= section
->parent
->virt_offset
+ section
->cur_offset
+ offset
;
512 value
= section
->virt_offset
+ offset
;
519 resolve_reloc (MonoImageWriter
*acfg
, BinReloc
*reloc
, guint8
**out_data
, gsize
*out_vaddr
, gsize
*out_start_val
, gsize
*out_end_val
)
522 gssize end_val
, start_val
;
525 end_val
= get_label_addr (acfg
, reloc
->val1
);
527 start_val
= get_label_addr (acfg
, reloc
->val2
);
528 } else if (reloc
->val2_section
) {
529 start_val
= reloc
->val2_offset
;
530 if (reloc
->val2_section
->parent
)
531 start_val
+= reloc
->val2_section
->parent
->virt_offset
+ reloc
->val2_section
->cur_offset
;
533 start_val
+= reloc
->val2_section
->virt_offset
;
537 end_val
= end_val
- start_val
+ reloc
->offset
;
538 if (reloc
->section
->parent
) {
539 data
= reloc
->section
->parent
->data
;
540 data
+= reloc
->section
->cur_offset
;
541 data
+= reloc
->section_offset
;
542 vaddr
= reloc
->section
->parent
->virt_offset
;
543 vaddr
+= reloc
->section
->cur_offset
;
544 vaddr
+= reloc
->section_offset
;
546 data
= reloc
->section
->data
;
547 data
+= reloc
->section_offset
;
548 vaddr
= reloc
->section
->virt_offset
;
549 vaddr
+= reloc
->section_offset
;
552 *out_start_val
= start_val
;
553 *out_end_val
= end_val
;
559 resolve_relocations (MonoImageWriter
*acfg
)
563 gsize end_val
, start_val
;
566 /* Only resolve static relocations */
567 for (reloc
= acfg
->relocations
; reloc
; reloc
= reloc
->next
) {
568 resolve_reloc (acfg
, reloc
, &data
, &vaddr
, &start_val
, &end_val
);
570 data
[1] = end_val
>> 8;
571 data
[2] = end_val
>> 16;
572 data
[3] = end_val
>> 24;
577 bin_writer_emit_writeout (MonoImageWriter
*acfg
)
580 int sindex
, file_size
, nsections
, file_offset
, vmaddr
;
581 struct mach_header header
;
582 struct segment_command segment
;
583 struct section
*sections
;
585 /* Assing vm addresses to sections */
588 for (s
= acfg
->sections
; s
; s
= s
->next
) {
589 s
->virt_offset
= vmaddr
;
590 vmaddr
+= s
->cur_offset
;
594 resolve_relocations (acfg
);
598 memset (&header
, 0, sizeof (header
));
599 header
.magic
= MH_MAGIC
;
600 header
.cputype
= CPU_TYPE_X86
;
601 header
.cpusubtype
= CPU_SUBTYPE_X86_ALL
;
602 header
.filetype
= MH_OBJECT
;
604 header
.sizeofcmds
= 0;
607 file_offset
+= sizeof (header
);
609 memset (&segment
, 0, sizeof (segment
));
610 segment
.cmd
= LC_SEGMENT
;
611 segment
.cmdsize
= sizeof (segment
);
612 segment
.maxprot
= VM_PROT_READ
|VM_PROT_WRITE
|VM_PROT_EXECUTE
;
613 segment
.initprot
= VM_PROT_READ
|VM_PROT_WRITE
|VM_PROT_EXECUTE
;
615 file_offset
+= sizeof (segment
);
616 file_offset
+= nsections
* sizeof (struct section
);
618 sections
= g_new0 (struct section
, nsections
);
620 for (s
= acfg
->sections
; s
; s
= s
->next
) {
621 s
->file_offset
= file_offset
;
623 /* .debug_line -> __debug_line */
624 sprintf (sections
[sindex
].sectname
, "__%s", s
->name
+ 1);
625 sprintf (sections
[sindex
].segname
, "%s", "__DWARF");
626 sections
[sindex
].addr
= s
->virt_offset
;
627 sections
[sindex
].size
= s
->cur_offset
;
628 sections
[sindex
].offset
= s
->file_offset
;
630 file_offset
+= s
->cur_offset
;
633 segment
.cmdsize
+= sizeof (struct section
);
639 header
.sizeofcmds
+= segment
.cmdsize
;
642 file_size
= file_offset
;
645 acfg
->out_buf_size
= file_size
;
646 acfg
->out_buf
= g_malloc (acfg
->out_buf_size
);
649 bin_writer_fwrite (acfg
, &header
, sizeof (header
), 1);
650 bin_writer_fwrite (acfg
, &segment
, sizeof (segment
), 1);
651 bin_writer_fwrite (acfg
, sections
, sizeof (struct section
), nsections
);
652 for (s
= acfg
->sections
; s
; s
= s
->next
) {
654 g_assert (acfg
->out_buf_pos
== s
->file_offset
);
655 bin_writer_fwrite (acfg
, s
->data
, s
->cur_offset
, 1);
666 #ifdef USE_ELF_WRITER
692 #if TARGET_SIZEOF_VOID_P == 4
694 typedef Elf32_Ehdr ElfHeader
;
695 typedef Elf32_Shdr ElfSectHeader
;
696 typedef Elf32_Phdr ElfProgHeader
;
697 typedef Elf32_Sym ElfSymbol
;
698 typedef Elf32_Rel ElfReloc
;
699 typedef Elf32_Rela ElfRelocA
;
700 typedef Elf32_Dyn ElfDynamic
;
704 typedef Elf64_Ehdr ElfHeader
;
705 typedef Elf64_Shdr ElfSectHeader
;
706 typedef Elf64_Phdr ElfProgHeader
;
707 typedef Elf64_Sym ElfSymbol
;
708 typedef Elf64_Rel ElfReloc
;
709 typedef Elf64_Rela ElfRelocA
;
710 typedef Elf64_Dyn ElfDynamic
;
722 static SectInfo section_info
[] = {
724 {".hash", SHT_HASH
, 4, 2, TARGET_SIZEOF_VOID_P
},
725 {".dynsym", SHT_DYNSYM
, sizeof (ElfSymbol
), 2, TARGET_SIZEOF_VOID_P
},
726 {".dynstr", SHT_STRTAB
, 0, 2, 1},
727 {".rel.dyn", SHT_REL
, sizeof (ElfReloc
), 2, TARGET_SIZEOF_VOID_P
},
728 {".rela.dyn", SHT_RELA
, sizeof (ElfRelocA
), 2, TARGET_SIZEOF_VOID_P
},
729 {".text", SHT_PROGBITS
, 0, 6, 4096},
730 {".rodata", SHT_PROGBITS
, 0, SHF_ALLOC
, 4096},
731 {".dynamic", SHT_DYNAMIC
, sizeof (ElfDynamic
), 3, TARGET_SIZEOF_VOID_P
},
732 {".got.plt", SHT_PROGBITS
, TARGET_SIZEOF_VOID_P
, 3, TARGET_SIZEOF_VOID_P
},
733 {".data", SHT_PROGBITS
, 0, 3, 8},
734 {".bss", SHT_NOBITS
, 0, 3, 8},
735 {".debug_frame", SHT_PROGBITS
, 0, 0, 8},
736 {".debug_info", SHT_PROGBITS
, 0, 0, 1},
737 {".debug_abbrev", SHT_PROGBITS
, 0, 0, 1},
738 {".debug_line", SHT_PROGBITS
, 0, 0, 1},
739 {".debug_loc", SHT_PROGBITS
, 0, 0, 1},
740 {".shstrtab", SHT_STRTAB
, 0, 0, 1},
741 {".symtab", SHT_SYMTAB
, sizeof (ElfSymbol
), 0, TARGET_SIZEOF_VOID_P
},
742 {".strtab", SHT_STRTAB
, 0, 0, 1}
751 str_table_add (ElfStrTable
*table
, const char* value
)
755 table
->data
= g_string_new_len ("", 1);
756 table
->hash
= g_hash_table_new (g_str_hash
, g_str_equal
);
758 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (table
->hash
, value
));
761 idx
= table
->data
->len
;
762 g_string_append (table
->data
, value
);
763 g_string_append_c (table
->data
, 0);
764 g_hash_table_insert (table
->hash
, (void*)value
, GUINT_TO_POINTER (idx
));
769 append_subsection (MonoImageWriter
*acfg
, ElfSectHeader
*sheaders
, BinSection
*sect
, BinSection
*add
)
771 int offset
= sect
->cur_offset
;
772 /*offset += (sheaders [sect->shidx].sh_addralign - 1);
773 offset &= ~(sheaders [sect->shidx].sh_addralign - 1);*/
775 * FIXME: we shouldn't align subsections at all, but if we don't then the
776 * stuff inside the subsections which is aligned won't get aligned.
778 if (strcmp (sect
->name
, ".debug_line") != 0) {
782 bin_writer_emit_ensure_buffer (sect
, offset
);
783 //g_print ("section %s aligned to %d from %d\n", sect->name, offset, sect->cur_offset);
784 sect
->cur_offset
= offset
;
786 bin_writer_emit_ensure_buffer (sect
, add
->cur_offset
);
787 memcpy (sect
->data
+ sect
->cur_offset
, add
->data
, add
->cur_offset
);
789 sect
->cur_offset
+= add
->cur_offset
;
790 add
->cur_offset
= offset
; /* it becomes the offset in the parent section */
791 //g_print ("subsection %d of %s added at offset %d (align: %d)\n", add->subsection, sect->name, add->cur_offset, (int)sheaders [sect->shidx].sh_addralign);
796 /* merge the subsections */
798 collect_sections (MonoImageWriter
*acfg
, ElfSectHeader
*sheaders
, BinSection
**out
, int num
)
800 int i
, j
, maxs
, num_sections
;
805 for (sect
= acfg
->sections
; sect
; sect
= sect
->next
) {
806 if (sect
->subsection
== 0) {
807 out
[num_sections
++] = sect
;
808 g_assert (num_sections
< num
);
810 maxs
= MAX (maxs
, sect
->subsection
);
812 for (i
= 0; i
< num_sections
; i
++) {
813 for (j
= 1; j
<= maxs
; ++j
) {
814 for (sect
= acfg
->sections
; sect
; sect
= sect
->next
) {
815 if (sect
->subsection
== j
&& strcmp (out
[i
]->name
, sect
->name
) == 0) {
816 append_subsection (acfg
, sheaders
, out
[i
], sect
);
825 elf_hash (const unsigned char *name
)
827 unsigned long h
= 0, g
;
829 h
= (h
<< 4) + *name
++;
830 if ((g
= h
& 0xf0000000))
837 #define NUM_BUCKETS 17
840 build_hash (MonoImageWriter
*acfg
, int num_sections
, ElfStrTable
*dynstr
)
843 int num_symbols
= 1 + num_sections
+ 3;
846 for (symbol
= acfg
->symbols
; symbol
; symbol
= symbol
->next
) {
847 if (!symbol
->is_global
)
850 str_table_add (dynstr
, symbol
->name
);
851 /*g_print ("adding sym: %s\n", symbol->name);*/
853 str_table_add (dynstr
, "__bss_start");
854 str_table_add (dynstr
, "_edata");
855 str_table_add (dynstr
, "_end");
857 data
= g_new0 (int, num_symbols
+ 2 + NUM_BUCKETS
);
858 data
[0] = NUM_BUCKETS
;
859 data
[1] = num_symbols
;
865 get_label_addr (MonoImageWriter
*acfg
, const char *name
)
872 lab
= (BinLabel
*)g_hash_table_lookup (acfg
->labels
, name
);
874 g_error ("Undefined label: '%s'.\n", name
);
875 section
= lab
->section
;
876 offset
= lab
->offset
;
877 if (section
->parent
) {
878 value
= section
->parent
->virt_offset
+ section
->cur_offset
+ offset
;
880 value
= section
->virt_offset
+ offset
;
886 collect_syms (MonoImageWriter
*acfg
, int *hash
, ElfStrTable
*strtab
, ElfSectHeader
*sheaders
, int *num_syms
)
897 symbols
= g_new0 (ElfSymbol
, hash
[1]);
900 for (symbol
= acfg
->symbols
; symbol
; symbol
= symbol
->next
)
903 symbols
= g_new0 (ElfSymbol
, i
+ SECT_NUM
+ 10); /* FIXME */
906 /* the first symbol is undef, all zeroes */
910 for (j
= 1; j
< SECT_NUM
; ++j
) {
911 symbols
[i
].st_info
= ELF32_ST_INFO (STB_LOCAL
, STT_SECTION
);
912 symbols
[i
].st_shndx
= j
;
913 symbols
[i
].st_value
= sheaders
[j
].sh_addr
;
917 for (section
= acfg
->sections
; section
; section
= section
->next
) {
920 symbols
[i
].st_info
= ELF32_ST_INFO (STB_LOCAL
, STT_SECTION
);
921 if (strcmp (section
->name
, ".text") == 0) {
922 symbols
[i
].st_shndx
= SECT_TEXT
;
923 section
->shidx
= SECT_TEXT
;
924 section
->file_offset
= 4096;
925 symbols
[i
].st_value
= section
->virt_offset
;
926 } else if (strcmp (section
->name
, ".rodata") == 0) {
927 symbols
[i
].st_shndx
= SECT_RODATA
;
928 section
->shidx
= SECT_RODATA
;
929 section
->file_offset
= 4096;
930 symbols
[i
].st_value
= section
->virt_offset
;
931 } else if (strcmp (section
->name
, ".data") == 0) {
932 symbols
[i
].st_shndx
= SECT_DATA
;
933 section
->shidx
= SECT_DATA
;
934 section
->file_offset
= 4096 + 28; /* FIXME */
935 symbols
[i
].st_value
= section
->virt_offset
;
936 } else if (strcmp (section
->name
, ".bss") == 0) {
937 symbols
[i
].st_shndx
= SECT_BSS
;
938 section
->shidx
= SECT_BSS
;
939 section
->file_offset
= 4096 + 28 + 8; /* FIXME */
940 symbols
[i
].st_value
= section
->virt_offset
;
945 for (symbol
= acfg
->symbols
; symbol
; symbol
= symbol
->next
) {
948 if (!symbol
->is_global
&& hash
)
950 symbols
[i
].st_info
= ELF32_ST_INFO (symbol
->is_global
? STB_GLOBAL
: STB_LOCAL
, symbol
->is_function
? STT_FUNC
: STT_OBJECT
);
951 symbols
[i
].st_name
= str_table_add (strtab
, symbol
->name
);
952 /*g_print ("sym name %s tabled to %d\n", symbol->name, symbols [i].st_name);*/
953 section
= symbol
->section
;
954 symbols
[i
].st_shndx
= section
->parent
? section
->parent
->shidx
: section
->shidx
;
955 lab
= (BinLabel
*)g_hash_table_lookup (acfg
->labels
, symbol
->name
);
956 offset
= lab
->offset
;
957 if (section
->parent
) {
958 symbols
[i
].st_value
= section
->parent
->virt_offset
+ section
->cur_offset
+ offset
;
960 symbols
[i
].st_value
= section
->virt_offset
+ offset
;
963 if (symbol
->end_label
) {
964 BinLabel
*elab
= (BinLabel
*)g_hash_table_lookup (acfg
->labels
, symbol
->end_label
);
966 symbols
[i
].st_size
= elab
->offset
- lab
->offset
;
970 /* add special symbols */
971 symbols
[i
].st_name
= str_table_add (strtab
, "__bss_start");
972 symbols
[i
].st_shndx
= 0xfff1;
973 symbols
[i
].st_info
= ELF32_ST_INFO (STB_GLOBAL
, 0);
975 symbols
[i
].st_name
= str_table_add (strtab
, "_edata");
976 symbols
[i
].st_shndx
= 0xfff1;
977 symbols
[i
].st_info
= ELF32_ST_INFO (STB_GLOBAL
, 0);
979 symbols
[i
].st_name
= str_table_add (strtab
, "_end");
980 symbols
[i
].st_shndx
= 0xfff1;
981 symbols
[i
].st_info
= ELF32_ST_INFO (STB_GLOBAL
, 0);
987 /* add to hash table */
990 chain
= hash
+ 2 + hash
[0];
991 for (i
= 0; i
< hash
[1]; ++i
) {
993 /*g_print ("checking %d '%s' (sym %d)\n", symbols [i].st_name, strtab->data->str + symbols [i].st_name, i);*/
994 if (!symbols
[i
].st_name
)
996 hashc
= elf_hash ((guint8
*)strtab
->data
->str
+ symbols
[i
].st_name
);
997 slot
= hashc
% hash
[0];
998 /*g_print ("hashing '%s' at slot %d (sym %d)\n", strtab->data->str + symbols [i].st_name, slot, i);*/
1000 chain
[i
] = bucket
[slot
];
1011 reloc_symbols (MonoImageWriter
*acfg
, ElfSymbol
*symbols
, ElfSectHeader
*sheaders
, ElfStrTable
*strtab
, gboolean dynamic
)
1013 BinSection
*section
;
1019 for (section
= acfg
->sections
; section
; section
= section
->next
) {
1020 if (section
->parent
)
1022 symbols
[i
].st_value
= sheaders
[section
->shidx
].sh_addr
;
1026 for (i
= 1; i
< SECT_NUM
; ++i
) {
1027 symbols
[i
].st_value
= sheaders
[i
].sh_addr
;
1030 for (symbol
= acfg
->symbols
; symbol
; symbol
= symbol
->next
) {
1033 if (dynamic
&& !symbol
->is_global
)
1035 section
= symbol
->section
;
1036 lab
= (BinLabel
*)g_hash_table_lookup (acfg
->labels
, symbol
->name
);
1037 offset
= lab
->offset
;
1038 if (section
->parent
) {
1039 symbols
[i
].st_value
= sheaders
[section
->parent
->shidx
].sh_addr
+ section
->cur_offset
+ offset
;
1041 symbols
[i
].st_value
= sheaders
[section
->shidx
].sh_addr
+ offset
;
1046 symbols
[i
].st_value
= sheaders
[SECT_BSS
].sh_addr
;
1049 symbols
[i
].st_value
= sheaders
[SECT_DATA
].sh_addr
+ sheaders
[SECT_DATA
].sh_size
;
1052 symbols
[i
].st_value
= sheaders
[SECT_BSS
].sh_addr
+ sheaders
[SECT_BSS
].sh_size
;
1057 resolve_reloc (MonoImageWriter
*acfg
, BinReloc
*reloc
, guint8
**out_data
, gsize
*out_vaddr
, gsize
*out_start_val
, gsize
*out_end_val
)
1060 gssize end_val
, start_val
;
1063 end_val
= get_label_addr (acfg
, reloc
->val1
);
1065 start_val
= get_label_addr (acfg
, reloc
->val2
);
1066 } else if (reloc
->val2_section
) {
1067 start_val
= reloc
->val2_offset
;
1068 if (reloc
->val2_section
->parent
)
1069 start_val
+= reloc
->val2_section
->parent
->virt_offset
+ reloc
->val2_section
->cur_offset
;
1071 start_val
+= reloc
->val2_section
->virt_offset
;
1075 end_val
= end_val
- start_val
+ reloc
->offset
;
1076 if (reloc
->section
->parent
) {
1077 data
= reloc
->section
->parent
->data
;
1078 data
+= reloc
->section
->cur_offset
;
1079 data
+= reloc
->section_offset
;
1080 vaddr
= reloc
->section
->parent
->virt_offset
;
1081 vaddr
+= reloc
->section
->cur_offset
;
1082 vaddr
+= reloc
->section_offset
;
1084 data
= reloc
->section
->data
;
1085 data
+= reloc
->section_offset
;
1086 vaddr
= reloc
->section
->virt_offset
;
1087 vaddr
+= reloc
->section_offset
;
1090 *out_start_val
= start_val
;
1091 *out_end_val
= end_val
;
1099 resolve_relocations (MonoImageWriter
*acfg
)
1103 gsize end_val
, start_val
;
1108 rr
= g_new0 (ElfRelocA
, acfg
->num_relocs
);
1111 for (reloc
= acfg
->relocations
; reloc
; reloc
= reloc
->next
) {
1112 resolve_reloc (acfg
, reloc
, &data
, &vaddr
, &start_val
, &end_val
);
1113 /* FIXME: little endian */
1115 data
[1] = end_val
>> 8;
1116 data
[2] = end_val
>> 16;
1117 data
[3] = end_val
>> 24;
1119 if (start_val
== 0 && reloc
->val1
[0] != '.') {
1120 rr
[i
].r_offset
= vaddr
;
1121 rr
[i
].r_info
= R_X86_64_RELATIVE
;
1122 rr
[i
].r_addend
= end_val
;
1124 g_assert (i
<= acfg
->num_relocs
);
1130 #else /* USE_ELF_RELA */
1133 do_reloc (MonoImageWriter
*acfg
, BinReloc
*reloc
, guint8
*data
, gssize addr
)
1137 * We use the official ARM relocation types, but implement only the stuff actually
1138 * needed by the code we generate.
1140 switch (reloc
->reloc_type
) {
1142 case R_ARM_JUMP24
: {
1143 guint32
*code
= (guint32
*)(gpointer
)data
;
1144 guint32 ins
= *code
;
1147 if (reloc
->reloc_type
== R_ARM_CALL
)
1149 g_assert (data
[3] == 0xeb);
1152 g_assert (data
[3] == 0xea);
1153 if (diff
>= 0 && diff
<= 33554431) {
1155 ins
= (ins
& 0xff000000) | diff
;
1157 } else if (diff
<= 0 && diff
>= -33554432) {
1159 ins
= (ins
& 0xff000000) | (diff
& ~0xff000000);
1162 g_assert_not_reached ();
1166 case R_ARM_ALU_PC_G0_NC
: {
1167 /* Generated by emit_plt () */
1168 guint8
*code
= data
;
1171 g_assert (val
<= 0xffffff);
1173 ARM_ADD_REG_IMM (code
, ARMREG_IP
, ARMREG_PC
, (val
& 0xFF0000) >> 16, 16);
1175 ARM_ADD_REG_IMM (code
, ARMREG_IP
, ARMREG_PC
, 0, 0);
1176 ARM_ADD_REG_IMM (code
, ARMREG_IP
, ARMREG_IP
, (val
& 0xFF00) >> 8, 24);
1177 ARM_LDR_IMM (code
, ARMREG_PC
, ARMREG_IP
, val
& 0xFF);
1181 g_assert_not_reached ();
1184 g_assert_not_reached ();
1189 resolve_relocations (MonoImageWriter
*acfg
)
1193 gsize end_val
, start_val
;
1198 rr
= g_new0 (ElfReloc
, acfg
->num_relocs
);
1201 for (reloc
= acfg
->relocations
; reloc
; reloc
= reloc
->next
) {
1202 resolve_reloc (acfg
, reloc
, &data
, &vaddr
, &start_val
, &end_val
);
1203 /* FIXME: little endian */
1204 if (reloc
->reloc_type
) {
1205 /* Must be static */
1206 g_assert (start_val
> 0);
1207 do_reloc (acfg
, reloc
, data
, end_val
);
1210 data
[1] = end_val
>> 8;
1211 data
[2] = end_val
>> 16;
1212 data
[3] = end_val
>> 24;
1215 if (start_val
== 0 && reloc
->val1
[0] != '.') {
1216 rr
[i
].r_offset
= vaddr
;
1217 rr
[i
].r_info
= R_386_RELATIVE
;
1219 g_assert (i
<= acfg
->num_relocs
);
1225 #endif /* USE_ELF_RELA */
1227 static int normal_sections
[] = { SECT_DATA
, SECT_DEBUG_FRAME
, SECT_DEBUG_INFO
, SECT_DEBUG_ABBREV
, SECT_DEBUG_LINE
, SECT_DEBUG_LOC
};
1230 bin_writer_emit_writeout (MonoImageWriter
*acfg
)
1233 ElfProgHeader progh
[4];
1234 ElfSectHeader secth
[SECT_NUM
];
1240 ElfStrTable str_table
= {NULL
, NULL
};
1241 ElfStrTable sh_str_table
= {NULL
, NULL
};
1242 ElfStrTable dyn_str_table
= {NULL
, NULL
};
1243 BinSection
* all_sections
[32];
1244 BinSection
* sections
[SECT_NUM
];
1247 ElfDynamic dynamic
[14];
1249 int i
, num_sections
, file_offset
, virt_offset
, size
;
1252 /* Section headers */
1253 memset (§h
, 0, sizeof (secth
));
1254 memset (&dynamic
, 0, sizeof (dynamic
));
1255 memset (&header
, 0, sizeof (header
));
1257 for (i
= 1; i
< SECT_NUM
; ++i
) {
1258 secth
[i
].sh_name
= str_table_add (&sh_str_table
, section_info
[i
].name
);
1259 secth
[i
].sh_type
= section_info
[i
].type
;
1260 secth
[i
].sh_addralign
= section_info
[i
].align
;
1261 secth
[i
].sh_flags
= section_info
[i
].flags
;
1262 secth
[i
].sh_entsize
= section_info
[i
].esize
;
1264 secth
[SECT_DYNSYM
].sh_info
= TARGET_SIZEOF_VOID_P
== 4 ? 4 : 2;
1265 secth
[SECT_SYMTAB
].sh_info
= TARGET_SIZEOF_VOID_P
== 4 ? 20 : 17;
1266 secth
[SECT_HASH
].sh_link
= SECT_DYNSYM
;
1267 secth
[SECT_DYNSYM
].sh_link
= SECT_DYNSTR
;
1268 secth
[SECT_REL_DYN
].sh_link
= SECT_DYNSYM
;
1269 secth
[SECT_RELA_DYN
].sh_link
= SECT_DYNSYM
;
1270 secth
[SECT_DYNAMIC
].sh_link
= SECT_DYNSTR
;
1271 secth
[SECT_SYMTAB
].sh_link
= SECT_STRTAB
;
1273 num_sections
= collect_sections (acfg
, secth
, all_sections
, 16);
1274 hash
= build_hash (acfg
, num_sections
, &dyn_str_table
);
1276 g_print ("num_sections: %d\n", num_sections
);
1277 g_print ("dynsym: %d, dynstr size: %d\n", hash
[1], (int)dyn_str_table
.data
->len
);
1278 for (i
= 0; i
< num_sections
; ++i
) {
1279 g_print ("section %s, size: %d, %x\n", all_sections
[i
]->name
, all_sections
[i
]->cur_offset
, all_sections
[i
]->cur_offset
);
1282 /* Associate the bin sections with the ELF sections */
1283 memset (sections
, 0, sizeof (sections
));
1284 for (i
= 0; i
< num_sections
; ++i
) {
1285 BinSection
*sect
= all_sections
[i
];
1288 for (j
= 0; j
< SECT_NUM
; ++j
) {
1289 if (strcmp (sect
->name
, section_info
[j
].name
) == 0) {
1295 sections
[all_sections
[i
]->shidx
] = sect
;
1298 /* at this point we know where in the file the first segment sections go */
1299 dynsym
= collect_syms (acfg
, hash
, &dyn_str_table
, NULL
, NULL
);
1300 num_local_syms
= hash
[1];
1301 symtab
= collect_syms (acfg
, NULL
, &str_table
, secth
, &num_local_syms
);
1303 file_offset
= virt_offset
= sizeof (header
) + sizeof (progh
);
1304 secth
[SECT_HASH
].sh_addr
= secth
[SECT_HASH
].sh_offset
= file_offset
;
1305 size
= sizeof (int) * (2 + hash
[0] + hash
[1]);
1306 virt_offset
= (file_offset
+= size
);
1307 secth
[SECT_HASH
].sh_size
= size
;
1308 secth
[SECT_DYNSYM
].sh_addr
= secth
[SECT_DYNSYM
].sh_offset
= file_offset
;
1309 size
= sizeof (ElfSymbol
) * hash
[1];
1310 virt_offset
= (file_offset
+= size
);
1311 secth
[SECT_DYNSYM
].sh_size
= size
;
1312 secth
[SECT_DYNSTR
].sh_addr
= secth
[SECT_DYNSTR
].sh_offset
= file_offset
;
1313 size
= dyn_str_table
.data
->len
;
1314 virt_offset
= (file_offset
+= size
);
1315 secth
[SECT_DYNSTR
].sh_size
= size
;
1317 file_offset
&= ~(4-1);
1318 secth
[SECT_REL_DYN
].sh_addr
= secth
[SECT_REL_DYN
].sh_offset
= file_offset
;
1319 #ifndef USE_ELF_RELA
1320 size
= sizeof (ElfReloc
) * acfg
->num_relocs
;
1324 virt_offset
= (file_offset
+= size
);
1325 secth
[SECT_REL_DYN
].sh_size
= size
;
1326 secth
[SECT_RELA_DYN
].sh_addr
= secth
[SECT_RELA_DYN
].sh_offset
= file_offset
;
1328 size
= sizeof (ElfRelocA
) * acfg
->num_relocs
;
1332 virt_offset
= (file_offset
+= size
);
1333 secth
[SECT_RELA_DYN
].sh_size
= size
;
1335 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_TEXT
].sh_addralign
);
1336 virt_offset
= file_offset
;
1337 secth
[SECT_TEXT
].sh_addr
= secth
[SECT_TEXT
].sh_offset
= file_offset
;
1338 if (sections
[SECT_TEXT
]) {
1339 if (sections
[SECT_TEXT
]->has_addr
) {
1340 secth
[SECT_TEXT
].sh_addr
= sections
[SECT_TEXT
]->addr
;
1341 secth
[SECT_TEXT
].sh_flags
&= ~SHF_ALLOC
;
1343 size
= sections
[SECT_TEXT
]->cur_offset
;
1344 secth
[SECT_TEXT
].sh_size
= size
;
1345 file_offset
+= size
;
1348 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_RODATA
].sh_addralign
);
1349 virt_offset
= file_offset
;
1350 secth
[SECT_RODATA
].sh_addr
= virt_offset
;
1351 secth
[SECT_RODATA
].sh_offset
= file_offset
;
1352 if (sections
[SECT_RODATA
]) {
1353 size
= sections
[SECT_RODATA
]->cur_offset
;
1354 secth
[SECT_RODATA
].sh_size
= size
;
1355 file_offset
+= size
;
1356 virt_offset
+= size
;
1359 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_DYNAMIC
].sh_addralign
);
1360 virt_offset
= file_offset
;
1362 /* .dynamic, .got.plt, .data, .bss here */
1363 /* Have to increase the virt offset since these go to a separate segment */
1364 virt_offset
+= PAGESIZE
;
1365 secth
[SECT_DYNAMIC
].sh_addr
= virt_offset
;
1366 secth
[SECT_DYNAMIC
].sh_offset
= file_offset
;
1367 size
= sizeof (dynamic
);
1368 secth
[SECT_DYNAMIC
].sh_size
= size
;
1369 file_offset
+= size
;
1370 virt_offset
+= size
;
1372 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_GOT_PLT
].sh_addralign
);
1373 virt_offset
= ALIGN_TO (virt_offset
, secth
[SECT_GOT_PLT
].sh_addralign
);
1374 secth
[SECT_GOT_PLT
].sh_addr
= virt_offset
;
1375 secth
[SECT_GOT_PLT
].sh_offset
= file_offset
;
1376 size
= 3 * TARGET_SIZEOF_VOID_P
;
1377 secth
[SECT_GOT_PLT
].sh_size
= size
;
1378 file_offset
+= size
;
1379 virt_offset
+= size
;
1381 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_DATA
].sh_addralign
);
1382 virt_offset
= ALIGN_TO (virt_offset
, secth
[SECT_DATA
].sh_addralign
);
1383 secth
[SECT_DATA
].sh_addr
= virt_offset
;
1384 secth
[SECT_DATA
].sh_offset
= file_offset
;
1385 if (sections
[SECT_DATA
]) {
1386 size
= sections
[SECT_DATA
]->cur_offset
;
1387 secth
[SECT_DATA
].sh_size
= size
;
1388 file_offset
+= size
;
1389 virt_offset
+= size
;
1392 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_BSS
].sh_addralign
);
1393 virt_offset
= ALIGN_TO (virt_offset
, secth
[SECT_BSS
].sh_addralign
);
1394 secth
[SECT_BSS
].sh_addr
= virt_offset
;
1395 secth
[SECT_BSS
].sh_offset
= file_offset
;
1396 if (sections
[SECT_BSS
]) {
1397 size
= sections
[SECT_BSS
]->cur_offset
;
1398 secth
[SECT_BSS
].sh_size
= size
;
1401 /* virtual doesn't matter anymore */
1402 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_DEBUG_FRAME
].sh_addralign
);
1403 secth
[SECT_DEBUG_FRAME
].sh_offset
= file_offset
;
1404 if (sections
[SECT_DEBUG_FRAME
])
1405 size
= sections
[SECT_DEBUG_FRAME
]->cur_offset
;
1408 secth
[SECT_DEBUG_FRAME
].sh_size
= size
;
1409 file_offset
+= size
;
1411 secth
[SECT_DEBUG_INFO
].sh_offset
= file_offset
;
1412 if (sections
[SECT_DEBUG_INFO
])
1413 size
= sections
[SECT_DEBUG_INFO
]->cur_offset
;
1416 secth
[SECT_DEBUG_INFO
].sh_size
= size
;
1417 file_offset
+= size
;
1419 secth
[SECT_DEBUG_ABBREV
].sh_offset
= file_offset
;
1420 if (sections
[SECT_DEBUG_ABBREV
])
1421 size
= sections
[SECT_DEBUG_ABBREV
]->cur_offset
;
1424 secth
[SECT_DEBUG_ABBREV
].sh_size
= size
;
1425 file_offset
+= size
;
1427 secth
[SECT_DEBUG_LINE
].sh_offset
= file_offset
;
1428 if (sections
[SECT_DEBUG_LINE
])
1429 size
= sections
[SECT_DEBUG_LINE
]->cur_offset
;
1432 secth
[SECT_DEBUG_LINE
].sh_size
= size
;
1433 file_offset
+= size
;
1435 secth
[SECT_DEBUG_LOC
].sh_offset
= file_offset
;
1436 if (sections
[SECT_DEBUG_LOC
])
1437 size
= sections
[SECT_DEBUG_LOC
]->cur_offset
;
1440 secth
[SECT_DEBUG_LOC
].sh_size
= size
;
1441 file_offset
+= size
;
1443 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_SHSTRTAB
].sh_addralign
);
1444 secth
[SECT_SHSTRTAB
].sh_offset
= file_offset
;
1445 size
= sh_str_table
.data
->len
;
1446 secth
[SECT_SHSTRTAB
].sh_size
= size
;
1447 file_offset
+= size
;
1449 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_SYMTAB
].sh_addralign
);
1450 secth
[SECT_SYMTAB
].sh_offset
= file_offset
;
1451 size
= sizeof (ElfSymbol
) * num_local_syms
;
1452 secth
[SECT_SYMTAB
].sh_size
= size
;
1453 file_offset
+= size
;
1455 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_STRTAB
].sh_addralign
);
1456 secth
[SECT_STRTAB
].sh_offset
= file_offset
;
1457 size
= str_table
.data
->len
;
1458 secth
[SECT_STRTAB
].sh_size
= size
;
1459 file_offset
+= size
;
1461 for (i
= 1; i
< SECT_NUM
; ++i
) {
1462 if (section_info
[i
].esize
!= 0)
1463 g_assert (secth
[i
].sh_size
% section_info
[i
].esize
== 0);
1467 file_offset
&= ~(4-1);
1469 header
.e_ident
[EI_MAG0
] = ELFMAG0
;
1470 header
.e_ident
[EI_MAG1
] = ELFMAG1
;
1471 header
.e_ident
[EI_MAG2
] = ELFMAG2
;
1472 header
.e_ident
[EI_MAG3
] = ELFMAG3
;
1473 header
.e_ident
[EI_CLASS
] = TARGET_SIZEOF_VOID_P
== 4 ? ELFCLASS32
: ELFCLASS64
;
1474 header
.e_ident
[EI_DATA
] = ELFDATA2LSB
;
1475 header
.e_ident
[EI_VERSION
] = EV_CURRENT
;
1476 header
.e_ident
[EI_OSABI
] = ELFOSABI_NONE
;
1477 header
.e_ident
[EI_ABIVERSION
] = 0;
1478 for (i
= EI_PAD
; i
< EI_NIDENT
; ++i
)
1479 header
.e_ident
[i
] = 0;
1481 header
.e_type
= ET_DYN
;
1482 #if defined(TARGET_X86)
1483 header
.e_machine
= EM_386
;
1484 #elif defined(TARGET_AMD64)
1485 header
.e_machine
= EM_X86_64
;
1486 #elif defined(TARGET_ARM)
1487 header
.e_machine
= EM_ARM
;
1489 g_assert_not_reached ();
1491 header
.e_version
= 1;
1493 header
.e_phoff
= sizeof (header
);
1494 header
.e_ehsize
= sizeof (header
);
1495 header
.e_phentsize
= sizeof (ElfProgHeader
);
1497 header
.e_entry
= secth
[SECT_TEXT
].sh_addr
;
1498 header
.e_shstrndx
= SECT_SHSTRTAB
;
1499 header
.e_shentsize
= sizeof (ElfSectHeader
);
1500 header
.e_shnum
= SECT_NUM
;
1501 header
.e_shoff
= file_offset
;
1505 dynamic
[i
].d_tag
= DT_HASH
;
1506 dynamic
[i
].d_un
.d_val
= secth
[SECT_HASH
].sh_offset
;
1508 dynamic
[i
].d_tag
= DT_STRTAB
;
1509 dynamic
[i
].d_un
.d_val
= secth
[SECT_DYNSTR
].sh_offset
;
1511 dynamic
[i
].d_tag
= DT_SYMTAB
;
1512 dynamic
[i
].d_un
.d_val
= secth
[SECT_DYNSYM
].sh_offset
;
1514 dynamic
[i
].d_tag
= DT_STRSZ
;
1515 dynamic
[i
].d_un
.d_val
= dyn_str_table
.data
->len
;
1517 dynamic
[i
].d_tag
= DT_SYMENT
;
1518 dynamic
[i
].d_un
.d_val
= sizeof (ElfSymbol
);
1521 dynamic
[i
].d_tag
= DT_RELA
;
1522 dynamic
[i
].d_un
.d_val
= secth
[SECT_RELA_DYN
].sh_offset
;
1524 dynamic
[i
].d_tag
= DT_RELASZ
;
1525 dynamic
[i
].d_un
.d_val
= secth
[SECT_RELA_DYN
].sh_size
;
1527 dynamic
[i
].d_tag
= DT_RELAENT
;
1528 dynamic
[i
].d_un
.d_val
= sizeof (ElfRelocA
);
1531 dynamic
[i
].d_tag
= DT_REL
;
1532 dynamic
[i
].d_un
.d_val
= secth
[SECT_REL_DYN
].sh_offset
;
1534 dynamic
[i
].d_tag
= DT_RELSZ
;
1535 dynamic
[i
].d_un
.d_val
= secth
[SECT_REL_DYN
].sh_size
;
1537 dynamic
[i
].d_tag
= DT_RELENT
;
1538 dynamic
[i
].d_un
.d_val
= sizeof (ElfReloc
);
1541 dynamic
[i
].d_tag
= DT_RELCOUNT
;
1542 dynamic
[i
].d_un
.d_val
= acfg
->num_relocs
;
1545 /* Program header */
1546 memset (&progh
, 0, sizeof (progh
));
1547 progh
[0].p_type
= PT_LOAD
;
1548 progh
[0].p_filesz
= progh
[0].p_memsz
= secth
[SECT_DYNAMIC
].sh_offset
;
1549 progh
[0].p_align
= 4096;
1550 progh
[0].p_flags
= 5;
1552 progh
[1].p_type
= PT_LOAD
;
1553 progh
[1].p_offset
= secth
[SECT_DYNAMIC
].sh_offset
;
1554 progh
[1].p_vaddr
= progh
[1].p_paddr
= secth
[SECT_DYNAMIC
].sh_addr
;
1555 progh
[1].p_filesz
= secth
[SECT_BSS
].sh_offset
- secth
[SECT_DYNAMIC
].sh_offset
;
1556 progh
[1].p_memsz
= secth
[SECT_BSS
].sh_addr
+ secth
[SECT_BSS
].sh_size
- secth
[SECT_DYNAMIC
].sh_addr
;
1557 progh
[1].p_align
= 4096;
1558 progh
[1].p_flags
= 6;
1560 progh
[2].p_type
= PT_DYNAMIC
;
1561 progh
[2].p_offset
= secth
[SECT_DYNAMIC
].sh_offset
;
1562 progh
[2].p_vaddr
= progh
[2].p_paddr
= secth
[SECT_DYNAMIC
].sh_addr
;
1563 progh
[2].p_filesz
= progh
[2].p_memsz
= secth
[SECT_DYNAMIC
].sh_size
;
1564 progh
[2].p_align
= TARGET_SIZEOF_VOID_P
;
1565 progh
[2].p_flags
= 6;
1567 progh
[3].p_type
= PT_GNU_STACK
;
1568 progh
[3].p_offset
= secth
[SECT_DYNAMIC
].sh_offset
;
1569 progh
[3].p_vaddr
= progh
[3].p_paddr
= secth
[SECT_DYNAMIC
].sh_addr
;
1570 progh
[3].p_filesz
= progh
[3].p_memsz
= secth
[SECT_DYNAMIC
].sh_size
;
1571 progh
[3].p_align
= TARGET_SIZEOF_VOID_P
;
1572 progh
[3].p_flags
= 6;
1574 /* Compute the addresses of the bin sections, so relocation can be done */
1575 for (i
= 0; i
< SECT_NUM
; ++i
) {
1577 sections
[i
]->file_offset
= secth
[i
].sh_offset
;
1578 sections
[i
]->virt_offset
= secth
[i
].sh_addr
;
1582 reloc_symbols (acfg
, dynsym
, secth
, &dyn_str_table
, TRUE
);
1583 reloc_symbols (acfg
, symtab
, secth
, &str_table
, FALSE
);
1584 relocs
= resolve_relocations (acfg
);
1587 acfg
->out_buf_size
= file_offset
+ sizeof (secth
);
1588 acfg
->out_buf
= (guint8
*)g_malloc (acfg
->out_buf_size
);
1591 bin_writer_fwrite (acfg
, &header
, sizeof (header
), 1);
1592 bin_writer_fwrite (acfg
, &progh
, sizeof (progh
), 1);
1593 bin_writer_fwrite (acfg
, hash
, sizeof (int) * (hash
[0] + hash
[1] + 2), 1);
1594 bin_writer_fwrite (acfg
, dynsym
, sizeof (ElfSymbol
) * hash
[1], 1);
1595 bin_writer_fwrite (acfg
, dyn_str_table
.data
->str
, dyn_str_table
.data
->len
, 1);
1597 bin_writer_fseek (acfg
, secth
[SECT_REL_DYN
].sh_offset
);
1598 bin_writer_fwrite (acfg
, relocs
, sizeof (ElfReloc
), acfg
->num_relocs
);
1601 bin_writer_fseek (acfg
, secth
[SECT_RELA_DYN
].sh_offset
);
1602 bin_writer_fwrite (acfg
, relocs
, secth
[SECT_RELA_DYN
].sh_size
, 1);
1605 if (sections
[SECT_TEXT
]) {
1606 bin_writer_fseek (acfg
, secth
[SECT_TEXT
].sh_offset
);
1607 bin_writer_fwrite (acfg
, sections
[SECT_TEXT
]->data
, sections
[SECT_TEXT
]->cur_offset
, 1);
1610 if (sections
[SECT_RODATA
]) {
1611 bin_writer_fseek (acfg
, secth
[SECT_RODATA
].sh_offset
);
1612 bin_writer_fwrite (acfg
, sections
[SECT_RODATA
]->data
, sections
[SECT_RODATA
]->cur_offset
, 1);
1615 bin_writer_fseek (acfg
, secth
[SECT_DYNAMIC
].sh_offset
);
1616 bin_writer_fwrite (acfg
, dynamic
, sizeof (dynamic
), 1);
1619 size
= secth
[SECT_DYNAMIC
].sh_addr
;
1620 bin_writer_fseek (acfg
, secth
[SECT_GOT_PLT
].sh_offset
);
1621 bin_writer_fwrite (acfg
, &size
, sizeof (size
), 1);
1623 /* normal sections */
1624 for (i
= 0; i
< sizeof (normal_sections
) / sizeof (normal_sections
[0]); ++i
) {
1625 int sect
= normal_sections
[i
];
1627 if (sections
[sect
]) {
1628 bin_writer_fseek (acfg
, secth
[sect
].sh_offset
);
1629 bin_writer_fwrite (acfg
, sections
[sect
]->data
, sections
[sect
]->cur_offset
, 1);
1633 bin_writer_fseek (acfg
, secth
[SECT_SHSTRTAB
].sh_offset
);
1634 bin_writer_fwrite (acfg
, sh_str_table
.data
->str
, sh_str_table
.data
->len
, 1);
1635 bin_writer_fseek (acfg
, secth
[SECT_SYMTAB
].sh_offset
);
1636 bin_writer_fwrite (acfg
, symtab
, sizeof (ElfSymbol
) * num_local_syms
, 1);
1637 bin_writer_fseek (acfg
, secth
[SECT_STRTAB
].sh_offset
);
1638 bin_writer_fwrite (acfg
, str_table
.data
->str
, str_table
.data
->len
, 1);
1639 /*g_print ("file_offset %d vs %d\n", file_offset, ftell (file));*/
1640 /*g_assert (file_offset >= ftell (file));*/
1641 bin_writer_fseek (acfg
, file_offset
);
1642 bin_writer_fwrite (acfg
, §h
, sizeof (secth
), 1);
1650 #endif /* USE_ELF_WRITER */
1652 #endif /* USE_BIN_WRITER */
1657 asm_writer_emit_start (MonoImageWriter
*acfg
)
1659 #if defined(TARGET_ASM_APPLE)
1660 fprintf (acfg
->fp
, ".subsections_via_symbols\n");
1665 asm_writer_emit_writeout (MonoImageWriter
*acfg
)
1673 asm_writer_emit_unset_mode (MonoImageWriter
*acfg
)
1675 if (acfg
->mode
== EMIT_NONE
)
1677 fprintf (acfg
->fp
, "\n");
1678 acfg
->mode
= EMIT_NONE
;
1682 asm_writer_emit_section_change (MonoImageWriter
*acfg
, const char *section_name
, int subsection_index
)
1684 asm_writer_emit_unset_mode (acfg
);
1685 #if defined(TARGET_ASM_APPLE)
1686 if (strcmp(section_name
, ".bss") == 0)
1687 fprintf (acfg
->fp
, "%s\n", ".data");
1688 else if (strstr (section_name
, ".debug") == section_name
) {
1689 //g_assert (subsection_index == 0);
1690 fprintf (acfg
->fp
, ".section __DWARF, __%s,regular,debug\n", section_name
+ 1);
1692 fprintf (acfg
->fp
, "%s\n", section_name
);
1693 #elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_POWERPC)
1694 /* ARM gas doesn't seem to like subsections of .bss */
1695 if (!strcmp (section_name
, ".text") || !strcmp (section_name
, ".data")) {
1696 fprintf (acfg
->fp
, "%s %d\n", section_name
, subsection_index
);
1698 fprintf (acfg
->fp
, ".section \"%s\"\n", section_name
);
1699 fprintf (acfg
->fp
, ".subsection %d\n", subsection_index
);
1701 #elif defined(HOST_WIN32)
1702 fprintf (acfg
->fp
, ".section %s\n", section_name
);
1704 if (!strcmp (section_name
, ".text") || !strcmp (section_name
, ".data") || !strcmp (section_name
, ".bss")) {
1705 fprintf (acfg
->fp
, "%s %d\n", section_name
, subsection_index
);
1707 fprintf (acfg
->fp
, ".section \"%s\"\n", section_name
);
1708 fprintf (acfg
->fp
, ".subsection %d\n", subsection_index
);
1714 const char *get_label (const char *s
)
1716 #ifdef TARGET_ASM_APPLE
1717 if (s
[0] == '.' && s
[1] == 'L')
1718 /* apple uses "L" instead of ".L" to mark temporary labels */
1725 #define GLOBAL_SYMBOL_DEF_SCL 2
1726 #define LOCAL_SYMBOL_DEF_SCL 3
1729 asm_writer_in_data_section (MonoImageWriter
*acfg
)
1731 gboolean in_data_section
= FALSE
;
1732 const char *data_sections
[] = {".data", ".bss", ".rdata"};
1734 for (guchar i
= 0; i
< G_N_ELEMENTS (data_sections
); ++i
) {
1735 if (strcmp (acfg
->current_section
, data_sections
[i
]) == 0) {
1736 in_data_section
= TRUE
;
1741 return in_data_section
;
1745 asm_writer_emit_symbol_type (MonoImageWriter
*acfg
, const char *name
, gboolean func
, gboolean global
)
1747 asm_writer_emit_unset_mode (acfg
);
1750 fprintf (acfg
->fp
, "\t.def %s; .scl %d; .type 32; .endef\n", name
, (global
== TRUE
? GLOBAL_SYMBOL_DEF_SCL
: LOCAL_SYMBOL_DEF_SCL
));
1752 if (!asm_writer_in_data_section (acfg
))
1753 fprintf (acfg
->fp
, "\t.data\n");
1762 asm_writer_emit_symbol_type (MonoImageWriter
*acfg
, const char *name
, gboolean func
, gboolean global
)
1771 asm_writer_emit_unset_mode (acfg
);
1773 #if defined(TARGET_ASM_APPLE)
1775 #elif defined(TARGET_ARM)
1776 fprintf (acfg
->fp
, "\t.type %s,#%s\n", name
, stype
);
1778 fprintf (acfg
->fp
, "\t.type %s,@%s\n", name
, stype
);
1781 #endif /* TARGET_WIN32 */
1784 asm_writer_emit_global (MonoImageWriter
*acfg
, const char *name
, gboolean func
)
1786 asm_writer_emit_unset_mode (acfg
);
1788 fprintf (acfg
->fp
, "\t.globl %s\n", name
);
1790 asm_writer_emit_symbol_type (acfg
, name
, func
, TRUE
);
1794 asm_writer_emit_local_symbol (MonoImageWriter
*acfg
, const char *name
, const char *end_label
, gboolean func
)
1796 asm_writer_emit_unset_mode (acfg
);
1798 #if !defined(TARGET_ASM_APPLE) && !defined(TARGET_WIN32)
1799 fprintf (acfg
->fp
, "\t.local %s\n", name
);
1802 asm_writer_emit_symbol_type (acfg
, name
, func
, FALSE
);
1806 asm_writer_emit_symbol_size (MonoImageWriter
*acfg
, const char *name
, const char *end_label
)
1808 asm_writer_emit_unset_mode (acfg
);
1811 #if !defined(TARGET_ASM_APPLE) && !defined(TARGET_WIN32)
1812 fprintf (acfg
->fp
, "\t.size %s,%s-%s\n", name
, end_label
, name
);
1817 asm_writer_emit_label (MonoImageWriter
*acfg
, const char *name
)
1819 asm_writer_emit_unset_mode (acfg
);
1820 fprintf (acfg
->fp
, "%s:\n", get_label (name
));
1824 asm_writer_emit_string (MonoImageWriter
*acfg
, const char *value
)
1826 asm_writer_emit_unset_mode (acfg
);
1827 fprintf (acfg
->fp
, "\t%s \"%s\"\n", AS_STRING_DIRECTIVE
, value
);
1831 asm_writer_emit_line (MonoImageWriter
*acfg
)
1833 asm_writer_emit_unset_mode (acfg
);
1834 fprintf (acfg
->fp
, "\n");
1838 asm_writer_emit_alignment (MonoImageWriter
*acfg
, int size
)
1840 asm_writer_emit_unset_mode (acfg
);
1841 #if defined(TARGET_ARM)
1842 fprintf (acfg
->fp
, "\t.align %d\n", ilog2 (size
));
1843 #elif defined(__ppc__) && defined(TARGET_ASM_APPLE)
1844 // the mach-o assembler specifies alignments as powers of 2.
1845 fprintf (acfg
->fp
, "\t.align %d\t; ilog2\n", ilog2(size
));
1846 #elif defined(TARGET_ASM_GAS)
1847 fprintf (acfg
->fp
, "\t.balign %d\n", size
);
1848 #elif defined(TARGET_ASM_APPLE)
1849 fprintf (acfg
->fp
, "\t.align %d\n", ilog2 (size
));
1851 fprintf (acfg
->fp
, "\t.align %d\n", size
);
1855 #ifndef USE_BIN_WRITER
1857 asm_writer_emit_alignment_fill (MonoImageWriter
*acfg
, int size
, int fill
)
1859 asm_writer_emit_unset_mode (acfg
);
1860 #if defined(TARGET_ASM_APPLE)
1861 fprintf (acfg
->fp
, "\t.align %d, 0x%0x\n", ilog2 (size
), fill
);
1863 asm_writer_emit_alignment (acfg
, size
);
1869 asm_writer_emit_pointer_unaligned (MonoImageWriter
*acfg
, const char *target
)
1871 asm_writer_emit_unset_mode (acfg
);
1872 fprintf (acfg
->fp
, "\t%s %s\n", AS_POINTER_DIRECTIVE
, target
? target
: "0");
1876 asm_writer_emit_pointer (MonoImageWriter
*acfg
, const char *target
)
1878 asm_writer_emit_unset_mode (acfg
);
1879 asm_writer_emit_alignment (acfg
, TARGET_SIZEOF_VOID_P
);
1880 asm_writer_emit_pointer_unaligned (acfg
, target
);
1883 static char *byte_to_str
;
1886 asm_writer_emit_bytes (MonoImageWriter
*acfg
, const guint8
* buf
, int size
)
1889 if (acfg
->mode
!= EMIT_BYTE
) {
1890 acfg
->mode
= EMIT_BYTE
;
1891 acfg
->col_count
= 0;
1894 if (byte_to_str
== NULL
) {
1895 byte_to_str
= g_new0 (char, 256 * 8);
1896 for (i
= 0; i
< 256; ++i
) {
1897 sprintf (byte_to_str
+ (i
* 8), ",%d", i
);
1901 for (i
= 0; i
< size
; ++i
, ++acfg
->col_count
) {
1902 if ((acfg
->col_count
% 32) == 0)
1903 fprintf (acfg
->fp
, "\n\t.byte %d", buf
[i
]);
1905 fputs (byte_to_str
+ (buf
[i
] * 8), acfg
->fp
);
1910 asm_writer_emit_int16 (MonoImageWriter
*acfg
, int value
)
1912 if (acfg
->mode
!= EMIT_WORD
) {
1913 acfg
->mode
= EMIT_WORD
;
1914 acfg
->col_count
= 0;
1916 if ((acfg
->col_count
++ % 8) == 0)
1917 fprintf (acfg
->fp
, "\n\t%s ", AS_INT16_DIRECTIVE
);
1919 fprintf (acfg
->fp
, ", ");
1920 fprintf (acfg
->fp
, "%d", value
);
1924 asm_writer_emit_int32 (MonoImageWriter
*acfg
, int value
)
1926 if (acfg
->mode
!= EMIT_LONG
) {
1927 acfg
->mode
= EMIT_LONG
;
1928 acfg
->col_count
= 0;
1930 if ((acfg
->col_count
++ % 8) == 0)
1931 fprintf (acfg
->fp
, "\n\t%s ", AS_INT32_DIRECTIVE
);
1933 fprintf (acfg
->fp
, ",");
1934 fprintf (acfg
->fp
, "%d", value
);
1938 asm_writer_emit_symbol (MonoImageWriter
*acfg
, const char *symbol
)
1940 if (acfg
->mode
!= EMIT_LONG
) {
1941 acfg
->mode
= EMIT_LONG
;
1942 acfg
->col_count
= 0;
1945 symbol
= get_label (symbol
);
1947 if ((acfg
->col_count
++ % 8) == 0)
1948 fprintf (acfg
->fp
, "\n\t%s ", AS_INT32_DIRECTIVE
);
1950 fprintf (acfg
->fp
, ",");
1951 fprintf (acfg
->fp
, "%s", symbol
);
1955 asm_writer_emit_symbol_diff (MonoImageWriter
*acfg
, const char *end
, const char* start
, int offset
)
1957 #ifdef TARGET_ASM_APPLE
1958 //char symbol [128];
1961 if (acfg
->mode
!= EMIT_LONG
) {
1962 acfg
->mode
= EMIT_LONG
;
1963 acfg
->col_count
= 0;
1966 // FIXME: This doesn't seem to work on the iphone
1968 //#ifdef TARGET_ASM_APPLE
1969 /* The apple assembler needs a separate symbol to be able to handle complex expressions */
1970 sprintf (symbol
, "LTMP_SYM%d", acfg
->label_gen
);
1971 start
= get_label (start
);
1972 end
= get_label (end
);
1975 fprintf (acfg
->fp
, "\n%s=%s - %s + %d", symbol
, end
, start
, offset
);
1976 else if (offset
< 0)
1977 fprintf (acfg
->fp
, "\n%s=%s - %s %d", symbol
, end
, start
, offset
);
1979 fprintf (acfg
->fp
, "\n%s=%s - %s", symbol
, end
, start
);
1981 fprintf (acfg
->fp
, "\n\t%s ", AS_INT32_DIRECTIVE
);
1982 fprintf (acfg
->fp
, "%s", symbol
);
1984 start
= get_label (start
);
1985 end
= get_label (end
);
1987 if (offset
== 0 && strcmp (start
, ".") != 0) {
1989 sprintf (symbol
, "%sDIFF_SYM%d", AS_TEMP_LABEL_PREFIX
, acfg
->label_gen
);
1991 fprintf (acfg
->fp
, "\n%s=%s - %s", symbol
, end
, start
);
1992 fprintf (acfg
->fp
, "\n\t%s ", AS_INT32_DIRECTIVE
);
1993 fprintf (acfg
->fp
, "%s", symbol
);
1997 if ((acfg
->col_count
++ % 8) == 0)
1998 fprintf (acfg
->fp
, "\n\t%s ", AS_INT32_DIRECTIVE
);
2000 fprintf (acfg
->fp
, ",");
2002 fprintf (acfg
->fp
, "%s - %s + %d", end
, start
, offset
);
2003 else if (offset
< 0)
2004 fprintf (acfg
->fp
, "%s - %s %d", end
, start
, offset
);
2006 fprintf (acfg
->fp
, "%s - %s", end
, start
);
2011 asm_writer_emit_zero_bytes (MonoImageWriter
*acfg
, int num
)
2013 asm_writer_emit_unset_mode (acfg
);
2014 fprintf (acfg
->fp
, "\t%s %d\n", AS_SKIP_DIRECTIVE
, num
);
2017 /* EMIT FUNCTIONS */
2020 mono_img_writer_emit_start (MonoImageWriter
*acfg
)
2022 #ifdef USE_BIN_WRITER
2023 if (acfg
->use_bin_writer
)
2024 bin_writer_emit_start (acfg
);
2026 asm_writer_emit_start (acfg
);
2028 asm_writer_emit_start (acfg
);
2033 mono_img_writer_emit_section_change (MonoImageWriter
*acfg
, const char *section_name
, int subsection_index
)
2035 #ifdef USE_BIN_WRITER
2036 if (acfg
->use_bin_writer
)
2037 bin_writer_emit_section_change (acfg
, section_name
, subsection_index
);
2039 asm_writer_emit_section_change (acfg
, section_name
, subsection_index
);
2041 asm_writer_emit_section_change (acfg
, section_name
, subsection_index
);
2044 acfg
->current_section
= section_name
;
2045 acfg
->current_subsection
= subsection_index
;
2049 mono_img_writer_emit_push_section (MonoImageWriter
*acfg
, const char *section_name
, int subsection
)
2051 g_assert (acfg
->stack_pos
< 16 - 1);
2052 acfg
->section_stack
[acfg
->stack_pos
] = acfg
->current_section
;
2053 acfg
->subsection_stack
[acfg
->stack_pos
] = acfg
->current_subsection
;
2056 mono_img_writer_emit_section_change (acfg
, section_name
, subsection
);
2060 mono_img_writer_emit_pop_section (MonoImageWriter
*acfg
)
2062 g_assert (acfg
->stack_pos
> 0);
2064 mono_img_writer_emit_section_change (acfg
, acfg
->section_stack
[acfg
->stack_pos
], acfg
->subsection_stack
[acfg
->stack_pos
]);
2068 mono_img_writer_set_section_addr (MonoImageWriter
*acfg
, guint64 addr
)
2070 #ifdef USE_BIN_WRITER
2071 if (!acfg
->use_bin_writer
)
2074 bin_writer_set_section_addr (acfg
, addr
);
2081 mono_img_writer_emit_global (MonoImageWriter
*acfg
, const char *name
, gboolean func
)
2083 #ifdef USE_BIN_WRITER
2084 if (acfg
->use_bin_writer
)
2085 bin_writer_emit_global (acfg
, name
, func
);
2087 asm_writer_emit_global (acfg
, name
, func
);
2089 asm_writer_emit_global (acfg
, name
, func
);
2094 mono_img_writer_emit_local_symbol (MonoImageWriter
*acfg
, const char *name
, const char *end_label
, gboolean func
)
2096 #ifdef USE_BIN_WRITER
2097 if (acfg
->use_bin_writer
)
2098 bin_writer_emit_local_symbol (acfg
, name
, end_label
, func
);
2100 asm_writer_emit_local_symbol (acfg
, name
, end_label
, func
);
2102 asm_writer_emit_local_symbol (acfg
, name
, end_label
, func
);
2107 mono_img_writer_emit_symbol_size (MonoImageWriter
*acfg
, const char *name
, const char *end_label
)
2109 if (!acfg
->use_bin_writer
)
2110 asm_writer_emit_symbol_size (acfg
, name
, end_label
);
2114 mono_img_writer_emit_label (MonoImageWriter
*acfg
, const char *name
)
2116 #ifdef USE_BIN_WRITER
2117 if (acfg
->use_bin_writer
)
2118 bin_writer_emit_label (acfg
, name
);
2120 asm_writer_emit_label (acfg
, name
);
2122 asm_writer_emit_label (acfg
, name
);
2127 mono_img_writer_emit_bytes (MonoImageWriter
*acfg
, const guint8
* buf
, int size
)
2129 #ifdef USE_BIN_WRITER
2130 if (acfg
->use_bin_writer
)
2131 bin_writer_emit_bytes (acfg
, buf
, size
);
2133 asm_writer_emit_bytes (acfg
, buf
, size
);
2135 asm_writer_emit_bytes (acfg
, buf
, size
);
2140 mono_img_writer_emit_string (MonoImageWriter
*acfg
, const char *value
)
2142 #ifdef USE_BIN_WRITER
2143 if (acfg
->use_bin_writer
)
2144 bin_writer_emit_string (acfg
, value
);
2146 asm_writer_emit_string (acfg
, value
);
2148 asm_writer_emit_string (acfg
, value
);
2153 mono_img_writer_emit_line (MonoImageWriter
*acfg
)
2155 #ifdef USE_BIN_WRITER
2156 if (acfg
->use_bin_writer
)
2157 bin_writer_emit_line (acfg
);
2159 asm_writer_emit_line (acfg
);
2161 asm_writer_emit_line (acfg
);
2166 mono_img_writer_emit_alignment (MonoImageWriter
*acfg
, int size
)
2168 #ifdef USE_BIN_WRITER
2169 if (acfg
->use_bin_writer
)
2170 bin_writer_emit_alignment (acfg
, size
);
2172 asm_writer_emit_alignment (acfg
, size
);
2174 asm_writer_emit_alignment (acfg
, size
);
2179 mono_img_writer_emit_alignment_fill (MonoImageWriter
*acfg
, int size
, int fill
)
2181 #ifdef USE_BIN_WRITER
2182 if (acfg
->use_bin_writer
)
2183 bin_writer_emit_alignment (acfg
, size
);
2185 asm_writer_emit_alignment (acfg
, size
);
2187 asm_writer_emit_alignment_fill (acfg
, size
, fill
);
2192 mono_img_writer_emit_pointer_unaligned (MonoImageWriter
*acfg
, const char *target
)
2194 #ifdef USE_BIN_WRITER
2195 if (acfg
->use_bin_writer
)
2196 bin_writer_emit_pointer_unaligned (acfg
, target
);
2198 asm_writer_emit_pointer_unaligned (acfg
, target
);
2200 asm_writer_emit_pointer_unaligned (acfg
, target
);
2205 mono_img_writer_emit_pointer (MonoImageWriter
*acfg
, const char *target
)
2207 #ifdef USE_BIN_WRITER
2208 if (acfg
->use_bin_writer
)
2209 bin_writer_emit_pointer (acfg
, target
);
2211 asm_writer_emit_pointer (acfg
, target
);
2213 asm_writer_emit_pointer (acfg
, target
);
2218 mono_img_writer_emit_int16 (MonoImageWriter
*acfg
, int value
)
2220 #ifdef USE_BIN_WRITER
2221 if (acfg
->use_bin_writer
)
2222 bin_writer_emit_int16 (acfg
, value
);
2224 asm_writer_emit_int16 (acfg
, value
);
2226 asm_writer_emit_int16 (acfg
, value
);
2231 mono_img_writer_emit_int32 (MonoImageWriter
*acfg
, int value
)
2233 #ifdef USE_BIN_WRITER
2234 if (acfg
->use_bin_writer
)
2235 bin_writer_emit_int32 (acfg
, value
);
2237 asm_writer_emit_int32 (acfg
, value
);
2239 asm_writer_emit_int32 (acfg
, value
);
2244 mono_img_writer_emit_symbol (MonoImageWriter
*acfg
, const char *symbol
)
2246 #ifdef USE_BIN_WRITER
2247 if (acfg
->use_bin_writer
)
2248 bin_writer_emit_symbol (acfg
, symbol
);
2250 asm_writer_emit_symbol (acfg
, symbol
);
2252 asm_writer_emit_symbol (acfg
, symbol
);
2257 mono_img_writer_emit_symbol_diff (MonoImageWriter
*acfg
, const char *end
, const char* start
, int offset
)
2259 #ifdef USE_BIN_WRITER
2260 if (acfg
->use_bin_writer
)
2261 bin_writer_emit_symbol_diff (acfg
, end
, start
, offset
);
2263 asm_writer_emit_symbol_diff (acfg
, end
, start
, offset
);
2265 asm_writer_emit_symbol_diff (acfg
, end
, start
, offset
);
2270 mono_img_writer_emit_zero_bytes (MonoImageWriter
*acfg
, int num
)
2272 #ifdef USE_BIN_WRITER
2273 if (acfg
->use_bin_writer
)
2274 bin_writer_emit_zero_bytes (acfg
, num
);
2276 asm_writer_emit_zero_bytes (acfg
, num
);
2278 asm_writer_emit_zero_bytes (acfg
, num
);
2283 mono_img_writer_emit_writeout (MonoImageWriter
*acfg
)
2285 #ifdef USE_BIN_WRITER
2286 if (acfg
->use_bin_writer
)
2287 return bin_writer_emit_writeout (acfg
);
2289 return asm_writer_emit_writeout (acfg
);
2291 return asm_writer_emit_writeout (acfg
);
2296 mono_img_writer_emit_byte (MonoImageWriter
*acfg
, guint8 val
)
2298 mono_img_writer_emit_bytes (acfg
, &val
, 1);
2302 * Emit a relocation entry of type RELOC_TYPE against symbol SYMBOL at the current PC.
2303 * Do not advance PC.
2306 mono_img_writer_emit_reloc (MonoImageWriter
*acfg
, int reloc_type
, const char *symbol
, int addend
)
2308 /* This is only supported by the bin writer */
2309 #ifdef USE_BIN_WRITER
2310 if (acfg
->use_bin_writer
)
2311 bin_writer_emit_reloc (acfg
, reloc_type
, symbol
, addend
);
2313 g_assert_not_reached ();
2315 g_assert_not_reached ();
2320 * mono_img_writer_emit_unset_mode:
2322 * Flush buffered data so it is safe to write to the output file from outside this
2323 * module. This is a nop for the binary writer.
2326 mono_img_writer_emit_unset_mode (MonoImageWriter
*acfg
)
2328 if (!acfg
->use_bin_writer
)
2329 asm_writer_emit_unset_mode (acfg
);
2333 * mono_img_writer_get_output:
2335 * Return the output buffer of a binary writer emitting to memory. The returned memory
2336 * is from malloc, and it is owned by the caller.
2339 mono_img_writer_get_output (MonoImageWriter
*acfg
, guint32
*size
)
2341 #ifdef USE_BIN_WRITER
2344 g_assert (acfg
->use_bin_writer
);
2346 buf
= acfg
->out_buf
;
2347 *size
= acfg
->out_buf_size
;
2348 acfg
->out_buf
= NULL
;
2351 g_assert_not_reached ();
2357 * Return whenever the binary writer is supported on this platform.
2360 mono_bin_writer_supported (void)
2362 #ifdef USE_BIN_WRITER
2370 * mono_img_writer_create:
2372 * Create an image writer writing to FP. If USE_BIN_WRITER is TRUE, FP can be NULL,
2373 * in this case the image writer will write to a memory buffer obtainable by calling
2374 * mono_img_writer_get_output ().
2377 mono_img_writer_create (FILE *fp
, gboolean use_bin_writer
)
2379 MonoImageWriter
*w
= g_new0 (MonoImageWriter
, 1);
2381 #ifndef USE_BIN_WRITER
2382 g_assert (!use_bin_writer
);
2385 if (!use_bin_writer
)
2389 w
->use_bin_writer
= use_bin_writer
;
2390 w
->mempool
= mono_mempool_new ();
2396 mono_img_writer_destroy (MonoImageWriter
*w
)
2398 // FIXME: Free all the stuff
2399 mono_mempool_destroy (w
->mempool
);
2404 mono_img_writer_subsections_supported (MonoImageWriter
*acfg
)
2406 #ifdef TARGET_ASM_APPLE
2407 return acfg
->use_bin_writer
;
2414 mono_img_writer_get_fp (MonoImageWriter
*acfg
)
2420 mono_img_writer_get_temp_label_prefix (MonoImageWriter
*acfg
)
2422 return AS_TEMP_LABEL_PREFIX
;