- header.e_version = 1;
-
- header.e_phoff = sizeof (header);
- header.e_ehsize = sizeof (header);
- header.e_phentsize = sizeof (ElfProgHeader);
- header.e_phnum = 3;
- header.e_entry = secth [SECT_TEXT].sh_addr;
- header.e_shstrndx = SECT_SHSTRTAB;
- header.e_shentsize = sizeof (ElfSectHeader);
- header.e_shnum = SECT_NUM;
- header.e_shoff = file_offset;
-
- /* dynamic data */
- i = 0;
- dynamic [i].d_tag = DT_HASH;
- dynamic [i].d_un.d_val = secth [SECT_HASH].sh_offset;
- ++i;
- dynamic [i].d_tag = DT_STRTAB;
- dynamic [i].d_un.d_val = secth [SECT_DYNSTR].sh_offset;
- ++i;
- dynamic [i].d_tag = DT_SYMTAB;
- dynamic [i].d_un.d_val = secth [SECT_DYNSYM].sh_offset;
- ++i;
- dynamic [i].d_tag = DT_STRSZ;
- dynamic [i].d_un.d_val = dyn_str_table.data->len;
- ++i;
- dynamic [i].d_tag = DT_SYMENT;
- dynamic [i].d_un.d_val = sizeof (ElfSymbol);
- ++i;
-#ifdef USE_ELF_RELA
- dynamic [i].d_tag = DT_RELA;
- dynamic [i].d_un.d_val = secth [SECT_RELA_DYN].sh_offset;
- ++i;
- dynamic [i].d_tag = DT_RELASZ;
- dynamic [i].d_un.d_val = secth [SECT_RELA_DYN].sh_size;
- ++i;
- dynamic [i].d_tag = DT_RELAENT;
- dynamic [i].d_un.d_val = sizeof (ElfRelocA);
- ++i;
-#else
- dynamic [i].d_tag = DT_REL;
- dynamic [i].d_un.d_val = secth [SECT_REL_DYN].sh_offset;
- ++i;
- dynamic [i].d_tag = DT_RELSZ;
- dynamic [i].d_un.d_val = secth [SECT_REL_DYN].sh_size;
- ++i;
- dynamic [i].d_tag = DT_RELENT;
- dynamic [i].d_un.d_val = sizeof (ElfReloc);
- ++i;
-#endif
- dynamic [i].d_tag = DT_RELCOUNT;
- dynamic [i].d_un.d_val = acfg->num_relocs;
- ++i;
-
- /* Program header */
- memset (&progh, 0, sizeof (progh));
- progh [0].p_type = PT_LOAD;
- progh [0].p_filesz = progh [0].p_memsz = secth [SECT_DYNAMIC].sh_offset;
- progh [0].p_align = 4096;
- progh [0].p_flags = 5;
-
- progh [1].p_type = PT_LOAD;
- progh [1].p_offset = secth [SECT_DYNAMIC].sh_offset;
- progh [1].p_vaddr = progh [1].p_paddr = secth [SECT_DYNAMIC].sh_addr;
- progh [1].p_filesz = secth [SECT_BSS].sh_offset - secth [SECT_DYNAMIC].sh_offset;
- progh [1].p_memsz = secth [SECT_BSS].sh_addr + secth [SECT_BSS].sh_size - secth [SECT_DYNAMIC].sh_addr;
- progh [1].p_align = 4096;
- progh [1].p_flags = 6;
-
- progh [2].p_type = PT_DYNAMIC;
- progh [2].p_offset = secth [SECT_DYNAMIC].sh_offset;
- progh [2].p_vaddr = progh [2].p_paddr = secth [SECT_DYNAMIC].sh_addr;
- progh [2].p_filesz = progh [2].p_memsz = secth [SECT_DYNAMIC].sh_size;
- progh [2].p_align = SIZEOF_VOID_P;
- progh [2].p_flags = 6;
-
- reloc_symbols (acfg, dynsym, secth, &dyn_str_table, TRUE);
- reloc_symbols (acfg, symtab, secth, &str_table, FALSE);
- relocs = resolve_relocations (acfg);
-
- fwrite (&header, sizeof (header), 1, file);
- fwrite (&progh, sizeof (progh), 1, file);
- fwrite (hash, sizeof (int) * (hash [0] + hash [1] + 2), 1, file);
- fwrite (dynsym, sizeof (ElfSymbol) * hash [1], 1, file);
- fwrite (dyn_str_table.data->str, dyn_str_table.data->len, 1, file);
- /* .rel.dyn */
- fseek (file, secth [SECT_REL_DYN].sh_offset, SEEK_SET);
- fwrite (relocs, sizeof (ElfReloc), acfg->num_relocs, file);
-
- /* .rela.dyn */
- fseek (file, secth [SECT_RELA_DYN].sh_offset, SEEK_SET);
- fwrite (relocs, secth [SECT_RELA_DYN].sh_size, 1, file);
-
- fseek (file, secth [SECT_TEXT].sh_offset, SEEK_SET);
- /* write .text, .data, .bss sections */
- fwrite (text_section->data, text_section->cur_offset, 1, file);
-
- /* .dynamic */
- fwrite (dynamic, sizeof (dynamic), 1, file);
- /* .got.plt */
- size = secth [SECT_DYNAMIC].sh_addr;
- fwrite (&size, sizeof (size), 1, file);
- fseek (file, secth [SECT_DATA].sh_offset, SEEK_SET);
- fwrite (data_section->data, data_section->cur_offset, 1, file);
-
- fseek (file, secth [SECT_SHSTRTAB].sh_offset, SEEK_SET);
- fwrite (sh_str_table.data->str, sh_str_table.data->len, 1, file);
- fseek (file, secth [SECT_SYMTAB].sh_offset, SEEK_SET);
- fwrite (symtab, sizeof (ElfSymbol) * num_local_syms, 1, file);
- fseek (file, secth [SECT_STRTAB].sh_offset, SEEK_SET);
- fwrite (str_table.data->str, str_table.data->len, 1, file);
- /*g_print ("file_offset %d vs %d\n", file_offset, ftell (file));*/
- /*g_assert (file_offset >= ftell (file));*/
- fseek (file, file_offset, SEEK_SET);
- fwrite (§h, sizeof (secth), 1, file);
- fclose (file);
- rename (tmp_outfile_name, outfile_name);
-
- g_free (tmp_outfile_name);
- g_free (outfile_name);
-
- return 0;
-}
-
-#endif /* USE_ELF_WRITER */
-
-#else
-
-static void
-emit_start (MonoAotCompile *acfg)
-{
- if (acfg->aot_opts.asm_only) {
- if (acfg->aot_opts.outfile)
- acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
- else
- acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
- acfg->fp = fopen (acfg->tmpfname, "w+");
- } else {
- int i = g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL);
- acfg->fp = fdopen (i, "w+");
- }
- g_assert (acfg->fp);
-}
-
-static void
-emit_unset_mode (MonoAotCompile *acfg)
-{
- if (acfg->mode == EMIT_NONE)
- return;
- fprintf (acfg->fp, "\n");
- acfg->mode = EMIT_NONE;
-}
-
-static void
-emit_section_change (MonoAotCompile *acfg, const char *section_name, int subsection_index)
-{
- emit_unset_mode (acfg);
-#if defined(PLATFORM_WIN32)
- fprintf (acfg->fp, ".section %s\n", section_name);
-#elif defined(__MACH__)
- if (strcmp(section_name, ".bss") == 0)
- fprintf (acfg->fp, "%s\n", ".data");
- else
- fprintf (acfg->fp, "%s\n", section_name);
-#elif defined(sparc) || defined(__arm__)
- /* For solaris as, GNU as should accept the same */
- fprintf (acfg->fp, ".section \"%s\"\n", section_name);
-#else
- fprintf (acfg->fp, "%s %d\n", section_name, subsection_index);
-#endif
-}
-
-static void
-emit_symbol_type (MonoAotCompile *acfg, const char *name, gboolean func)
-{
- const char *stype;
-
- if (func)
- stype = "function";
- else
- stype = "object";
-
- emit_unset_mode (acfg);
-#if defined(__MACH__)
-
-#elif defined(sparc) || defined(__arm__)
- fprintf (acfg->fp, "\t.type %s,#%s\n", name, stype);
-#elif defined(PLATFORM_WIN32)
-
-#elif defined(__x86_64__) || defined(__i386__)
- fprintf (acfg->fp, "\t.type %s,@%s\n", name, stype);
-#else
- fprintf (acfg->fp, "\t.type %s,@%s\n", name, stype);
-#endif
-}
-
-static void
-emit_global_inner (MonoAotCompile *acfg, const char *name, gboolean func)
-{
- emit_unset_mode (acfg);
-#if (defined(__ppc__) && defined(__MACH__)) || defined(PLATFORM_WIN32)
- // mach-o always uses a '_' prefix.
- fprintf (acfg->fp, "\t.globl _%s\n", name);
-#else
- fprintf (acfg->fp, "\t.globl %s\n", name);
-#endif
-
- emit_symbol_type (acfg, name, func);
-}
-
-static void
-emit_label (MonoAotCompile *acfg, const char *name)
-{
- emit_unset_mode (acfg);
-#if (defined(__ppc__) && defined(__MACH__)) || defined(PLATFORM_WIN32)
- // mach-o always uses a '_' prefix.
- fprintf (acfg->fp, "_%s:\n", name);
-#else
- fprintf (acfg->fp, "%s:\n", name);
-#endif
-
-#if defined(PLATFORM_WIN32)
- /* Emit a normal label too */
- fprintf (acfg->fp, "%s:\n", name);
-#endif
-}
-
-static void
-emit_string (MonoAotCompile *acfg, const char *value)
-{
- emit_unset_mode (acfg);
- fprintf (acfg->fp, "\t%s \"%s\"\n", AS_STRING_DIRECTIVE, value);
-}
-
-static void
-emit_line (MonoAotCompile *acfg)
-{
- emit_unset_mode (acfg);
- fprintf (acfg->fp, "\n");
-}
-
-static void
-emit_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
-{
- emit_unset_mode (acfg);
- emit_section_change (acfg, ".text", 1);
- emit_global (acfg, name, FALSE);
- emit_label (acfg, name);
- emit_string (acfg, value);
-}
-
-static void
-emit_alignment (MonoAotCompile *acfg, int size)
-{
- emit_unset_mode (acfg);
-#if defined(__arm__)
- fprintf (acfg->fp, "\t.align %d\n", ilog2 (size));
-#elif defined(__ppc__) && defined(__MACH__)
- // the mach-o assembler specifies alignments as powers of 2.
- fprintf (acfg->fp, "\t.align %d\t; ilog2\n", ilog2(size));
-#elif defined(__powerpc__)
- /* ignore on linux/ppc */
-#else
- fprintf (acfg->fp, "\t.align %d\n", size);
-#endif
-}
-
-static void
-emit_pointer (MonoAotCompile *acfg, const char *target)
-{
- emit_unset_mode (acfg);
- emit_alignment (acfg, sizeof (gpointer));
-#if defined(__x86_64__)
- fprintf (acfg->fp, "\t.quad %s\n", target ? target : "0");
-#elif defined(sparc) && SIZEOF_VOID_P == 8
- fprintf (acfg->fp, "\t.xword %s\n", target ? target : "0");
-#else
- fprintf (acfg->fp, "\t.long %s\n", target ? target : "0");
-#endif
-}
-
-static char *byte_to_str;
-
-static void
-emit_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
-{
- int i;
- if (acfg->mode != EMIT_BYTE) {
- acfg->mode = EMIT_BYTE;
- acfg->col_count = 0;
- }
-
- if (byte_to_str == NULL) {
- byte_to_str = g_new0 (char, 256 * 8);
- for (i = 0; i < 256; ++i) {
- sprintf (byte_to_str + (i * 8), ",%d", i);
- }
- }
-
- for (i = 0; i < size; ++i, ++acfg->col_count) {
- if ((acfg->col_count % 32) == 0)
- fprintf (acfg->fp, "\n\t.byte %d", buf [i]);
- else
- fputs (byte_to_str + (buf [i] * 8), acfg->fp);
- }
-}
-
-static inline void
-emit_int16 (MonoAotCompile *acfg, int value)
-{
- if (acfg->mode != EMIT_WORD) {
- acfg->mode = EMIT_WORD;
- acfg->col_count = 0;
- }
- if ((acfg->col_count++ % 8) == 0)
-#if defined(__MACH__)
- fprintf (acfg->fp, "\n\t.short ");
-#elif defined(__arm__)
- /* FIXME: Use .hword on other archs as well */
- fprintf (acfg->fp, "\n\t.hword ");
-#else
- fprintf (acfg->fp, "\n\t.word ");
-#endif
- else
- fprintf (acfg->fp, ", ");
- fprintf (acfg->fp, "%d", value);