- return rr;
-}
-
-#endif /* USE_ELF_RELA */
-
-static int
-emit_writeout (MonoAotCompile *acfg)
-{
- char *outfile_name, *tmp_outfile_name;
- FILE *file;
- ElfHeader header;
- ElfProgHeader progh [3];
- ElfSectHeader secth [SECT_NUM];
-#ifdef USE_ELF_RELA
- ElfRelocA *relocs;
-#else
- ElfReloc *relocs;
-#endif
- ElfStrTable str_table = {NULL, NULL};
- ElfStrTable sh_str_table = {NULL, NULL};
- ElfStrTable dyn_str_table = {NULL, NULL};
- BinSection* sections [6];
- BinSection *text_section = NULL, *data_section = NULL, *bss_section = NULL;
- ElfSymbol *dynsym;
- ElfSymbol *symtab;
- ElfDynamic dynamic [14];
- int *hash;
- int i, num_sections, file_offset, virt_offset, size, num_symtab;
- int num_local_syms;
-
- g_assert (!acfg->aot_opts.asm_only);
-
- if (acfg->aot_opts.outfile)
- outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
- else
- outfile_name = g_strdup_printf ("%s%s", acfg->image->name, SHARED_EXT);
-
- tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
-
- unlink (tmp_outfile_name);
- file = fopen (tmp_outfile_name, "w");
- g_assert (file);
-
- /* Section headers */
- memset (§h, 0, sizeof (secth));
- memset (&dynamic, 0, sizeof (dynamic));
- memset (&header, 0, sizeof (header));
-
- for (i = 1; i < SECT_NUM; ++i) {
- secth [i].sh_name = str_table_add (&sh_str_table, section_info [i].name);
- secth [i].sh_type = section_info [i].type;
- secth [i].sh_addralign = section_info [i].align;
- secth [i].sh_flags = section_info [i].flags;
- secth [i].sh_entsize = section_info [i].esize;
- }
- secth [SECT_DYNSYM].sh_info = SIZEOF_VOID_P == 4 ? 4 : 2;
- secth [SECT_SYMTAB].sh_info = SIZEOF_VOID_P == 4 ? 20 : 17;
- secth [SECT_HASH].sh_link = SECT_DYNSYM;
- secth [SECT_DYNSYM].sh_link = SECT_DYNSTR;
- secth [SECT_REL_DYN].sh_link = SECT_DYNSYM;
- secth [SECT_RELA_DYN].sh_link = SECT_DYNSYM;
- secth [SECT_DYNAMIC].sh_link = SECT_DYNSTR;
- secth [SECT_SYMTAB].sh_link = SECT_STRTAB;
-
- num_sections = collect_sections (acfg, secth, sections, 6);
- hash = build_hash (acfg, num_sections, &dyn_str_table);
- num_symtab = hash [1]; /* FIXME */
- g_print ("num_sections: %d\n", num_sections);
- g_print ("dynsym: %d, dynstr size: %d\n", hash [1], (int)dyn_str_table.data->len);
- for (i = 0; i < num_sections; ++i) {
- g_print ("section %s, size: %d, %x\n", sections [i]->name, sections [i]->cur_offset, sections [i]->cur_offset);
- }
-
- /* at this point we know where in the file the first segment sections go */
- dynsym = collect_syms (acfg, hash, &dyn_str_table, NULL, NULL);
- num_local_syms = hash [1];
- symtab = collect_syms (acfg, NULL, &str_table, secth, &num_local_syms);
-
- for (i = 0; i < num_sections; ++i) {
- if (sections [i]->shidx == SECT_TEXT) {
- text_section = sections [i];
- } else if (sections [i]->shidx == SECT_DATA) {
- data_section = sections [i];
- } else if (sections [i]->shidx == SECT_BSS) {
- bss_section = sections [i];
- }
- }
-
- file_offset = virt_offset = sizeof (header) + sizeof (progh);
- secth [SECT_HASH].sh_addr = secth [SECT_HASH].sh_offset = file_offset;
- size = sizeof (int) * (2 + hash [0] + hash [1]);
- virt_offset = (file_offset += size);
- secth [SECT_HASH].sh_size = size;
- secth [SECT_DYNSYM].sh_addr = secth [SECT_DYNSYM].sh_offset = file_offset;
- size = sizeof (ElfSymbol) * hash [1];
- virt_offset = (file_offset += size);
- secth [SECT_DYNSYM].sh_size = size;
- secth [SECT_DYNSTR].sh_addr = secth [SECT_DYNSTR].sh_offset = file_offset;
- size = dyn_str_table.data->len;
- virt_offset = (file_offset += size);
- secth [SECT_DYNSTR].sh_size = size;
- file_offset += 4-1;
- file_offset &= ~(4-1);
- secth [SECT_REL_DYN].sh_addr = secth [SECT_REL_DYN].sh_offset = file_offset;
-#ifndef USE_ELF_RELA
- size = sizeof (ElfReloc) * acfg->num_relocs;
-#else
- size = 0;
-#endif
- virt_offset = (file_offset += size);
- secth [SECT_REL_DYN].sh_size = size;
- secth [SECT_RELA_DYN].sh_addr = secth [SECT_RELA_DYN].sh_offset = file_offset;
-#ifdef USE_ELF_RELA
- size = sizeof (ElfRelocA) * acfg->num_relocs;
-#else
- size = 0;
-#endif
- virt_offset = (file_offset += size);
- secth [SECT_RELA_DYN].sh_size = size;
- file_offset += 4096-1;
- file_offset &= ~(4096-1);
- virt_offset = file_offset;
- secth [SECT_TEXT].sh_addr = secth [SECT_TEXT].sh_offset = file_offset;
- size = text_section->cur_offset;
- secth [SECT_TEXT].sh_size = size;
- file_offset += size;
- file_offset += 4-1;
- file_offset &= ~(4-1);
- virt_offset = file_offset;
- /* .dynamic, .got.plt, .data, .bss here */
- /* Have to increase the virt offset since these go to a separate segment */
- virt_offset += PAGESIZE;
- secth [SECT_DYNAMIC].sh_addr = virt_offset;
- secth [SECT_DYNAMIC].sh_offset = file_offset;
- size = sizeof (dynamic);
- secth [SECT_DYNAMIC].sh_size = size;
- size += 4-1;
- size &= ~(4-1);
- file_offset += size;
- virt_offset += size;
- secth [SECT_GOT_PLT].sh_addr = virt_offset;
- secth [SECT_GOT_PLT].sh_offset = file_offset;
- size = 12;
- secth [SECT_GOT_PLT].sh_size = size;
- size += 8-1;
- size &= ~(8-1);
- file_offset += size;
- virt_offset += size;
- secth [SECT_DATA].sh_addr = virt_offset;
- secth [SECT_DATA].sh_offset = file_offset;
- size = data_section->cur_offset;
- secth [SECT_DATA].sh_size = size;
- size += 8-1;
- size &= ~(8-1);
- file_offset += size;
- virt_offset += size;
- secth [SECT_BSS].sh_addr = virt_offset;
- secth [SECT_BSS].sh_offset = file_offset;
- size = bss_section->cur_offset;
- secth [SECT_BSS].sh_size = size;
-
- /* virtual doesn't matter anymore */
- secth [SECT_SHSTRTAB].sh_offset = file_offset;
- size = sh_str_table.data->len;
- secth [SECT_SHSTRTAB].sh_size = size;
- size += SIZEOF_VOID_P-1;
- size &= ~(SIZEOF_VOID_P-1);
- file_offset += size;
- secth [SECT_SYMTAB].sh_offset = file_offset;
- size = sizeof (ElfSymbol) * num_local_syms;
- secth [SECT_SYMTAB].sh_size = size;
- file_offset += size;
- secth [SECT_STRTAB].sh_offset = file_offset;
- size = str_table.data->len;
- secth [SECT_STRTAB].sh_size = size;
- file_offset += size;
- file_offset += 4-1;
- file_offset &= ~(4-1);
-
- text_section->file_offset = secth [SECT_TEXT].sh_offset;
- text_section->virt_offset = secth [SECT_TEXT].sh_addr;
- data_section->file_offset = secth [SECT_DATA].sh_offset;
- data_section->virt_offset = secth [SECT_DATA].sh_addr;
- bss_section->file_offset = secth [SECT_BSS].sh_offset;
- bss_section->virt_offset = secth [SECT_BSS].sh_addr;
-
- header.e_ident [EI_MAG0] = ELFMAG0;
- header.e_ident [EI_MAG1] = ELFMAG1;
- header.e_ident [EI_MAG2] = ELFMAG2;
- header.e_ident [EI_MAG3] = ELFMAG3;
- header.e_ident [EI_CLASS] = SIZEOF_VOID_P == 4 ? ELFCLASS32 : ELFCLASS64;
- header.e_ident [EI_DATA] = ELFDATA2LSB;
- header.e_ident [EI_VERSION] = EV_CURRENT;
- header.e_ident [EI_OSABI] = ELFOSABI_NONE;
- header.e_ident [EI_ABIVERSION] = 0;
- for (i = EI_PAD; i < EI_NIDENT; ++i)
- header.e_ident [i] = 0;
-
- header.e_type = ET_DYN;
-#if defined(__i386__)
- header.e_machine = EM_386;
-#elif defined(__x86_64__)
- header.e_machine = EM_X86_64;
-#else
- g_assert_not_reached ();
-#endif
- 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