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_ilp32__)
78 #define AS_POINTER_DIRECTIVE ".quad"
79 #elif defined(TARGET_ARM64)
81 #ifdef TARGET_ASM_APPLE
82 #define AS_POINTER_DIRECTIVE ".quad"
84 #define AS_POINTER_DIRECTIVE ".xword"
88 #define AS_POINTER_DIRECTIVE ".long"
91 #if defined(TARGET_ASM_APPLE)
92 #define AS_INT16_DIRECTIVE ".short"
93 #elif defined(TARGET_ASM_GAS) && defined(TARGET_WIN32)
94 #define AS_INT16_DIRECTIVE ".word"
95 #elif defined(TARGET_ASM_GAS)
96 #define AS_INT16_DIRECTIVE ".hword"
98 #define AS_INT16_DIRECTIVE ".word"
101 #if defined(TARGET_ASM_APPLE)
102 #define AS_SKIP_DIRECTIVE ".space"
104 #define AS_SKIP_DIRECTIVE ".skip"
107 #if defined(TARGET_ASM_APPLE)
108 #define AS_GLOBAL_PREFIX "_"
110 #define AS_GLOBAL_PREFIX ""
113 #ifdef TARGET_ASM_APPLE
114 #define AS_TEMP_LABEL_PREFIX "L"
116 #define AS_TEMP_LABEL_PREFIX ".L"
119 #define ROUND_DOWN(VALUE,SIZE) ((VALUE) & ~((SIZE) - 1))
121 #ifdef USE_BIN_WRITER
123 typedef struct _BinSymbol BinSymbol
;
124 typedef struct _BinReloc BinReloc
;
125 typedef struct _BinSection BinSection
;
137 struct _MonoImageWriter
{
138 MonoMemPool
*mempool
;
140 gboolean use_bin_writer
;
141 const char *current_section
;
142 int current_subsection
;
143 const char *section_stack
[16];
144 int subsection_stack
[16];
148 #ifdef USE_BIN_WRITER
150 BinSection
*sections
;
151 BinSection
*cur_section
;
152 BinReloc
*relocations
;
156 int out_buf_size
, out_buf_pos
;
160 int mode
; /* emit mode */
161 int col_count
; /* bytes emitted per .byte line */
165 static G_GNUC_UNUSED
int
166 ilog2(register int value
)
169 while (value
& ~0xf) count
+= 4, value
>>= 4;
170 while (value
) count
++, value
>>= 1;
174 #ifdef USE_BIN_WRITER
176 typedef struct _BinLabel BinLabel
;
187 BinSection
*val2_section
;
200 gboolean is_function
;
221 bin_writer_emit_start (MonoImageWriter
*acfg
)
223 acfg
->labels
= g_hash_table_new (g_str_hash
, g_str_equal
);
227 bin_writer_emit_section_change (MonoImageWriter
*acfg
, const char *section_name
, int subsection_index
)
231 if (acfg
->cur_section
&& acfg
->cur_section
->subsection
== subsection_index
232 && strcmp (acfg
->cur_section
->name
, section_name
) == 0)
234 for (section
= acfg
->sections
; section
; section
= section
->next
) {
235 if (section
->subsection
== subsection_index
&& strcmp (section
->name
, section_name
) == 0) {
236 acfg
->cur_section
= section
;
241 section
= g_new0 (BinSection
, 1);
242 section
->name
= g_strdup (section_name
);
243 section
->subsection
= subsection_index
;
244 section
->next
= acfg
->sections
;
245 acfg
->sections
= section
;
246 acfg
->cur_section
= section
;
251 bin_writer_set_section_addr (MonoImageWriter
*acfg
, guint64 addr
)
253 acfg
->cur_section
->addr
= addr
;
254 acfg
->cur_section
->has_addr
= TRUE
;
258 bin_writer_emit_symbol_inner (MonoImageWriter
*acfg
, const char *name
, const char *end_label
, gboolean is_global
, gboolean func
)
260 BinSymbol
*symbol
= g_new0 (BinSymbol
, 1);
261 symbol
->name
= g_strdup (name
);
263 symbol
->end_label
= g_strdup (end_label
);
264 symbol
->is_function
= func
;
265 symbol
->is_global
= is_global
;
266 symbol
->section
= acfg
->cur_section
;
267 /* FIXME: we align after this call... */
268 symbol
->offset
= symbol
->section
->cur_offset
;
269 symbol
->next
= acfg
->symbols
;
270 acfg
->symbols
= symbol
;
274 bin_writer_emit_global (MonoImageWriter
*acfg
, const char *name
, gboolean func
)
276 bin_writer_emit_symbol_inner (acfg
, name
, NULL
, TRUE
, func
);
280 bin_writer_emit_local_symbol (MonoImageWriter
*acfg
, const char *name
, const char *end_label
, gboolean func
)
282 bin_writer_emit_symbol_inner (acfg
, name
, end_label
, FALSE
, func
);
286 bin_writer_emit_label (MonoImageWriter
*acfg
, const char *name
)
288 BinLabel
*label
= g_new0 (BinLabel
, 1);
289 label
->name
= g_strdup (name
);
290 label
->section
= acfg
->cur_section
;
291 label
->offset
= acfg
->cur_section
->cur_offset
;
292 g_hash_table_insert (acfg
->labels
, label
->name
, label
);
296 bin_writer_emit_ensure_buffer (BinSection
*section
, int size
)
298 int new_offset
= section
->cur_offset
+ size
;
299 if (new_offset
>= section
->data_len
) {
300 int new_size
= section
->data_len
? section
->data_len
* 2: 256;
302 while (new_size
<= new_offset
)
304 data
= (guint8
*)g_malloc0 (new_size
);
305 memcpy (data
, section
->data
, section
->data_len
);
306 g_free (section
->data
);
307 section
->data
= data
;
308 section
->data_len
= new_size
;
313 bin_writer_emit_bytes (MonoImageWriter
*acfg
, const guint8
* buf
, int size
)
315 bin_writer_emit_ensure_buffer (acfg
->cur_section
, size
);
316 memcpy (acfg
->cur_section
->data
+ acfg
->cur_section
->cur_offset
, buf
, size
);
317 acfg
->cur_section
->cur_offset
+= size
;
321 bin_writer_emit_string (MonoImageWriter
*acfg
, const char *value
)
323 int size
= strlen (value
) + 1;
324 bin_writer_emit_bytes (acfg
, (const guint8
*)value
, size
);
328 bin_writer_emit_line (MonoImageWriter
*acfg
)
330 /* Nothing to do in binary writer */
334 bin_writer_emit_alignment (MonoImageWriter
*acfg
, int size
)
336 int offset
= acfg
->cur_section
->cur_offset
;
338 offset
+= (size
- 1);
339 offset
&= ~(size
- 1);
340 add
= offset
- acfg
->cur_section
->cur_offset
;
342 bin_writer_emit_ensure_buffer (acfg
->cur_section
, add
);
343 acfg
->cur_section
->cur_offset
+= add
;
348 bin_writer_emit_pointer_unaligned (MonoImageWriter
*acfg
, const char *target
)
353 acfg
->cur_section
->cur_offset
+= sizeof (gpointer
);
357 reloc
= g_new0 (BinReloc
, 1);
358 reloc
->val1
= g_strdup (target
);
359 reloc
->section
= acfg
->cur_section
;
360 reloc
->section_offset
= acfg
->cur_section
->cur_offset
;
361 reloc
->next
= acfg
->relocations
;
362 acfg
->relocations
= reloc
;
363 if (strcmp (reloc
->section
->name
, ".data") == 0) {
365 //g_print ("reloc: %s at %d\n", target, acfg->cur_section->cur_offset);
367 acfg
->cur_section
->cur_offset
+= sizeof (gpointer
);
371 bin_writer_emit_pointer (MonoImageWriter
*acfg
, const char *target
)
373 bin_writer_emit_alignment (acfg
, sizeof (gpointer
));
374 bin_writer_emit_pointer_unaligned (acfg
, target
);
378 bin_writer_emit_int16 (MonoImageWriter
*acfg
, int value
)
381 bin_writer_emit_ensure_buffer (acfg
->cur_section
, 2);
382 data
= acfg
->cur_section
->data
+ acfg
->cur_section
->cur_offset
;
383 acfg
->cur_section
->cur_offset
+= 2;
384 /* FIXME: little endian */
386 data
[1] = value
>> 8;
390 bin_writer_emit_int32 (MonoImageWriter
*acfg
, int value
)
393 bin_writer_emit_ensure_buffer (acfg
->cur_section
, 4);
394 data
= acfg
->cur_section
->data
+ acfg
->cur_section
->cur_offset
;
395 acfg
->cur_section
->cur_offset
+= 4;
396 /* FIXME: little endian */
398 data
[1] = value
>> 8;
399 data
[2] = value
>> 16;
400 data
[3] = value
>> 24;
404 create_reloc (MonoImageWriter
*acfg
, const char *end
, const char* start
, int offset
)
407 reloc
= (BinReloc
*)mono_mempool_alloc0 (acfg
->mempool
, sizeof (BinReloc
));
408 reloc
->val1
= mono_mempool_strdup (acfg
->mempool
, end
);
409 if (strcmp (start
, ".") == 0) {
410 reloc
->val2_section
= acfg
->cur_section
;
411 reloc
->val2_offset
= acfg
->cur_section
->cur_offset
;
413 reloc
->val2
= mono_mempool_strdup (acfg
->mempool
, start
);
415 reloc
->offset
= offset
;
416 reloc
->section
= acfg
->cur_section
;
417 reloc
->section_offset
= acfg
->cur_section
->cur_offset
;
418 reloc
->next
= acfg
->relocations
;
419 acfg
->relocations
= reloc
;
424 bin_writer_emit_symbol_diff (MonoImageWriter
*acfg
, const char *end
, const char* start
, int offset
)
426 create_reloc (acfg
, end
, start
, offset
);
427 acfg
->cur_section
->cur_offset
+= 4;
428 /*if (strcmp (reloc->section->name, ".data") == 0) {
430 g_print ("reloc: %s - %s + %d at %d\n", end, start, offset, acfg->cur_section->cur_offset - 4);
435 * Emit a relocation entry of type RELOC_TYPE against symbol SYMBOL at the current PC.
438 static G_GNUC_UNUSED
void
439 bin_writer_emit_reloc (MonoImageWriter
*acfg
, int reloc_type
, const char *symbol
, int addend
)
441 BinReloc
*reloc
= create_reloc (acfg
, symbol
, ".", addend
);
442 reloc
->reloc_type
= reloc_type
;
446 bin_writer_emit_zero_bytes (MonoImageWriter
*acfg
, int num
)
448 bin_writer_emit_ensure_buffer (acfg
->cur_section
, num
);
449 acfg
->cur_section
->cur_offset
+= num
;
453 bin_writer_fwrite (MonoImageWriter
*acfg
, void *val
, size_t size
, size_t nmemb
)
456 fwrite (val
, size
, nmemb
, acfg
->fp
);
458 g_assert (acfg
->out_buf_pos
+ (size
* nmemb
) <= acfg
->out_buf_size
);
459 memcpy (acfg
->out_buf
+ acfg
->out_buf_pos
, val
, size
* nmemb
);
460 acfg
->out_buf_pos
+= (size
* nmemb
);
465 bin_writer_fseek (MonoImageWriter
*acfg
, int offset
)
468 fseek (acfg
->fp
, offset
, SEEK_SET
);
470 acfg
->out_buf_pos
= offset
;
473 #ifdef USE_MACH_WRITER
476 * This is a minimal implementation designed to support xdebug on 32 bit osx
477 * FIXME: 64 bit support
480 #include <mach-o/loader.h>
483 get_label_addr (MonoImageWriter
*acfg
, const char *name
)
490 lab
= g_hash_table_lookup (acfg
->labels
, name
);
492 g_error ("Undefined label: '%s'.\n", name
);
493 section
= lab
->section
;
494 offset
= lab
->offset
;
495 if (section
->parent
) {
496 value
= section
->parent
->virt_offset
+ section
->cur_offset
+ offset
;
498 value
= section
->virt_offset
+ offset
;
505 resolve_reloc (MonoImageWriter
*acfg
, BinReloc
*reloc
, guint8
**out_data
, gsize
*out_vaddr
, gsize
*out_start_val
, gsize
*out_end_val
)
508 gssize end_val
, start_val
;
511 end_val
= get_label_addr (acfg
, reloc
->val1
);
513 start_val
= get_label_addr (acfg
, reloc
->val2
);
514 } else if (reloc
->val2_section
) {
515 start_val
= reloc
->val2_offset
;
516 if (reloc
->val2_section
->parent
)
517 start_val
+= reloc
->val2_section
->parent
->virt_offset
+ reloc
->val2_section
->cur_offset
;
519 start_val
+= reloc
->val2_section
->virt_offset
;
523 end_val
= end_val
- start_val
+ reloc
->offset
;
524 if (reloc
->section
->parent
) {
525 data
= reloc
->section
->parent
->data
;
526 data
+= reloc
->section
->cur_offset
;
527 data
+= reloc
->section_offset
;
528 vaddr
= reloc
->section
->parent
->virt_offset
;
529 vaddr
+= reloc
->section
->cur_offset
;
530 vaddr
+= reloc
->section_offset
;
532 data
= reloc
->section
->data
;
533 data
+= reloc
->section_offset
;
534 vaddr
= reloc
->section
->virt_offset
;
535 vaddr
+= reloc
->section_offset
;
538 *out_start_val
= start_val
;
539 *out_end_val
= end_val
;
545 resolve_relocations (MonoImageWriter
*acfg
)
549 gsize end_val
, start_val
;
552 /* Only resolve static relocations */
553 for (reloc
= acfg
->relocations
; reloc
; reloc
= reloc
->next
) {
554 resolve_reloc (acfg
, reloc
, &data
, &vaddr
, &start_val
, &end_val
);
556 data
[1] = end_val
>> 8;
557 data
[2] = end_val
>> 16;
558 data
[3] = end_val
>> 24;
563 bin_writer_emit_writeout (MonoImageWriter
*acfg
)
566 int sindex
, file_size
, nsections
, file_offset
, vmaddr
;
567 struct mach_header header
;
568 struct segment_command segment
;
569 struct section
*sections
;
571 /* Assing vm addresses to sections */
574 for (s
= acfg
->sections
; s
; s
= s
->next
) {
575 s
->virt_offset
= vmaddr
;
576 vmaddr
+= s
->cur_offset
;
580 resolve_relocations (acfg
);
584 memset (&header
, 0, sizeof (header
));
585 header
.magic
= MH_MAGIC
;
586 header
.cputype
= CPU_TYPE_X86
;
587 header
.cpusubtype
= CPU_SUBTYPE_X86_ALL
;
588 header
.filetype
= MH_OBJECT
;
590 header
.sizeofcmds
= 0;
593 file_offset
+= sizeof (header
);
595 memset (&segment
, 0, sizeof (segment
));
596 segment
.cmd
= LC_SEGMENT
;
597 segment
.cmdsize
= sizeof (segment
);
598 segment
.maxprot
= VM_PROT_READ
|VM_PROT_WRITE
|VM_PROT_EXECUTE
;
599 segment
.initprot
= VM_PROT_READ
|VM_PROT_WRITE
|VM_PROT_EXECUTE
;
601 file_offset
+= sizeof (segment
);
602 file_offset
+= nsections
* sizeof (struct section
);
604 sections
= g_new0 (struct section
, nsections
);
606 for (s
= acfg
->sections
; s
; s
= s
->next
) {
607 s
->file_offset
= file_offset
;
609 /* .debug_line -> __debug_line */
610 sprintf (sections
[sindex
].sectname
, "__%s", s
->name
+ 1);
611 sprintf (sections
[sindex
].segname
, "%s", "__DWARF");
612 sections
[sindex
].addr
= s
->virt_offset
;
613 sections
[sindex
].size
= s
->cur_offset
;
614 sections
[sindex
].offset
= s
->file_offset
;
616 file_offset
+= s
->cur_offset
;
619 segment
.cmdsize
+= sizeof (struct section
);
625 header
.sizeofcmds
+= segment
.cmdsize
;
628 file_size
= file_offset
;
631 acfg
->out_buf_size
= file_size
;
632 acfg
->out_buf
= g_malloc (acfg
->out_buf_size
);
635 bin_writer_fwrite (acfg
, &header
, sizeof (header
), 1);
636 bin_writer_fwrite (acfg
, &segment
, sizeof (segment
), 1);
637 bin_writer_fwrite (acfg
, sections
, sizeof (struct section
), nsections
);
638 for (s
= acfg
->sections
; s
; s
= s
->next
) {
640 g_assert (acfg
->out_buf_pos
== s
->file_offset
);
641 bin_writer_fwrite (acfg
, s
->data
, s
->cur_offset
, 1);
652 #ifdef USE_ELF_WRITER
678 #if TARGET_SIZEOF_VOID_P == 4
680 typedef Elf32_Ehdr ElfHeader
;
681 typedef Elf32_Shdr ElfSectHeader
;
682 typedef Elf32_Phdr ElfProgHeader
;
683 typedef Elf32_Sym ElfSymbol
;
684 typedef Elf32_Rel ElfReloc
;
685 typedef Elf32_Rela ElfRelocA
;
686 typedef Elf32_Dyn ElfDynamic
;
690 typedef Elf64_Ehdr ElfHeader
;
691 typedef Elf64_Shdr ElfSectHeader
;
692 typedef Elf64_Phdr ElfProgHeader
;
693 typedef Elf64_Sym ElfSymbol
;
694 typedef Elf64_Rel ElfReloc
;
695 typedef Elf64_Rela ElfRelocA
;
696 typedef Elf64_Dyn ElfDynamic
;
708 static SectInfo section_info
[] = {
710 {".hash", SHT_HASH
, 4, 2, TARGET_SIZEOF_VOID_P
},
711 {".dynsym", SHT_DYNSYM
, sizeof (ElfSymbol
), 2, TARGET_SIZEOF_VOID_P
},
712 {".dynstr", SHT_STRTAB
, 0, 2, 1},
713 {".rel.dyn", SHT_REL
, sizeof (ElfReloc
), 2, TARGET_SIZEOF_VOID_P
},
714 {".rela.dyn", SHT_RELA
, sizeof (ElfRelocA
), 2, TARGET_SIZEOF_VOID_P
},
715 {".text", SHT_PROGBITS
, 0, 6, 4096},
716 {".rodata", SHT_PROGBITS
, 0, SHF_ALLOC
, 4096},
717 {".dynamic", SHT_DYNAMIC
, sizeof (ElfDynamic
), 3, TARGET_SIZEOF_VOID_P
},
718 {".got.plt", SHT_PROGBITS
, TARGET_SIZEOF_VOID_P
, 3, TARGET_SIZEOF_VOID_P
},
719 {".data", SHT_PROGBITS
, 0, 3, 8},
720 {".bss", SHT_NOBITS
, 0, 3, 8},
721 {".debug_frame", SHT_PROGBITS
, 0, 0, 8},
722 {".debug_info", SHT_PROGBITS
, 0, 0, 1},
723 {".debug_abbrev", SHT_PROGBITS
, 0, 0, 1},
724 {".debug_line", SHT_PROGBITS
, 0, 0, 1},
725 {".debug_loc", SHT_PROGBITS
, 0, 0, 1},
726 {".shstrtab", SHT_STRTAB
, 0, 0, 1},
727 {".symtab", SHT_SYMTAB
, sizeof (ElfSymbol
), 0, TARGET_SIZEOF_VOID_P
},
728 {".strtab", SHT_STRTAB
, 0, 0, 1}
737 str_table_add (ElfStrTable
*table
, const char* value
)
741 table
->data
= g_string_new_len ("", 1);
742 table
->hash
= g_hash_table_new (g_str_hash
, g_str_equal
);
744 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (table
->hash
, value
));
747 idx
= table
->data
->len
;
748 g_string_append (table
->data
, value
);
749 g_string_append_c (table
->data
, 0);
750 g_hash_table_insert (table
->hash
, (void*)value
, GUINT_TO_POINTER (idx
));
755 append_subsection (MonoImageWriter
*acfg
, ElfSectHeader
*sheaders
, BinSection
*sect
, BinSection
*add
)
757 int offset
= sect
->cur_offset
;
758 /*offset += (sheaders [sect->shidx].sh_addralign - 1);
759 offset &= ~(sheaders [sect->shidx].sh_addralign - 1);*/
761 * FIXME: we shouldn't align subsections at all, but if we don't then the
762 * stuff inside the subsections which is aligned won't get aligned.
764 if (strcmp (sect
->name
, ".debug_line") != 0) {
768 bin_writer_emit_ensure_buffer (sect
, offset
);
769 //g_print ("section %s aligned to %d from %d\n", sect->name, offset, sect->cur_offset);
770 sect
->cur_offset
= offset
;
772 bin_writer_emit_ensure_buffer (sect
, add
->cur_offset
);
773 memcpy (sect
->data
+ sect
->cur_offset
, add
->data
, add
->cur_offset
);
775 sect
->cur_offset
+= add
->cur_offset
;
776 add
->cur_offset
= offset
; /* it becomes the offset in the parent section */
777 //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);
782 /* merge the subsections */
784 collect_sections (MonoImageWriter
*acfg
, ElfSectHeader
*sheaders
, BinSection
**out
, int num
)
786 int i
, j
, maxs
, num_sections
;
791 for (sect
= acfg
->sections
; sect
; sect
= sect
->next
) {
792 if (sect
->subsection
== 0) {
793 out
[num_sections
++] = sect
;
794 g_assert (num_sections
< num
);
796 maxs
= MAX (maxs
, sect
->subsection
);
798 for (i
= 0; i
< num_sections
; i
++) {
799 for (j
= 1; j
<= maxs
; ++j
) {
800 for (sect
= acfg
->sections
; sect
; sect
= sect
->next
) {
801 if (sect
->subsection
== j
&& strcmp (out
[i
]->name
, sect
->name
) == 0) {
802 append_subsection (acfg
, sheaders
, out
[i
], sect
);
811 elf_hash (const unsigned char *name
)
813 unsigned long h
= 0, g
;
815 h
= (h
<< 4) + *name
++;
816 if ((g
= h
& 0xf0000000))
823 #define NUM_BUCKETS 17
826 build_hash (MonoImageWriter
*acfg
, int num_sections
, ElfStrTable
*dynstr
)
829 int num_symbols
= 1 + num_sections
+ 3;
832 for (symbol
= acfg
->symbols
; symbol
; symbol
= symbol
->next
) {
833 if (!symbol
->is_global
)
836 str_table_add (dynstr
, symbol
->name
);
837 /*g_print ("adding sym: %s\n", symbol->name);*/
839 str_table_add (dynstr
, "__bss_start");
840 str_table_add (dynstr
, "_edata");
841 str_table_add (dynstr
, "_end");
843 data
= g_new0 (int, num_symbols
+ 2 + NUM_BUCKETS
);
844 data
[0] = NUM_BUCKETS
;
845 data
[1] = num_symbols
;
851 get_label_addr (MonoImageWriter
*acfg
, const char *name
)
858 lab
= (BinLabel
*)g_hash_table_lookup (acfg
->labels
, name
);
860 g_error ("Undefined label: '%s'.\n", name
);
861 section
= lab
->section
;
862 offset
= lab
->offset
;
863 if (section
->parent
) {
864 value
= section
->parent
->virt_offset
+ section
->cur_offset
+ offset
;
866 value
= section
->virt_offset
+ offset
;
872 collect_syms (MonoImageWriter
*acfg
, int *hash
, ElfStrTable
*strtab
, ElfSectHeader
*sheaders
, int *num_syms
)
883 symbols
= g_new0 (ElfSymbol
, hash
[1]);
886 for (symbol
= acfg
->symbols
; symbol
; symbol
= symbol
->next
)
889 symbols
= g_new0 (ElfSymbol
, i
+ SECT_NUM
+ 10); /* FIXME */
892 /* the first symbol is undef, all zeroes */
896 for (j
= 1; j
< SECT_NUM
; ++j
) {
897 symbols
[i
].st_info
= ELF32_ST_INFO (STB_LOCAL
, STT_SECTION
);
898 symbols
[i
].st_shndx
= j
;
899 symbols
[i
].st_value
= sheaders
[j
].sh_addr
;
903 for (section
= acfg
->sections
; section
; section
= section
->next
) {
906 symbols
[i
].st_info
= ELF32_ST_INFO (STB_LOCAL
, STT_SECTION
);
907 if (strcmp (section
->name
, ".text") == 0) {
908 symbols
[i
].st_shndx
= SECT_TEXT
;
909 section
->shidx
= SECT_TEXT
;
910 section
->file_offset
= 4096;
911 symbols
[i
].st_value
= section
->virt_offset
;
912 } else if (strcmp (section
->name
, ".rodata") == 0) {
913 symbols
[i
].st_shndx
= SECT_RODATA
;
914 section
->shidx
= SECT_RODATA
;
915 section
->file_offset
= 4096;
916 symbols
[i
].st_value
= section
->virt_offset
;
917 } else if (strcmp (section
->name
, ".data") == 0) {
918 symbols
[i
].st_shndx
= SECT_DATA
;
919 section
->shidx
= SECT_DATA
;
920 section
->file_offset
= 4096 + 28; /* FIXME */
921 symbols
[i
].st_value
= section
->virt_offset
;
922 } else if (strcmp (section
->name
, ".bss") == 0) {
923 symbols
[i
].st_shndx
= SECT_BSS
;
924 section
->shidx
= SECT_BSS
;
925 section
->file_offset
= 4096 + 28 + 8; /* FIXME */
926 symbols
[i
].st_value
= section
->virt_offset
;
931 for (symbol
= acfg
->symbols
; symbol
; symbol
= symbol
->next
) {
934 if (!symbol
->is_global
&& hash
)
936 symbols
[i
].st_info
= ELF32_ST_INFO (symbol
->is_global
? STB_GLOBAL
: STB_LOCAL
, symbol
->is_function
? STT_FUNC
: STT_OBJECT
);
937 symbols
[i
].st_name
= str_table_add (strtab
, symbol
->name
);
938 /*g_print ("sym name %s tabled to %d\n", symbol->name, symbols [i].st_name);*/
939 section
= symbol
->section
;
940 symbols
[i
].st_shndx
= section
->parent
? section
->parent
->shidx
: section
->shidx
;
941 lab
= (BinLabel
*)g_hash_table_lookup (acfg
->labels
, symbol
->name
);
942 offset
= lab
->offset
;
943 if (section
->parent
) {
944 symbols
[i
].st_value
= section
->parent
->virt_offset
+ section
->cur_offset
+ offset
;
946 symbols
[i
].st_value
= section
->virt_offset
+ offset
;
949 if (symbol
->end_label
) {
950 BinLabel
*elab
= (BinLabel
*)g_hash_table_lookup (acfg
->labels
, symbol
->end_label
);
952 symbols
[i
].st_size
= elab
->offset
- lab
->offset
;
956 /* add special symbols */
957 symbols
[i
].st_name
= str_table_add (strtab
, "__bss_start");
958 symbols
[i
].st_shndx
= 0xfff1;
959 symbols
[i
].st_info
= ELF32_ST_INFO (STB_GLOBAL
, 0);
961 symbols
[i
].st_name
= str_table_add (strtab
, "_edata");
962 symbols
[i
].st_shndx
= 0xfff1;
963 symbols
[i
].st_info
= ELF32_ST_INFO (STB_GLOBAL
, 0);
965 symbols
[i
].st_name
= str_table_add (strtab
, "_end");
966 symbols
[i
].st_shndx
= 0xfff1;
967 symbols
[i
].st_info
= ELF32_ST_INFO (STB_GLOBAL
, 0);
973 /* add to hash table */
976 chain
= hash
+ 2 + hash
[0];
977 for (i
= 0; i
< hash
[1]; ++i
) {
979 /*g_print ("checking %d '%s' (sym %d)\n", symbols [i].st_name, strtab->data->str + symbols [i].st_name, i);*/
980 if (!symbols
[i
].st_name
)
982 hashc
= elf_hash ((guint8
*)strtab
->data
->str
+ symbols
[i
].st_name
);
983 slot
= hashc
% hash
[0];
984 /*g_print ("hashing '%s' at slot %d (sym %d)\n", strtab->data->str + symbols [i].st_name, slot, i);*/
986 chain
[i
] = bucket
[slot
];
997 reloc_symbols (MonoImageWriter
*acfg
, ElfSymbol
*symbols
, ElfSectHeader
*sheaders
, ElfStrTable
*strtab
, gboolean dynamic
)
1005 for (section
= acfg
->sections
; section
; section
= section
->next
) {
1006 if (section
->parent
)
1008 symbols
[i
].st_value
= sheaders
[section
->shidx
].sh_addr
;
1012 for (i
= 1; i
< SECT_NUM
; ++i
) {
1013 symbols
[i
].st_value
= sheaders
[i
].sh_addr
;
1016 for (symbol
= acfg
->symbols
; symbol
; symbol
= symbol
->next
) {
1019 if (dynamic
&& !symbol
->is_global
)
1021 section
= symbol
->section
;
1022 lab
= (BinLabel
*)g_hash_table_lookup (acfg
->labels
, symbol
->name
);
1023 offset
= lab
->offset
;
1024 if (section
->parent
) {
1025 symbols
[i
].st_value
= sheaders
[section
->parent
->shidx
].sh_addr
+ section
->cur_offset
+ offset
;
1027 symbols
[i
].st_value
= sheaders
[section
->shidx
].sh_addr
+ offset
;
1032 symbols
[i
].st_value
= sheaders
[SECT_BSS
].sh_addr
;
1035 symbols
[i
].st_value
= sheaders
[SECT_DATA
].sh_addr
+ sheaders
[SECT_DATA
].sh_size
;
1038 symbols
[i
].st_value
= sheaders
[SECT_BSS
].sh_addr
+ sheaders
[SECT_BSS
].sh_size
;
1043 resolve_reloc (MonoImageWriter
*acfg
, BinReloc
*reloc
, guint8
**out_data
, gsize
*out_vaddr
, gsize
*out_start_val
, gsize
*out_end_val
)
1046 gssize end_val
, start_val
;
1049 end_val
= get_label_addr (acfg
, reloc
->val1
);
1051 start_val
= get_label_addr (acfg
, reloc
->val2
);
1052 } else if (reloc
->val2_section
) {
1053 start_val
= reloc
->val2_offset
;
1054 if (reloc
->val2_section
->parent
)
1055 start_val
+= reloc
->val2_section
->parent
->virt_offset
+ reloc
->val2_section
->cur_offset
;
1057 start_val
+= reloc
->val2_section
->virt_offset
;
1061 end_val
= end_val
- start_val
+ reloc
->offset
;
1062 if (reloc
->section
->parent
) {
1063 data
= reloc
->section
->parent
->data
;
1064 data
+= reloc
->section
->cur_offset
;
1065 data
+= reloc
->section_offset
;
1066 vaddr
= reloc
->section
->parent
->virt_offset
;
1067 vaddr
+= reloc
->section
->cur_offset
;
1068 vaddr
+= reloc
->section_offset
;
1070 data
= reloc
->section
->data
;
1071 data
+= reloc
->section_offset
;
1072 vaddr
= reloc
->section
->virt_offset
;
1073 vaddr
+= reloc
->section_offset
;
1076 *out_start_val
= start_val
;
1077 *out_end_val
= end_val
;
1085 resolve_relocations (MonoImageWriter
*acfg
)
1089 gsize end_val
, start_val
;
1094 rr
= g_new0 (ElfRelocA
, acfg
->num_relocs
);
1097 for (reloc
= acfg
->relocations
; reloc
; reloc
= reloc
->next
) {
1098 resolve_reloc (acfg
, reloc
, &data
, &vaddr
, &start_val
, &end_val
);
1099 /* FIXME: little endian */
1101 data
[1] = end_val
>> 8;
1102 data
[2] = end_val
>> 16;
1103 data
[3] = end_val
>> 24;
1105 if (start_val
== 0 && reloc
->val1
[0] != '.') {
1106 rr
[i
].r_offset
= vaddr
;
1107 rr
[i
].r_info
= R_X86_64_RELATIVE
;
1108 rr
[i
].r_addend
= end_val
;
1110 g_assert (i
<= acfg
->num_relocs
);
1116 #else /* USE_ELF_RELA */
1119 do_reloc (MonoImageWriter
*acfg
, BinReloc
*reloc
, guint8
*data
, gssize addr
)
1123 * We use the official ARM relocation types, but implement only the stuff actually
1124 * needed by the code we generate.
1126 switch (reloc
->reloc_type
) {
1128 case R_ARM_JUMP24
: {
1129 guint32
*code
= (guint32
*)(gpointer
)data
;
1130 guint32 ins
= *code
;
1133 if (reloc
->reloc_type
== R_ARM_CALL
)
1135 g_assert (data
[3] == 0xeb);
1138 g_assert (data
[3] == 0xea);
1139 if (diff
>= 0 && diff
<= 33554431) {
1141 ins
= (ins
& 0xff000000) | diff
;
1143 } else if (diff
<= 0 && diff
>= -33554432) {
1145 ins
= (ins
& 0xff000000) | (diff
& ~0xff000000);
1148 g_assert_not_reached ();
1152 case R_ARM_ALU_PC_G0_NC
: {
1153 /* Generated by emit_plt () */
1154 guint8
*code
= data
;
1157 g_assert (val
<= 0xffffff);
1159 ARM_ADD_REG_IMM (code
, ARMREG_IP
, ARMREG_PC
, (val
& 0xFF0000) >> 16, 16);
1161 ARM_ADD_REG_IMM (code
, ARMREG_IP
, ARMREG_PC
, 0, 0);
1162 ARM_ADD_REG_IMM (code
, ARMREG_IP
, ARMREG_IP
, (val
& 0xFF00) >> 8, 24);
1163 ARM_LDR_IMM (code
, ARMREG_PC
, ARMREG_IP
, val
& 0xFF);
1167 g_assert_not_reached ();
1170 g_assert_not_reached ();
1175 resolve_relocations (MonoImageWriter
*acfg
)
1179 gsize end_val
, start_val
;
1184 rr
= g_new0 (ElfReloc
, acfg
->num_relocs
);
1187 for (reloc
= acfg
->relocations
; reloc
; reloc
= reloc
->next
) {
1188 resolve_reloc (acfg
, reloc
, &data
, &vaddr
, &start_val
, &end_val
);
1189 /* FIXME: little endian */
1190 if (reloc
->reloc_type
) {
1191 /* Must be static */
1192 g_assert (start_val
> 0);
1193 do_reloc (acfg
, reloc
, data
, end_val
);
1196 data
[1] = end_val
>> 8;
1197 data
[2] = end_val
>> 16;
1198 data
[3] = end_val
>> 24;
1201 if (start_val
== 0 && reloc
->val1
[0] != '.') {
1202 rr
[i
].r_offset
= vaddr
;
1203 rr
[i
].r_info
= R_386_RELATIVE
;
1205 g_assert (i
<= acfg
->num_relocs
);
1211 #endif /* USE_ELF_RELA */
1213 static int normal_sections
[] = { SECT_DATA
, SECT_DEBUG_FRAME
, SECT_DEBUG_INFO
, SECT_DEBUG_ABBREV
, SECT_DEBUG_LINE
, SECT_DEBUG_LOC
};
1216 bin_writer_emit_writeout (MonoImageWriter
*acfg
)
1219 ElfProgHeader progh
[4];
1220 ElfSectHeader secth
[SECT_NUM
];
1226 ElfStrTable str_table
= {NULL
, NULL
};
1227 ElfStrTable sh_str_table
= {NULL
, NULL
};
1228 ElfStrTable dyn_str_table
= {NULL
, NULL
};
1229 BinSection
* all_sections
[32];
1230 BinSection
* sections
[SECT_NUM
];
1233 ElfDynamic dynamic
[14];
1235 int i
, num_sections
, file_offset
, virt_offset
, size
;
1238 /* Section headers */
1239 memset (§h
, 0, sizeof (secth
));
1240 memset (&dynamic
, 0, sizeof (dynamic
));
1241 memset (&header
, 0, sizeof (header
));
1243 for (i
= 1; i
< SECT_NUM
; ++i
) {
1244 secth
[i
].sh_name
= str_table_add (&sh_str_table
, section_info
[i
].name
);
1245 secth
[i
].sh_type
= section_info
[i
].type
;
1246 secth
[i
].sh_addralign
= section_info
[i
].align
;
1247 secth
[i
].sh_flags
= section_info
[i
].flags
;
1248 secth
[i
].sh_entsize
= section_info
[i
].esize
;
1250 secth
[SECT_DYNSYM
].sh_info
= TARGET_SIZEOF_VOID_P
== 4 ? 4 : 2;
1251 secth
[SECT_SYMTAB
].sh_info
= TARGET_SIZEOF_VOID_P
== 4 ? 20 : 17;
1252 secth
[SECT_HASH
].sh_link
= SECT_DYNSYM
;
1253 secth
[SECT_DYNSYM
].sh_link
= SECT_DYNSTR
;
1254 secth
[SECT_REL_DYN
].sh_link
= SECT_DYNSYM
;
1255 secth
[SECT_RELA_DYN
].sh_link
= SECT_DYNSYM
;
1256 secth
[SECT_DYNAMIC
].sh_link
= SECT_DYNSTR
;
1257 secth
[SECT_SYMTAB
].sh_link
= SECT_STRTAB
;
1259 num_sections
= collect_sections (acfg
, secth
, all_sections
, 16);
1260 hash
= build_hash (acfg
, num_sections
, &dyn_str_table
);
1262 g_print ("num_sections: %d\n", num_sections
);
1263 g_print ("dynsym: %d, dynstr size: %d\n", hash
[1], (int)dyn_str_table
.data
->len
);
1264 for (i
= 0; i
< num_sections
; ++i
) {
1265 g_print ("section %s, size: %d, %x\n", all_sections
[i
]->name
, all_sections
[i
]->cur_offset
, all_sections
[i
]->cur_offset
);
1268 /* Associate the bin sections with the ELF sections */
1269 memset (sections
, 0, sizeof (sections
));
1270 for (i
= 0; i
< num_sections
; ++i
) {
1271 BinSection
*sect
= all_sections
[i
];
1274 for (j
= 0; j
< SECT_NUM
; ++j
) {
1275 if (strcmp (sect
->name
, section_info
[j
].name
) == 0) {
1281 sections
[all_sections
[i
]->shidx
] = sect
;
1284 /* at this point we know where in the file the first segment sections go */
1285 dynsym
= collect_syms (acfg
, hash
, &dyn_str_table
, NULL
, NULL
);
1286 num_local_syms
= hash
[1];
1287 symtab
= collect_syms (acfg
, NULL
, &str_table
, secth
, &num_local_syms
);
1289 file_offset
= virt_offset
= sizeof (header
) + sizeof (progh
);
1290 secth
[SECT_HASH
].sh_addr
= secth
[SECT_HASH
].sh_offset
= file_offset
;
1291 size
= sizeof (int) * (2 + hash
[0] + hash
[1]);
1292 virt_offset
= (file_offset
+= size
);
1293 secth
[SECT_HASH
].sh_size
= size
;
1294 secth
[SECT_DYNSYM
].sh_addr
= secth
[SECT_DYNSYM
].sh_offset
= file_offset
;
1295 size
= sizeof (ElfSymbol
) * hash
[1];
1296 virt_offset
= (file_offset
+= size
);
1297 secth
[SECT_DYNSYM
].sh_size
= size
;
1298 secth
[SECT_DYNSTR
].sh_addr
= secth
[SECT_DYNSTR
].sh_offset
= file_offset
;
1299 size
= dyn_str_table
.data
->len
;
1300 virt_offset
= (file_offset
+= size
);
1301 secth
[SECT_DYNSTR
].sh_size
= size
;
1303 file_offset
&= ~(4-1);
1304 secth
[SECT_REL_DYN
].sh_addr
= secth
[SECT_REL_DYN
].sh_offset
= file_offset
;
1305 #ifndef USE_ELF_RELA
1306 size
= sizeof (ElfReloc
) * acfg
->num_relocs
;
1310 virt_offset
= (file_offset
+= size
);
1311 secth
[SECT_REL_DYN
].sh_size
= size
;
1312 secth
[SECT_RELA_DYN
].sh_addr
= secth
[SECT_RELA_DYN
].sh_offset
= file_offset
;
1314 size
= sizeof (ElfRelocA
) * acfg
->num_relocs
;
1318 virt_offset
= (file_offset
+= size
);
1319 secth
[SECT_RELA_DYN
].sh_size
= size
;
1321 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_TEXT
].sh_addralign
);
1322 virt_offset
= file_offset
;
1323 secth
[SECT_TEXT
].sh_addr
= secth
[SECT_TEXT
].sh_offset
= file_offset
;
1324 if (sections
[SECT_TEXT
]) {
1325 if (sections
[SECT_TEXT
]->has_addr
) {
1326 secth
[SECT_TEXT
].sh_addr
= sections
[SECT_TEXT
]->addr
;
1327 secth
[SECT_TEXT
].sh_flags
&= ~SHF_ALLOC
;
1329 size
= sections
[SECT_TEXT
]->cur_offset
;
1330 secth
[SECT_TEXT
].sh_size
= size
;
1331 file_offset
+= size
;
1334 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_RODATA
].sh_addralign
);
1335 virt_offset
= file_offset
;
1336 secth
[SECT_RODATA
].sh_addr
= virt_offset
;
1337 secth
[SECT_RODATA
].sh_offset
= file_offset
;
1338 if (sections
[SECT_RODATA
]) {
1339 size
= sections
[SECT_RODATA
]->cur_offset
;
1340 secth
[SECT_RODATA
].sh_size
= size
;
1341 file_offset
+= size
;
1342 virt_offset
+= size
;
1345 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_DYNAMIC
].sh_addralign
);
1346 virt_offset
= file_offset
;
1348 /* .dynamic, .got.plt, .data, .bss here */
1349 /* Have to increase the virt offset since these go to a separate segment */
1350 virt_offset
+= PAGESIZE
;
1351 secth
[SECT_DYNAMIC
].sh_addr
= virt_offset
;
1352 secth
[SECT_DYNAMIC
].sh_offset
= file_offset
;
1353 size
= sizeof (dynamic
);
1354 secth
[SECT_DYNAMIC
].sh_size
= size
;
1355 file_offset
+= size
;
1356 virt_offset
+= size
;
1358 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_GOT_PLT
].sh_addralign
);
1359 virt_offset
= ALIGN_TO (virt_offset
, secth
[SECT_GOT_PLT
].sh_addralign
);
1360 secth
[SECT_GOT_PLT
].sh_addr
= virt_offset
;
1361 secth
[SECT_GOT_PLT
].sh_offset
= file_offset
;
1362 size
= 3 * TARGET_SIZEOF_VOID_P
;
1363 secth
[SECT_GOT_PLT
].sh_size
= size
;
1364 file_offset
+= size
;
1365 virt_offset
+= size
;
1367 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_DATA
].sh_addralign
);
1368 virt_offset
= ALIGN_TO (virt_offset
, secth
[SECT_DATA
].sh_addralign
);
1369 secth
[SECT_DATA
].sh_addr
= virt_offset
;
1370 secth
[SECT_DATA
].sh_offset
= file_offset
;
1371 if (sections
[SECT_DATA
]) {
1372 size
= sections
[SECT_DATA
]->cur_offset
;
1373 secth
[SECT_DATA
].sh_size
= size
;
1374 file_offset
+= size
;
1375 virt_offset
+= size
;
1378 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_BSS
].sh_addralign
);
1379 virt_offset
= ALIGN_TO (virt_offset
, secth
[SECT_BSS
].sh_addralign
);
1380 secth
[SECT_BSS
].sh_addr
= virt_offset
;
1381 secth
[SECT_BSS
].sh_offset
= file_offset
;
1382 if (sections
[SECT_BSS
]) {
1383 size
= sections
[SECT_BSS
]->cur_offset
;
1384 secth
[SECT_BSS
].sh_size
= size
;
1387 /* virtual doesn't matter anymore */
1388 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_DEBUG_FRAME
].sh_addralign
);
1389 secth
[SECT_DEBUG_FRAME
].sh_offset
= file_offset
;
1390 if (sections
[SECT_DEBUG_FRAME
])
1391 size
= sections
[SECT_DEBUG_FRAME
]->cur_offset
;
1394 secth
[SECT_DEBUG_FRAME
].sh_size
= size
;
1395 file_offset
+= size
;
1397 secth
[SECT_DEBUG_INFO
].sh_offset
= file_offset
;
1398 if (sections
[SECT_DEBUG_INFO
])
1399 size
= sections
[SECT_DEBUG_INFO
]->cur_offset
;
1402 secth
[SECT_DEBUG_INFO
].sh_size
= size
;
1403 file_offset
+= size
;
1405 secth
[SECT_DEBUG_ABBREV
].sh_offset
= file_offset
;
1406 if (sections
[SECT_DEBUG_ABBREV
])
1407 size
= sections
[SECT_DEBUG_ABBREV
]->cur_offset
;
1410 secth
[SECT_DEBUG_ABBREV
].sh_size
= size
;
1411 file_offset
+= size
;
1413 secth
[SECT_DEBUG_LINE
].sh_offset
= file_offset
;
1414 if (sections
[SECT_DEBUG_LINE
])
1415 size
= sections
[SECT_DEBUG_LINE
]->cur_offset
;
1418 secth
[SECT_DEBUG_LINE
].sh_size
= size
;
1419 file_offset
+= size
;
1421 secth
[SECT_DEBUG_LOC
].sh_offset
= file_offset
;
1422 if (sections
[SECT_DEBUG_LOC
])
1423 size
= sections
[SECT_DEBUG_LOC
]->cur_offset
;
1426 secth
[SECT_DEBUG_LOC
].sh_size
= size
;
1427 file_offset
+= size
;
1429 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_SHSTRTAB
].sh_addralign
);
1430 secth
[SECT_SHSTRTAB
].sh_offset
= file_offset
;
1431 size
= sh_str_table
.data
->len
;
1432 secth
[SECT_SHSTRTAB
].sh_size
= size
;
1433 file_offset
+= size
;
1435 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_SYMTAB
].sh_addralign
);
1436 secth
[SECT_SYMTAB
].sh_offset
= file_offset
;
1437 size
= sizeof (ElfSymbol
) * num_local_syms
;
1438 secth
[SECT_SYMTAB
].sh_size
= size
;
1439 file_offset
+= size
;
1441 file_offset
= ALIGN_TO (file_offset
, secth
[SECT_STRTAB
].sh_addralign
);
1442 secth
[SECT_STRTAB
].sh_offset
= file_offset
;
1443 size
= str_table
.data
->len
;
1444 secth
[SECT_STRTAB
].sh_size
= size
;
1445 file_offset
+= size
;
1447 for (i
= 1; i
< SECT_NUM
; ++i
) {
1448 if (section_info
[i
].esize
!= 0)
1449 g_assert (secth
[i
].sh_size
% section_info
[i
].esize
== 0);
1453 file_offset
&= ~(4-1);
1455 header
.e_ident
[EI_MAG0
] = ELFMAG0
;
1456 header
.e_ident
[EI_MAG1
] = ELFMAG1
;
1457 header
.e_ident
[EI_MAG2
] = ELFMAG2
;
1458 header
.e_ident
[EI_MAG3
] = ELFMAG3
;
1459 header
.e_ident
[EI_CLASS
] = TARGET_SIZEOF_VOID_P
== 4 ? ELFCLASS32
: ELFCLASS64
;
1460 header
.e_ident
[EI_DATA
] = ELFDATA2LSB
;
1461 header
.e_ident
[EI_VERSION
] = EV_CURRENT
;
1462 header
.e_ident
[EI_OSABI
] = ELFOSABI_NONE
;
1463 header
.e_ident
[EI_ABIVERSION
] = 0;
1464 for (i
= EI_PAD
; i
< EI_NIDENT
; ++i
)
1465 header
.e_ident
[i
] = 0;
1467 header
.e_type
= ET_DYN
;
1468 #if defined(TARGET_X86)
1469 header
.e_machine
= EM_386
;
1470 #elif defined(TARGET_AMD64)
1471 header
.e_machine
= EM_X86_64
;
1472 #elif defined(TARGET_ARM)
1473 header
.e_machine
= EM_ARM
;
1475 g_assert_not_reached ();
1477 header
.e_version
= 1;
1479 header
.e_phoff
= sizeof (header
);
1480 header
.e_ehsize
= sizeof (header
);
1481 header
.e_phentsize
= sizeof (ElfProgHeader
);
1483 header
.e_entry
= secth
[SECT_TEXT
].sh_addr
;
1484 header
.e_shstrndx
= SECT_SHSTRTAB
;
1485 header
.e_shentsize
= sizeof (ElfSectHeader
);
1486 header
.e_shnum
= SECT_NUM
;
1487 header
.e_shoff
= file_offset
;
1491 dynamic
[i
].d_tag
= DT_HASH
;
1492 dynamic
[i
].d_un
.d_val
= secth
[SECT_HASH
].sh_offset
;
1494 dynamic
[i
].d_tag
= DT_STRTAB
;
1495 dynamic
[i
].d_un
.d_val
= secth
[SECT_DYNSTR
].sh_offset
;
1497 dynamic
[i
].d_tag
= DT_SYMTAB
;
1498 dynamic
[i
].d_un
.d_val
= secth
[SECT_DYNSYM
].sh_offset
;
1500 dynamic
[i
].d_tag
= DT_STRSZ
;
1501 dynamic
[i
].d_un
.d_val
= dyn_str_table
.data
->len
;
1503 dynamic
[i
].d_tag
= DT_SYMENT
;
1504 dynamic
[i
].d_un
.d_val
= sizeof (ElfSymbol
);
1507 dynamic
[i
].d_tag
= DT_RELA
;
1508 dynamic
[i
].d_un
.d_val
= secth
[SECT_RELA_DYN
].sh_offset
;
1510 dynamic
[i
].d_tag
= DT_RELASZ
;
1511 dynamic
[i
].d_un
.d_val
= secth
[SECT_RELA_DYN
].sh_size
;
1513 dynamic
[i
].d_tag
= DT_RELAENT
;
1514 dynamic
[i
].d_un
.d_val
= sizeof (ElfRelocA
);
1517 dynamic
[i
].d_tag
= DT_REL
;
1518 dynamic
[i
].d_un
.d_val
= secth
[SECT_REL_DYN
].sh_offset
;
1520 dynamic
[i
].d_tag
= DT_RELSZ
;
1521 dynamic
[i
].d_un
.d_val
= secth
[SECT_REL_DYN
].sh_size
;
1523 dynamic
[i
].d_tag
= DT_RELENT
;
1524 dynamic
[i
].d_un
.d_val
= sizeof (ElfReloc
);
1527 dynamic
[i
].d_tag
= DT_RELCOUNT
;
1528 dynamic
[i
].d_un
.d_val
= acfg
->num_relocs
;
1531 /* Program header */
1532 memset (&progh
, 0, sizeof (progh
));
1533 progh
[0].p_type
= PT_LOAD
;
1534 progh
[0].p_filesz
= progh
[0].p_memsz
= secth
[SECT_DYNAMIC
].sh_offset
;
1535 progh
[0].p_align
= 4096;
1536 progh
[0].p_flags
= 5;
1538 progh
[1].p_type
= PT_LOAD
;
1539 progh
[1].p_offset
= secth
[SECT_DYNAMIC
].sh_offset
;
1540 progh
[1].p_vaddr
= progh
[1].p_paddr
= secth
[SECT_DYNAMIC
].sh_addr
;
1541 progh
[1].p_filesz
= secth
[SECT_BSS
].sh_offset
- secth
[SECT_DYNAMIC
].sh_offset
;
1542 progh
[1].p_memsz
= secth
[SECT_BSS
].sh_addr
+ secth
[SECT_BSS
].sh_size
- secth
[SECT_DYNAMIC
].sh_addr
;
1543 progh
[1].p_align
= 4096;
1544 progh
[1].p_flags
= 6;
1546 progh
[2].p_type
= PT_DYNAMIC
;
1547 progh
[2].p_offset
= secth
[SECT_DYNAMIC
].sh_offset
;
1548 progh
[2].p_vaddr
= progh
[2].p_paddr
= secth
[SECT_DYNAMIC
].sh_addr
;
1549 progh
[2].p_filesz
= progh
[2].p_memsz
= secth
[SECT_DYNAMIC
].sh_size
;
1550 progh
[2].p_align
= TARGET_SIZEOF_VOID_P
;
1551 progh
[2].p_flags
= 6;
1553 progh
[3].p_type
= PT_GNU_STACK
;
1554 progh
[3].p_offset
= secth
[SECT_DYNAMIC
].sh_offset
;
1555 progh
[3].p_vaddr
= progh
[3].p_paddr
= secth
[SECT_DYNAMIC
].sh_addr
;
1556 progh
[3].p_filesz
= progh
[3].p_memsz
= secth
[SECT_DYNAMIC
].sh_size
;
1557 progh
[3].p_align
= TARGET_SIZEOF_VOID_P
;
1558 progh
[3].p_flags
= 6;
1560 /* Compute the addresses of the bin sections, so relocation can be done */
1561 for (i
= 0; i
< SECT_NUM
; ++i
) {
1563 sections
[i
]->file_offset
= secth
[i
].sh_offset
;
1564 sections
[i
]->virt_offset
= secth
[i
].sh_addr
;
1568 reloc_symbols (acfg
, dynsym
, secth
, &dyn_str_table
, TRUE
);
1569 reloc_symbols (acfg
, symtab
, secth
, &str_table
, FALSE
);
1570 relocs
= resolve_relocations (acfg
);
1573 acfg
->out_buf_size
= file_offset
+ sizeof (secth
);
1574 acfg
->out_buf
= (guint8
*)g_malloc (acfg
->out_buf_size
);
1577 bin_writer_fwrite (acfg
, &header
, sizeof (header
), 1);
1578 bin_writer_fwrite (acfg
, &progh
, sizeof (progh
), 1);
1579 bin_writer_fwrite (acfg
, hash
, sizeof (int) * (hash
[0] + hash
[1] + 2), 1);
1580 bin_writer_fwrite (acfg
, dynsym
, sizeof (ElfSymbol
) * hash
[1], 1);
1581 bin_writer_fwrite (acfg
, dyn_str_table
.data
->str
, dyn_str_table
.data
->len
, 1);
1583 bin_writer_fseek (acfg
, secth
[SECT_REL_DYN
].sh_offset
);
1584 bin_writer_fwrite (acfg
, relocs
, sizeof (ElfReloc
), acfg
->num_relocs
);
1587 bin_writer_fseek (acfg
, secth
[SECT_RELA_DYN
].sh_offset
);
1588 bin_writer_fwrite (acfg
, relocs
, secth
[SECT_RELA_DYN
].sh_size
, 1);
1591 if (sections
[SECT_TEXT
]) {
1592 bin_writer_fseek (acfg
, secth
[SECT_TEXT
].sh_offset
);
1593 bin_writer_fwrite (acfg
, sections
[SECT_TEXT
]->data
, sections
[SECT_TEXT
]->cur_offset
, 1);
1596 if (sections
[SECT_RODATA
]) {
1597 bin_writer_fseek (acfg
, secth
[SECT_RODATA
].sh_offset
);
1598 bin_writer_fwrite (acfg
, sections
[SECT_RODATA
]->data
, sections
[SECT_RODATA
]->cur_offset
, 1);
1601 bin_writer_fseek (acfg
, secth
[SECT_DYNAMIC
].sh_offset
);
1602 bin_writer_fwrite (acfg
, dynamic
, sizeof (dynamic
), 1);
1605 size
= secth
[SECT_DYNAMIC
].sh_addr
;
1606 bin_writer_fseek (acfg
, secth
[SECT_GOT_PLT
].sh_offset
);
1607 bin_writer_fwrite (acfg
, &size
, sizeof (size
), 1);
1609 /* normal sections */
1610 for (i
= 0; i
< sizeof (normal_sections
) / sizeof (normal_sections
[0]); ++i
) {
1611 int sect
= normal_sections
[i
];
1613 if (sections
[sect
]) {
1614 bin_writer_fseek (acfg
, secth
[sect
].sh_offset
);
1615 bin_writer_fwrite (acfg
, sections
[sect
]->data
, sections
[sect
]->cur_offset
, 1);
1619 bin_writer_fseek (acfg
, secth
[SECT_SHSTRTAB
].sh_offset
);
1620 bin_writer_fwrite (acfg
, sh_str_table
.data
->str
, sh_str_table
.data
->len
, 1);
1621 bin_writer_fseek (acfg
, secth
[SECT_SYMTAB
].sh_offset
);
1622 bin_writer_fwrite (acfg
, symtab
, sizeof (ElfSymbol
) * num_local_syms
, 1);
1623 bin_writer_fseek (acfg
, secth
[SECT_STRTAB
].sh_offset
);
1624 bin_writer_fwrite (acfg
, str_table
.data
->str
, str_table
.data
->len
, 1);
1625 /*g_print ("file_offset %d vs %d\n", file_offset, ftell (file));*/
1626 /*g_assert (file_offset >= ftell (file));*/
1627 bin_writer_fseek (acfg
, file_offset
);
1628 bin_writer_fwrite (acfg
, §h
, sizeof (secth
), 1);
1636 #endif /* USE_ELF_WRITER */
1638 #endif /* USE_BIN_WRITER */
1643 asm_writer_emit_start (MonoImageWriter
*acfg
)
1645 #if defined(TARGET_ASM_APPLE)
1646 fprintf (acfg
->fp
, ".subsections_via_symbols\n");
1651 asm_writer_emit_writeout (MonoImageWriter
*acfg
)
1659 asm_writer_emit_unset_mode (MonoImageWriter
*acfg
)
1661 if (acfg
->mode
== EMIT_NONE
)
1663 fprintf (acfg
->fp
, "\n");
1664 acfg
->mode
= EMIT_NONE
;
1668 asm_writer_emit_section_change (MonoImageWriter
*acfg
, const char *section_name
, int subsection_index
)
1670 asm_writer_emit_unset_mode (acfg
);
1671 #if defined(TARGET_ASM_APPLE)
1672 if (strcmp(section_name
, ".bss") == 0)
1673 fprintf (acfg
->fp
, "%s\n", ".data");
1674 else if (strstr (section_name
, ".debug") == section_name
) {
1675 //g_assert (subsection_index == 0);
1676 fprintf (acfg
->fp
, ".section __DWARF, __%s,regular,debug\n", section_name
+ 1);
1678 fprintf (acfg
->fp
, "%s\n", section_name
);
1679 #elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_POWERPC)
1680 /* ARM gas doesn't seem to like subsections of .bss */
1681 if (!strcmp (section_name
, ".text") || !strcmp (section_name
, ".data")) {
1682 fprintf (acfg
->fp
, "%s %d\n", section_name
, subsection_index
);
1684 fprintf (acfg
->fp
, ".section \"%s\"\n", section_name
);
1685 fprintf (acfg
->fp
, ".subsection %d\n", subsection_index
);
1687 #elif defined(HOST_WIN32)
1688 fprintf (acfg
->fp
, ".section %s\n", section_name
);
1690 if (!strcmp (section_name
, ".text") || !strcmp (section_name
, ".data") || !strcmp (section_name
, ".bss")) {
1691 fprintf (acfg
->fp
, "%s %d\n", section_name
, subsection_index
);
1693 fprintf (acfg
->fp
, ".section \"%s\"\n", section_name
);
1694 fprintf (acfg
->fp
, ".subsection %d\n", subsection_index
);
1700 const char *get_label (const char *s
)
1702 #ifdef TARGET_ASM_APPLE
1703 if (s
[0] == '.' && s
[1] == 'L')
1704 /* apple uses "L" instead of ".L" to mark temporary labels */
1711 #define GLOBAL_SYMBOL_DEF_SCL 2
1712 #define LOCAL_SYMBOL_DEF_SCL 3
1715 asm_writer_in_data_section (MonoImageWriter
*acfg
)
1717 gboolean in_data_section
= FALSE
;
1718 const char *data_sections
[] = {".data", ".bss", ".rdata"};
1720 for (guchar i
= 0; i
< G_N_ELEMENTS (data_sections
); ++i
) {
1721 if (strcmp (acfg
->current_section
, data_sections
[i
]) == 0) {
1722 in_data_section
= TRUE
;
1727 return in_data_section
;
1731 asm_writer_emit_symbol_type (MonoImageWriter
*acfg
, const char *name
, gboolean func
, gboolean global
)
1733 asm_writer_emit_unset_mode (acfg
);
1736 fprintf (acfg
->fp
, "\t.def %s; .scl %d; .type 32; .endef\n", name
, (global
== TRUE
? GLOBAL_SYMBOL_DEF_SCL
: LOCAL_SYMBOL_DEF_SCL
));
1738 if (!asm_writer_in_data_section (acfg
))
1739 fprintf (acfg
->fp
, "\t.data\n");
1748 asm_writer_emit_symbol_type (MonoImageWriter
*acfg
, const char *name
, gboolean func
, gboolean global
)
1757 asm_writer_emit_unset_mode (acfg
);
1759 #if defined(TARGET_ASM_APPLE)
1761 #elif defined(TARGET_ARM)
1762 fprintf (acfg
->fp
, "\t.type %s,#%s\n", name
, stype
);
1764 fprintf (acfg
->fp
, "\t.type %s,@%s\n", name
, stype
);
1767 #endif /* TARGET_WIN32 */
1770 asm_writer_emit_global (MonoImageWriter
*acfg
, const char *name
, gboolean func
)
1772 asm_writer_emit_unset_mode (acfg
);
1774 fprintf (acfg
->fp
, "\t.globl %s\n", name
);
1776 asm_writer_emit_symbol_type (acfg
, name
, func
, TRUE
);
1780 asm_writer_emit_local_symbol (MonoImageWriter
*acfg
, const char *name
, const char *end_label
, gboolean func
)
1782 asm_writer_emit_unset_mode (acfg
);
1784 #if !defined(TARGET_ASM_APPLE) && !defined(TARGET_WIN32)
1785 fprintf (acfg
->fp
, "\t.local %s\n", name
);
1788 asm_writer_emit_symbol_type (acfg
, name
, func
, FALSE
);
1792 asm_writer_emit_symbol_size (MonoImageWriter
*acfg
, const char *name
, const char *end_label
)
1794 asm_writer_emit_unset_mode (acfg
);
1797 #if !defined(TARGET_ASM_APPLE) && !defined(TARGET_WIN32)
1798 fprintf (acfg
->fp
, "\t.size %s,%s-%s\n", name
, end_label
, name
);
1803 asm_writer_emit_label (MonoImageWriter
*acfg
, const char *name
)
1805 asm_writer_emit_unset_mode (acfg
);
1806 fprintf (acfg
->fp
, "%s:\n", get_label (name
));
1810 asm_writer_emit_string (MonoImageWriter
*acfg
, const char *value
)
1812 asm_writer_emit_unset_mode (acfg
);
1813 fprintf (acfg
->fp
, "\t%s \"%s\"\n", AS_STRING_DIRECTIVE
, value
);
1817 asm_writer_emit_line (MonoImageWriter
*acfg
)
1819 asm_writer_emit_unset_mode (acfg
);
1820 fprintf (acfg
->fp
, "\n");
1824 asm_writer_emit_alignment (MonoImageWriter
*acfg
, int size
)
1826 asm_writer_emit_unset_mode (acfg
);
1827 #if defined(TARGET_ARM)
1828 fprintf (acfg
->fp
, "\t.align %d\n", ilog2 (size
));
1829 #elif defined(__ppc__) && defined(TARGET_ASM_APPLE)
1830 // the mach-o assembler specifies alignments as powers of 2.
1831 fprintf (acfg
->fp
, "\t.align %d\t; ilog2\n", ilog2(size
));
1832 #elif defined(TARGET_ASM_GAS)
1833 fprintf (acfg
->fp
, "\t.balign %d\n", size
);
1834 #elif defined(TARGET_ASM_APPLE)
1835 fprintf (acfg
->fp
, "\t.align %d\n", ilog2 (size
));
1837 fprintf (acfg
->fp
, "\t.align %d\n", size
);
1841 #ifndef USE_BIN_WRITER
1843 asm_writer_emit_alignment_fill (MonoImageWriter
*acfg
, int size
, int fill
)
1845 asm_writer_emit_unset_mode (acfg
);
1846 #if defined(TARGET_ASM_APPLE)
1847 fprintf (acfg
->fp
, "\t.align %d, 0x%0x\n", ilog2 (size
), fill
);
1849 asm_writer_emit_alignment (acfg
, size
);
1855 asm_writer_emit_pointer_unaligned (MonoImageWriter
*acfg
, const char *target
)
1857 asm_writer_emit_unset_mode (acfg
);
1858 fprintf (acfg
->fp
, "\t%s %s\n", AS_POINTER_DIRECTIVE
, target
? target
: "0");
1862 asm_writer_emit_pointer (MonoImageWriter
*acfg
, const char *target
)
1864 asm_writer_emit_unset_mode (acfg
);
1865 asm_writer_emit_alignment (acfg
, sizeof (target_mgreg_t
));
1866 asm_writer_emit_pointer_unaligned (acfg
, target
);
1869 static char *byte_to_str
;
1872 asm_writer_emit_bytes (MonoImageWriter
*acfg
, const guint8
* buf
, int size
)
1875 if (acfg
->mode
!= EMIT_BYTE
) {
1876 acfg
->mode
= EMIT_BYTE
;
1877 acfg
->col_count
= 0;
1880 if (byte_to_str
== NULL
) {
1881 byte_to_str
= g_new0 (char, 256 * 8);
1882 for (i
= 0; i
< 256; ++i
) {
1883 sprintf (byte_to_str
+ (i
* 8), ",%d", i
);
1887 for (i
= 0; i
< size
; ++i
, ++acfg
->col_count
) {
1888 if ((acfg
->col_count
% 32) == 0)
1889 fprintf (acfg
->fp
, "\n\t.byte %d", buf
[i
]);
1891 fputs (byte_to_str
+ (buf
[i
] * 8), acfg
->fp
);
1896 asm_writer_emit_int16 (MonoImageWriter
*acfg
, int value
)
1898 if (acfg
->mode
!= EMIT_WORD
) {
1899 acfg
->mode
= EMIT_WORD
;
1900 acfg
->col_count
= 0;
1902 if ((acfg
->col_count
++ % 8) == 0)
1903 fprintf (acfg
->fp
, "\n\t%s ", AS_INT16_DIRECTIVE
);
1905 fprintf (acfg
->fp
, ", ");
1906 fprintf (acfg
->fp
, "%d", value
);
1910 asm_writer_emit_int32 (MonoImageWriter
*acfg
, int value
)
1912 if (acfg
->mode
!= EMIT_LONG
) {
1913 acfg
->mode
= EMIT_LONG
;
1914 acfg
->col_count
= 0;
1916 if ((acfg
->col_count
++ % 8) == 0)
1917 fprintf (acfg
->fp
, "\n\t%s ", AS_INT32_DIRECTIVE
);
1919 fprintf (acfg
->fp
, ",");
1920 fprintf (acfg
->fp
, "%d", value
);
1924 asm_writer_emit_symbol_diff (MonoImageWriter
*acfg
, const char *end
, const char* start
, int offset
)
1926 #ifdef TARGET_ASM_APPLE
1927 //char symbol [128];
1930 if (acfg
->mode
!= EMIT_LONG
) {
1931 acfg
->mode
= EMIT_LONG
;
1932 acfg
->col_count
= 0;
1935 // FIXME: This doesn't seem to work on the iphone
1937 //#ifdef TARGET_ASM_APPLE
1938 /* The apple assembler needs a separate symbol to be able to handle complex expressions */
1939 sprintf (symbol
, "LTMP_SYM%d", acfg
->label_gen
);
1940 start
= get_label (start
);
1941 end
= get_label (end
);
1944 fprintf (acfg
->fp
, "\n%s=%s - %s + %d", symbol
, end
, start
, offset
);
1945 else if (offset
< 0)
1946 fprintf (acfg
->fp
, "\n%s=%s - %s %d", symbol
, end
, start
, offset
);
1948 fprintf (acfg
->fp
, "\n%s=%s - %s", symbol
, end
, start
);
1950 fprintf (acfg
->fp
, "\n\t%s ", AS_INT32_DIRECTIVE
);
1951 fprintf (acfg
->fp
, "%s", symbol
);
1953 start
= get_label (start
);
1954 end
= get_label (end
);
1956 if (offset
== 0 && strcmp (start
, ".") != 0) {
1958 sprintf (symbol
, "%sDIFF_SYM%d", AS_TEMP_LABEL_PREFIX
, acfg
->label_gen
);
1960 fprintf (acfg
->fp
, "\n%s=%s - %s", symbol
, end
, start
);
1961 fprintf (acfg
->fp
, "\n\t%s ", AS_INT32_DIRECTIVE
);
1962 fprintf (acfg
->fp
, "%s", symbol
);
1966 if ((acfg
->col_count
++ % 8) == 0)
1967 fprintf (acfg
->fp
, "\n\t%s ", AS_INT32_DIRECTIVE
);
1969 fprintf (acfg
->fp
, ",");
1971 fprintf (acfg
->fp
, "%s - %s + %d", end
, start
, offset
);
1972 else if (offset
< 0)
1973 fprintf (acfg
->fp
, "%s - %s %d", end
, start
, offset
);
1975 fprintf (acfg
->fp
, "%s - %s", end
, start
);
1980 asm_writer_emit_zero_bytes (MonoImageWriter
*acfg
, int num
)
1982 asm_writer_emit_unset_mode (acfg
);
1983 fprintf (acfg
->fp
, "\t%s %d\n", AS_SKIP_DIRECTIVE
, num
);
1986 /* EMIT FUNCTIONS */
1989 mono_img_writer_emit_start (MonoImageWriter
*acfg
)
1991 #ifdef USE_BIN_WRITER
1992 if (acfg
->use_bin_writer
)
1993 bin_writer_emit_start (acfg
);
1995 asm_writer_emit_start (acfg
);
1997 asm_writer_emit_start (acfg
);
2002 mono_img_writer_emit_section_change (MonoImageWriter
*acfg
, const char *section_name
, int subsection_index
)
2004 #ifdef USE_BIN_WRITER
2005 if (acfg
->use_bin_writer
)
2006 bin_writer_emit_section_change (acfg
, section_name
, subsection_index
);
2008 asm_writer_emit_section_change (acfg
, section_name
, subsection_index
);
2010 asm_writer_emit_section_change (acfg
, section_name
, subsection_index
);
2013 acfg
->current_section
= section_name
;
2014 acfg
->current_subsection
= subsection_index
;
2018 mono_img_writer_emit_push_section (MonoImageWriter
*acfg
, const char *section_name
, int subsection
)
2020 g_assert (acfg
->stack_pos
< 16 - 1);
2021 acfg
->section_stack
[acfg
->stack_pos
] = acfg
->current_section
;
2022 acfg
->subsection_stack
[acfg
->stack_pos
] = acfg
->current_subsection
;
2025 mono_img_writer_emit_section_change (acfg
, section_name
, subsection
);
2029 mono_img_writer_emit_pop_section (MonoImageWriter
*acfg
)
2031 g_assert (acfg
->stack_pos
> 0);
2033 mono_img_writer_emit_section_change (acfg
, acfg
->section_stack
[acfg
->stack_pos
], acfg
->subsection_stack
[acfg
->stack_pos
]);
2037 mono_img_writer_set_section_addr (MonoImageWriter
*acfg
, guint64 addr
)
2039 #ifdef USE_BIN_WRITER
2040 if (!acfg
->use_bin_writer
)
2043 bin_writer_set_section_addr (acfg
, addr
);
2050 mono_img_writer_emit_global (MonoImageWriter
*acfg
, const char *name
, gboolean func
)
2052 #ifdef USE_BIN_WRITER
2053 if (acfg
->use_bin_writer
)
2054 bin_writer_emit_global (acfg
, name
, func
);
2056 asm_writer_emit_global (acfg
, name
, func
);
2058 asm_writer_emit_global (acfg
, name
, func
);
2063 mono_img_writer_emit_local_symbol (MonoImageWriter
*acfg
, const char *name
, const char *end_label
, gboolean func
)
2065 #ifdef USE_BIN_WRITER
2066 if (acfg
->use_bin_writer
)
2067 bin_writer_emit_local_symbol (acfg
, name
, end_label
, func
);
2069 asm_writer_emit_local_symbol (acfg
, name
, end_label
, func
);
2071 asm_writer_emit_local_symbol (acfg
, name
, end_label
, func
);
2076 mono_img_writer_emit_symbol_size (MonoImageWriter
*acfg
, const char *name
, const char *end_label
)
2078 if (!acfg
->use_bin_writer
)
2079 asm_writer_emit_symbol_size (acfg
, name
, end_label
);
2083 mono_img_writer_emit_label (MonoImageWriter
*acfg
, const char *name
)
2085 #ifdef USE_BIN_WRITER
2086 if (acfg
->use_bin_writer
)
2087 bin_writer_emit_label (acfg
, name
);
2089 asm_writer_emit_label (acfg
, name
);
2091 asm_writer_emit_label (acfg
, name
);
2096 mono_img_writer_emit_bytes (MonoImageWriter
*acfg
, const guint8
* buf
, int size
)
2098 #ifdef USE_BIN_WRITER
2099 if (acfg
->use_bin_writer
)
2100 bin_writer_emit_bytes (acfg
, buf
, size
);
2102 asm_writer_emit_bytes (acfg
, buf
, size
);
2104 asm_writer_emit_bytes (acfg
, buf
, size
);
2109 mono_img_writer_emit_string (MonoImageWriter
*acfg
, const char *value
)
2111 #ifdef USE_BIN_WRITER
2112 if (acfg
->use_bin_writer
)
2113 bin_writer_emit_string (acfg
, value
);
2115 asm_writer_emit_string (acfg
, value
);
2117 asm_writer_emit_string (acfg
, value
);
2122 mono_img_writer_emit_line (MonoImageWriter
*acfg
)
2124 #ifdef USE_BIN_WRITER
2125 if (acfg
->use_bin_writer
)
2126 bin_writer_emit_line (acfg
);
2128 asm_writer_emit_line (acfg
);
2130 asm_writer_emit_line (acfg
);
2135 mono_img_writer_emit_alignment (MonoImageWriter
*acfg
, int size
)
2137 #ifdef USE_BIN_WRITER
2138 if (acfg
->use_bin_writer
)
2139 bin_writer_emit_alignment (acfg
, size
);
2141 asm_writer_emit_alignment (acfg
, size
);
2143 asm_writer_emit_alignment (acfg
, size
);
2148 mono_img_writer_emit_alignment_fill (MonoImageWriter
*acfg
, int size
, int fill
)
2150 #ifdef USE_BIN_WRITER
2151 if (acfg
->use_bin_writer
)
2152 bin_writer_emit_alignment (acfg
, size
);
2154 asm_writer_emit_alignment (acfg
, size
);
2156 asm_writer_emit_alignment_fill (acfg
, size
, fill
);
2161 mono_img_writer_emit_pointer_unaligned (MonoImageWriter
*acfg
, const char *target
)
2163 #ifdef USE_BIN_WRITER
2164 if (acfg
->use_bin_writer
)
2165 bin_writer_emit_pointer_unaligned (acfg
, target
);
2167 asm_writer_emit_pointer_unaligned (acfg
, target
);
2169 asm_writer_emit_pointer_unaligned (acfg
, target
);
2174 mono_img_writer_emit_pointer (MonoImageWriter
*acfg
, const char *target
)
2176 #ifdef USE_BIN_WRITER
2177 if (acfg
->use_bin_writer
)
2178 bin_writer_emit_pointer (acfg
, target
);
2180 asm_writer_emit_pointer (acfg
, target
);
2182 asm_writer_emit_pointer (acfg
, target
);
2187 mono_img_writer_emit_int16 (MonoImageWriter
*acfg
, int value
)
2189 #ifdef USE_BIN_WRITER
2190 if (acfg
->use_bin_writer
)
2191 bin_writer_emit_int16 (acfg
, value
);
2193 asm_writer_emit_int16 (acfg
, value
);
2195 asm_writer_emit_int16 (acfg
, value
);
2200 mono_img_writer_emit_int32 (MonoImageWriter
*acfg
, int value
)
2202 #ifdef USE_BIN_WRITER
2203 if (acfg
->use_bin_writer
)
2204 bin_writer_emit_int32 (acfg
, value
);
2206 asm_writer_emit_int32 (acfg
, value
);
2208 asm_writer_emit_int32 (acfg
, value
);
2213 mono_img_writer_emit_symbol_diff (MonoImageWriter
*acfg
, const char *end
, const char* start
, int offset
)
2215 #ifdef USE_BIN_WRITER
2216 if (acfg
->use_bin_writer
)
2217 bin_writer_emit_symbol_diff (acfg
, end
, start
, offset
);
2219 asm_writer_emit_symbol_diff (acfg
, end
, start
, offset
);
2221 asm_writer_emit_symbol_diff (acfg
, end
, start
, offset
);
2226 mono_img_writer_emit_zero_bytes (MonoImageWriter
*acfg
, int num
)
2228 #ifdef USE_BIN_WRITER
2229 if (acfg
->use_bin_writer
)
2230 bin_writer_emit_zero_bytes (acfg
, num
);
2232 asm_writer_emit_zero_bytes (acfg
, num
);
2234 asm_writer_emit_zero_bytes (acfg
, num
);
2239 mono_img_writer_emit_writeout (MonoImageWriter
*acfg
)
2241 #ifdef USE_BIN_WRITER
2242 if (acfg
->use_bin_writer
)
2243 return bin_writer_emit_writeout (acfg
);
2245 return asm_writer_emit_writeout (acfg
);
2247 return asm_writer_emit_writeout (acfg
);
2252 mono_img_writer_emit_byte (MonoImageWriter
*acfg
, guint8 val
)
2254 mono_img_writer_emit_bytes (acfg
, &val
, 1);
2258 * Emit a relocation entry of type RELOC_TYPE against symbol SYMBOL at the current PC.
2259 * Do not advance PC.
2262 mono_img_writer_emit_reloc (MonoImageWriter
*acfg
, int reloc_type
, const char *symbol
, int addend
)
2264 /* This is only supported by the bin writer */
2265 #ifdef USE_BIN_WRITER
2266 if (acfg
->use_bin_writer
)
2267 bin_writer_emit_reloc (acfg
, reloc_type
, symbol
, addend
);
2269 g_assert_not_reached ();
2271 g_assert_not_reached ();
2276 * mono_img_writer_emit_unset_mode:
2278 * Flush buffered data so it is safe to write to the output file from outside this
2279 * module. This is a nop for the binary writer.
2282 mono_img_writer_emit_unset_mode (MonoImageWriter
*acfg
)
2284 if (!acfg
->use_bin_writer
)
2285 asm_writer_emit_unset_mode (acfg
);
2289 * mono_img_writer_get_output:
2291 * Return the output buffer of a binary writer emitting to memory. The returned memory
2292 * is from malloc, and it is owned by the caller.
2295 mono_img_writer_get_output (MonoImageWriter
*acfg
, guint32
*size
)
2297 #ifdef USE_BIN_WRITER
2300 g_assert (acfg
->use_bin_writer
);
2302 buf
= acfg
->out_buf
;
2303 *size
= acfg
->out_buf_size
;
2304 acfg
->out_buf
= NULL
;
2307 g_assert_not_reached ();
2313 * Return whenever the binary writer is supported on this platform.
2316 mono_bin_writer_supported (void)
2318 #ifdef USE_BIN_WRITER
2326 * mono_img_writer_create:
2328 * Create an image writer writing to FP. If USE_BIN_WRITER is TRUE, FP can be NULL,
2329 * in this case the image writer will write to a memory buffer obtainable by calling
2330 * mono_img_writer_get_output ().
2333 mono_img_writer_create (FILE *fp
, gboolean use_bin_writer
)
2335 MonoImageWriter
*w
= g_new0 (MonoImageWriter
, 1);
2337 #ifndef USE_BIN_WRITER
2338 g_assert (!use_bin_writer
);
2341 if (!use_bin_writer
)
2345 w
->use_bin_writer
= use_bin_writer
;
2346 w
->mempool
= mono_mempool_new ();
2352 mono_img_writer_destroy (MonoImageWriter
*w
)
2354 // FIXME: Free all the stuff
2355 mono_mempool_destroy (w
->mempool
);
2360 mono_img_writer_subsections_supported (MonoImageWriter
*acfg
)
2362 #ifdef TARGET_ASM_APPLE
2363 return acfg
->use_bin_writer
;
2370 mono_img_writer_get_fp (MonoImageWriter
*acfg
)
2376 mono_img_writer_get_temp_label_prefix (MonoImageWriter
*acfg
)
2378 return AS_TEMP_LABEL_PREFIX
;