summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/elf_writer_quick.cc1336
-rw-r--r--compiler/elf_writer_quick.h261
2 files changed, 671 insertions, 926 deletions
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index f2a4e95cbc..09f2eaea20 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -29,16 +29,21 @@
namespace art {
-static constexpr Elf32_Word NextOffset(const Elf32_Shdr& cur, const Elf32_Shdr& prev) {
- return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign);
-}
-
-static uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
- return ((binding) << 4) + ((type) & 0xf);
+bool ElfWriterQuick::Create(File* elf_file,
+ OatWriter* oat_writer,
+ const std::vector<const DexFile*>& dex_files,
+ const std::string& android_root,
+ bool is_host,
+ const CompilerDriver& driver) {
+ ElfWriterQuick elf_writer(driver, elf_file);
+ return elf_writer.Write(oat_writer, dex_files, android_root, is_host);
}
-bool ElfWriterQuick::ElfBuilder::Write() {
- // The basic layout of the elf file. Order may be different in final output.
+bool ElfWriterQuick::Write(OatWriter* oat_writer,
+ const std::vector<const DexFile*>& dex_files_unused,
+ const std::string& android_root_unused,
+ bool is_host_unused) {
+ const bool debug = false;
// +-------------------------+
// | Elf32_Ehdr |
// +-------------------------+
@@ -62,14 +67,12 @@ bool ElfWriterQuick::ElfBuilder::Write() {
// | boot.oat\0 |
// +-------------------------+
// | .hash |
- // | Elf32_Word nbucket = b |
- // | Elf32_Word nchain = c |
- // | Elf32_Word bucket[0] |
- // | ... |
- // | Elf32_Word bucket[b - 1]|
- // | Elf32_Word chain[0] |
- // | ... |
- // | Elf32_Word chain[c - 1] |
+ // | Elf32_Word nbucket = 1 |
+ // | Elf32_Word nchain = 3 |
+ // | Elf32_Word bucket[0] = 0|
+ // | Elf32_Word chain[0] = 1|
+ // | Elf32_Word chain[1] = 2|
+ // | Elf32_Word chain[2] = 3|
// +-------------------------+
// | .rodata |
// | oatdata..oatexec-4 |
@@ -85,12 +88,6 @@ bool ElfWriterQuick::ElfBuilder::Write() {
// | Elf32_Dyn DT_STRTAB |
// | Elf32_Dyn DT_STRSZ |
// | Elf32_Dyn DT_NULL |
- // +-------------------------+ (Optional)
- // | .strtab | (Optional)
- // | program symbol names | (Optional)
- // +-------------------------+ (Optional)
- // | .symtab | (Optional)
- // | program symbols | (Optional)
// +-------------------------+
// | .shstrtab |
// | \0 |
@@ -101,20 +98,7 @@ bool ElfWriterQuick::ElfBuilder::Write() {
// | .rodata\0 |
// | .text\0 |
// | .shstrtab\0 |
- // | .symtab\0 | (Optional)
- // | .strtab\0 | (Optional)
- // | .debug_str\0 | (Optional)
- // | .debug_info\0 | (Optional)
- // | .debug_frame\0 | (Optional)
- // | .debug_abbrev\0 | (Optional)
- // +-------------------------+ (Optional)
- // | .debug_str | (Optional)
- // +-------------------------+ (Optional)
- // | .debug_info | (Optional)
- // +-------------------------+ (Optional)
- // | .debug_frame | (Optional)
- // +-------------------------+ (Optional)
- // | .debug_abbrev | (Optional)
+ // | .debug_frame\0 |
// +-------------------------+
// | Elf32_Shdr NULL |
// | Elf32_Shdr .dynsym |
@@ -124,20 +108,20 @@ bool ElfWriterQuick::ElfBuilder::Write() {
// | Elf32_Shdr .rodata |
// | Elf32_Shdr .dynamic |
// | Elf32_Shdr .shstrtab |
- // | Elf32_Shdr .debug_str | (Optional)
// | Elf32_Shdr .debug_info | (Optional)
- // | Elf32_Shdr .debug_frame | (Optional)
// | Elf32_Shdr .debug_abbrev| (Optional)
+ // | Elf32_Shdr .debug_frame | (Optional)
// +-------------------------+
+ // phase 1: computing offsets
+ uint32_t expected_offset = 0;
- if (fatal_error_) {
- return false;
- }
- // Step 1. Figure out all the offsets.
+ // Elf32_Ehdr
+ expected_offset += sizeof(Elf32_Ehdr);
- // What phdr is.
- uint32_t phdr_offset = sizeof(Elf32_Ehdr);
+ // PHDR
+ uint32_t phdr_alignment = sizeof(Elf32_Word);
+ uint32_t phdr_offset = expected_offset;
const uint8_t PH_PHDR = 0;
const uint8_t PH_LOAD_R__ = 1;
const uint8_t PH_LOAD_R_X = 2;
@@ -145,12 +129,295 @@ bool ElfWriterQuick::ElfBuilder::Write() {
const uint8_t PH_DYNAMIC = 4;
const uint8_t PH_NUM = 5;
uint32_t phdr_size = sizeof(Elf32_Phdr) * PH_NUM;
- if (debug_logging_) {
+ expected_offset += phdr_size;
+ if (debug) {
LOG(INFO) << "phdr_offset=" << phdr_offset << std::hex << " " << phdr_offset;
LOG(INFO) << "phdr_size=" << phdr_size << std::hex << " " << phdr_size;
}
+
+ // .dynsym
+ uint32_t dynsym_alignment = sizeof(Elf32_Word);
+ uint32_t dynsym_offset = expected_offset = RoundUp(expected_offset, dynsym_alignment);
+ const uint8_t SYM_UNDEF = 0; // aka STN_UNDEF
+ const uint8_t SYM_OATDATA = 1;
+ const uint8_t SYM_OATEXEC = 2;
+ const uint8_t SYM_OATLASTWORD = 3;
+ const uint8_t SYM_NUM = 4;
+ uint32_t dynsym_size = sizeof(Elf32_Sym) * SYM_NUM;
+ expected_offset += dynsym_size;
+ if (debug) {
+ LOG(INFO) << "dynsym_offset=" << dynsym_offset << std::hex << " " << dynsym_offset;
+ LOG(INFO) << "dynsym_size=" << dynsym_size << std::hex << " " << dynsym_size;
+ }
+
+ // .dynstr
+ uint32_t dynstr_alignment = 1;
+ uint32_t dynstr_offset = expected_offset = RoundUp(expected_offset, dynstr_alignment);
+ std::string dynstr;
+ dynstr += '\0';
+ uint32_t dynstr_oatdata_offset = dynstr.size();
+ dynstr += "oatdata";
+ dynstr += '\0';
+ uint32_t dynstr_oatexec_offset = dynstr.size();
+ dynstr += "oatexec";
+ dynstr += '\0';
+ uint32_t dynstr_oatlastword_offset = dynstr.size();
+ dynstr += "oatlastword";
+ dynstr += '\0';
+ uint32_t dynstr_soname_offset = dynstr.size();
+ std::string file_name(elf_file_->GetPath());
+ size_t directory_separator_pos = file_name.rfind('/');
+ if (directory_separator_pos != std::string::npos) {
+ file_name = file_name.substr(directory_separator_pos + 1);
+ }
+ dynstr += file_name;
+ dynstr += '\0';
+ uint32_t dynstr_size = dynstr.size();
+ expected_offset += dynstr_size;
+ if (debug) {
+ LOG(INFO) << "dynstr_offset=" << dynstr_offset << std::hex << " " << dynstr_offset;
+ LOG(INFO) << "dynstr_size=" << dynstr_size << std::hex << " " << dynstr_size;
+ }
+
+ // .hash
+ uint32_t hash_alignment = sizeof(Elf32_Word); // Even for 64-bit
+ uint32_t hash_offset = expected_offset = RoundUp(expected_offset, hash_alignment);
+ const uint8_t HASH_NBUCKET = 0;
+ const uint8_t HASH_NCHAIN = 1;
+ const uint8_t HASH_BUCKET0 = 2;
+ const uint8_t HASH_NUM = HASH_BUCKET0 + 1 + SYM_NUM;
+ uint32_t hash_size = sizeof(Elf32_Word) * HASH_NUM;
+ expected_offset += hash_size;
+ if (debug) {
+ LOG(INFO) << "hash_offset=" << hash_offset << std::hex << " " << hash_offset;
+ LOG(INFO) << "hash_size=" << hash_size << std::hex << " " << hash_size;
+ }
+
+ // .rodata
+ uint32_t oat_data_alignment = kPageSize;
+ uint32_t oat_data_offset = expected_offset = RoundUp(expected_offset, oat_data_alignment);
+ const OatHeader& oat_header = oat_writer->GetOatHeader();
+ CHECK(oat_header.IsValid());
+ uint32_t oat_data_size = oat_header.GetExecutableOffset();
+ expected_offset += oat_data_size;
+ if (debug) {
+ LOG(INFO) << "oat_data_offset=" << oat_data_offset << std::hex << " " << oat_data_offset;
+ LOG(INFO) << "oat_data_size=" << oat_data_size << std::hex << " " << oat_data_size;
+ }
+
+ // .text
+ uint32_t oat_exec_alignment = kPageSize;
+ CHECK_ALIGNED(expected_offset, kPageSize);
+ uint32_t oat_exec_offset = expected_offset = RoundUp(expected_offset, oat_exec_alignment);
+ uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size;
+ expected_offset += oat_exec_size;
+ CHECK_EQ(oat_data_offset + oat_writer->GetSize(), expected_offset);
+ if (debug) {
+ LOG(INFO) << "oat_exec_offset=" << oat_exec_offset << std::hex << " " << oat_exec_offset;
+ LOG(INFO) << "oat_exec_size=" << oat_exec_size << std::hex << " " << oat_exec_size;
+ }
+
+ // .dynamic
+ // alignment would naturally be sizeof(Elf32_Word), but we want this in a new segment
+ uint32_t dynamic_alignment = kPageSize;
+ uint32_t dynamic_offset = expected_offset = RoundUp(expected_offset, dynamic_alignment);
+ const uint8_t DH_SONAME = 0;
+ const uint8_t DH_HASH = 1;
+ const uint8_t DH_SYMTAB = 2;
+ const uint8_t DH_SYMENT = 3;
+ const uint8_t DH_STRTAB = 4;
+ const uint8_t DH_STRSZ = 5;
+ const uint8_t DH_NULL = 6;
+ const uint8_t DH_NUM = 7;
+ uint32_t dynamic_size = sizeof(Elf32_Dyn) * DH_NUM;
+ expected_offset += dynamic_size;
+ if (debug) {
+ LOG(INFO) << "dynamic_offset=" << dynamic_offset << std::hex << " " << dynamic_offset;
+ LOG(INFO) << "dynamic_size=" << dynamic_size << std::hex << " " << dynamic_size;
+ }
+
+ // .shstrtab
+ uint32_t shstrtab_alignment = 1;
+ uint32_t shstrtab_offset = expected_offset = RoundUp(expected_offset, shstrtab_alignment);
+ std::string shstrtab;
+ shstrtab += '\0';
+ uint32_t shstrtab_dynamic_offset = shstrtab.size();
+ CHECK_EQ(1U, shstrtab_dynamic_offset);
+ shstrtab += ".dynamic";
+ shstrtab += '\0';
+ uint32_t shstrtab_dynsym_offset = shstrtab.size();
+ shstrtab += ".dynsym";
+ shstrtab += '\0';
+ uint32_t shstrtab_dynstr_offset = shstrtab.size();
+ shstrtab += ".dynstr";
+ shstrtab += '\0';
+ uint32_t shstrtab_hash_offset = shstrtab.size();
+ shstrtab += ".hash";
+ shstrtab += '\0';
+ uint32_t shstrtab_rodata_offset = shstrtab.size();
+ shstrtab += ".rodata";
+ shstrtab += '\0';
+ uint32_t shstrtab_text_offset = shstrtab.size();
+ shstrtab += ".text";
+ shstrtab += '\0';
+ uint32_t shstrtab_shstrtab_offset = shstrtab.size();
+ shstrtab += ".shstrtab";
+ shstrtab += '\0';
+ uint32_t shstrtab_debug_info_offset = shstrtab.size();
+ shstrtab += ".debug_info";
+ shstrtab += '\0';
+ uint32_t shstrtab_debug_abbrev_offset = shstrtab.size();
+ shstrtab += ".debug_abbrev";
+ shstrtab += '\0';
+ uint32_t shstrtab_debug_str_offset = shstrtab.size();
+ shstrtab += ".debug_str";
+ shstrtab += '\0';
+ uint32_t shstrtab_debug_frame_offset = shstrtab.size();
+ shstrtab += ".debug_frame";
+ shstrtab += '\0';
+ uint32_t shstrtab_size = shstrtab.size();
+ expected_offset += shstrtab_size;
+ if (debug) {
+ LOG(INFO) << "shstrtab_offset=" << shstrtab_offset << std::hex << " " << shstrtab_offset;
+ LOG(INFO) << "shstrtab_size=" << shstrtab_size << std::hex << " " << shstrtab_size;
+ }
+
+ // Create debug informatin, if we have it.
+ bool generateDebugInformation = compiler_driver_->GetCallFrameInformation() != nullptr;
+ std::vector<uint8_t> dbg_info;
+ std::vector<uint8_t> dbg_abbrev;
+ std::vector<uint8_t> dbg_str;
+ if (generateDebugInformation) {
+ FillInCFIInformation(oat_writer, &dbg_info, &dbg_abbrev, &dbg_str);
+ }
+
+ uint32_t shdbg_info_alignment = 1;
+ uint32_t shdbg_info_offset = expected_offset;
+ uint32_t shdbg_info_size = dbg_info.size();
+ expected_offset += shdbg_info_size;
+ if (debug) {
+ LOG(INFO) << "shdbg_info_offset=" << shdbg_info_offset << std::hex << " " << shdbg_info_offset;
+ LOG(INFO) << "shdbg_info_size=" << shdbg_info_size << std::hex << " " << shdbg_info_size;
+ }
+
+ uint32_t shdbg_abbrev_alignment = 1;
+ uint32_t shdbg_abbrev_offset = expected_offset;
+ uint32_t shdbg_abbrev_size = dbg_abbrev.size();
+ expected_offset += shdbg_abbrev_size;
+ if (debug) {
+ LOG(INFO) << "shdbg_abbrev_offset=" << shdbg_abbrev_offset << std::hex << " " << shdbg_abbrev_offset;
+ LOG(INFO) << "shdbg_abbrev_size=" << shdbg_abbrev_size << std::hex << " " << shdbg_abbrev_size;
+ }
+
+ uint32_t shdbg_frm_alignment = 4;
+ uint32_t shdbg_frm_offset = expected_offset = RoundUp(expected_offset, shdbg_frm_alignment);
+ uint32_t shdbg_frm_size =
+ generateDebugInformation ? compiler_driver_->GetCallFrameInformation()->size() : 0;
+ expected_offset += shdbg_frm_size;
+ if (debug) {
+ LOG(INFO) << "shdbg_frm_offset=" << shdbg_frm_offset << std::hex << " " << shdbg_frm_offset;
+ LOG(INFO) << "shdbg_frm_size=" << shdbg_frm_size << std::hex << " " << shdbg_frm_size;
+ }
+
+ uint32_t shdbg_str_alignment = 1;
+ uint32_t shdbg_str_offset = expected_offset;
+ uint32_t shdbg_str_size = dbg_str.size();
+ expected_offset += shdbg_str_size;
+ if (debug) {
+ LOG(INFO) << "shdbg_str_offset=" << shdbg_str_offset << std::hex << " " << shdbg_str_offset;
+ LOG(INFO) << "shdbg_str_size=" << shdbg_str_size << std::hex << " " << shdbg_str_size;
+ }
+
+ // section headers (after all sections)
+ uint32_t shdr_alignment = sizeof(Elf32_Word);
+ uint32_t shdr_offset = expected_offset = RoundUp(expected_offset, shdr_alignment);
+ const uint8_t SH_NULL = 0;
+ const uint8_t SH_DYNSYM = 1;
+ const uint8_t SH_DYNSTR = 2;
+ const uint8_t SH_HASH = 3;
+ const uint8_t SH_RODATA = 4;
+ const uint8_t SH_TEXT = 5;
+ const uint8_t SH_DYNAMIC = 6;
+ const uint8_t SH_SHSTRTAB = 7;
+ const uint8_t SH_DBG_INFO = 8;
+ const uint8_t SH_DBG_ABRV = 9;
+ const uint8_t SH_DBG_FRM = 10;
+ const uint8_t SH_DBG_STR = 11;
+ const uint8_t SH_NUM = generateDebugInformation ? 12 : 8;
+ uint32_t shdr_size = sizeof(Elf32_Shdr) * SH_NUM;
+ expected_offset += shdr_size;
+ if (debug) {
+ LOG(INFO) << "shdr_offset=" << shdr_offset << std::hex << " " << shdr_offset;
+ LOG(INFO) << "shdr_size=" << shdr_size << std::hex << " " << shdr_size;
+ }
+
+ // phase 2: initializing data
+
+ // Elf32_Ehdr
+ Elf32_Ehdr elf_header;
+ memset(&elf_header, 0, sizeof(elf_header));
+ elf_header.e_ident[EI_MAG0] = ELFMAG0;
+ elf_header.e_ident[EI_MAG1] = ELFMAG1;
+ elf_header.e_ident[EI_MAG2] = ELFMAG2;
+ elf_header.e_ident[EI_MAG3] = ELFMAG3;
+ elf_header.e_ident[EI_CLASS] = ELFCLASS32;
+ elf_header.e_ident[EI_DATA] = ELFDATA2LSB;
+ elf_header.e_ident[EI_VERSION] = EV_CURRENT;
+ elf_header.e_ident[EI_OSABI] = ELFOSABI_LINUX;
+ elf_header.e_ident[EI_ABIVERSION] = 0;
+ elf_header.e_type = ET_DYN;
+ switch (compiler_driver_->GetInstructionSet()) {
+ case kArm:
+ // Fall through.
+ case kThumb2: {
+ elf_header.e_machine = EM_ARM;
+ elf_header.e_flags = EF_ARM_EABI_VER5;
+ break;
+ }
+ case kArm64: {
+ elf_header.e_machine = EM_AARCH64;
+ elf_header.e_flags = 0;
+ break;
+ }
+ case kX86: {
+ elf_header.e_machine = EM_386;
+ elf_header.e_flags = 0;
+ break;
+ }
+ case kX86_64: {
+ elf_header.e_machine = EM_X86_64;
+ elf_header.e_flags = 0;
+ break;
+ }
+ case kMips: {
+ elf_header.e_machine = EM_MIPS;
+ elf_header.e_flags = (EF_MIPS_NOREORDER |
+ EF_MIPS_PIC |
+ EF_MIPS_CPIC |
+ EF_MIPS_ABI_O32 |
+ EF_MIPS_ARCH_32R2);
+ break;
+ }
+ default: {
+ LOG(FATAL) << "Unknown instruction set: " << compiler_driver_->GetInstructionSet();
+ break;
+ }
+ }
+ elf_header.e_version = 1;
+ elf_header.e_entry = 0;
+ elf_header.e_phoff = phdr_offset;
+ elf_header.e_shoff = shdr_offset;
+ elf_header.e_ehsize = sizeof(Elf32_Ehdr);
+ elf_header.e_phentsize = sizeof(Elf32_Phdr);
+ elf_header.e_phnum = PH_NUM;
+ elf_header.e_shentsize = sizeof(Elf32_Shdr);
+ elf_header.e_shnum = SH_NUM;
+ elf_header.e_shstrndx = SH_SHSTRTAB;
+
+ // PHDR
Elf32_Phdr program_headers[PH_NUM];
memset(&program_headers, 0, sizeof(program_headers));
+
program_headers[PH_PHDR].p_type = PT_PHDR;
program_headers[PH_PHDR].p_offset = phdr_offset;
program_headers[PH_PHDR].p_vaddr = phdr_offset;
@@ -158,680 +425,419 @@ bool ElfWriterQuick::ElfBuilder::Write() {
program_headers[PH_PHDR].p_filesz = sizeof(program_headers);
program_headers[PH_PHDR].p_memsz = sizeof(program_headers);
program_headers[PH_PHDR].p_flags = PF_R;
- program_headers[PH_PHDR].p_align = sizeof(Elf32_Word);
+ program_headers[PH_PHDR].p_align = phdr_alignment;
program_headers[PH_LOAD_R__].p_type = PT_LOAD;
program_headers[PH_LOAD_R__].p_offset = 0;
program_headers[PH_LOAD_R__].p_vaddr = 0;
program_headers[PH_LOAD_R__].p_paddr = 0;
+ program_headers[PH_LOAD_R__].p_filesz = oat_data_offset + oat_data_size;
+ program_headers[PH_LOAD_R__].p_memsz = oat_data_offset + oat_data_size;
program_headers[PH_LOAD_R__].p_flags = PF_R;
+ program_headers[PH_LOAD_R__].p_align = oat_data_alignment;
program_headers[PH_LOAD_R_X].p_type = PT_LOAD;
+ program_headers[PH_LOAD_R_X].p_offset = oat_exec_offset;
+ program_headers[PH_LOAD_R_X].p_vaddr = oat_exec_offset;
+ program_headers[PH_LOAD_R_X].p_paddr = oat_exec_offset;
+ program_headers[PH_LOAD_R_X].p_filesz = oat_exec_size;
+ program_headers[PH_LOAD_R_X].p_memsz = oat_exec_size;
program_headers[PH_LOAD_R_X].p_flags = PF_R | PF_X;
+ program_headers[PH_LOAD_R_X].p_align = oat_exec_alignment;
+ // TODO: PF_W for DYNAMIC is considered processor specific, do we need it?
program_headers[PH_LOAD_RW_].p_type = PT_LOAD;
+ program_headers[PH_LOAD_RW_].p_offset = dynamic_offset;
+ program_headers[PH_LOAD_RW_].p_vaddr = dynamic_offset;
+ program_headers[PH_LOAD_RW_].p_paddr = dynamic_offset;
+ program_headers[PH_LOAD_RW_].p_filesz = dynamic_size;
+ program_headers[PH_LOAD_RW_].p_memsz = dynamic_size;
program_headers[PH_LOAD_RW_].p_flags = PF_R | PF_W;
+ program_headers[PH_LOAD_RW_].p_align = dynamic_alignment;
+ // TODO: PF_W for DYNAMIC is considered processor specific, do we need it?
program_headers[PH_DYNAMIC].p_type = PT_DYNAMIC;
+ program_headers[PH_DYNAMIC].p_offset = dynamic_offset;
+ program_headers[PH_DYNAMIC].p_vaddr = dynamic_offset;
+ program_headers[PH_DYNAMIC].p_paddr = dynamic_offset;
+ program_headers[PH_DYNAMIC].p_filesz = dynamic_size;
+ program_headers[PH_DYNAMIC].p_memsz = dynamic_size;
program_headers[PH_DYNAMIC].p_flags = PF_R | PF_W;
+ program_headers[PH_DYNAMIC].p_align = dynamic_alignment;
+
+ // .dynsym
+ Elf32_Sym dynsym[SYM_NUM];
+ memset(&dynsym, 0, sizeof(dynsym));
+
+ dynsym[SYM_UNDEF].st_name = 0;
+ dynsym[SYM_UNDEF].st_value = 0;
+ dynsym[SYM_UNDEF].st_size = 0;
+ dynsym[SYM_UNDEF].st_info = 0;
+ dynsym[SYM_UNDEF].st_other = 0;
+ dynsym[SYM_UNDEF].st_shndx = 0;
+
+ dynsym[SYM_OATDATA].st_name = dynstr_oatdata_offset;
+ dynsym[SYM_OATDATA].st_value = oat_data_offset;
+ dynsym[SYM_OATDATA].st_size = oat_data_size;
+ SetBindingAndType(&dynsym[SYM_OATDATA], STB_GLOBAL, STT_OBJECT);
+ dynsym[SYM_OATDATA].st_other = STV_DEFAULT;
+ dynsym[SYM_OATDATA].st_shndx = SH_RODATA;
+
+ dynsym[SYM_OATEXEC].st_name = dynstr_oatexec_offset;
+ dynsym[SYM_OATEXEC].st_value = oat_exec_offset;
+ dynsym[SYM_OATEXEC].st_size = oat_exec_size;
+ SetBindingAndType(&dynsym[SYM_OATEXEC], STB_GLOBAL, STT_OBJECT);
+ dynsym[SYM_OATEXEC].st_other = STV_DEFAULT;
+ dynsym[SYM_OATEXEC].st_shndx = SH_TEXT;
+
+ dynsym[SYM_OATLASTWORD].st_name = dynstr_oatlastword_offset;
+ dynsym[SYM_OATLASTWORD].st_value = oat_exec_offset + oat_exec_size - 4;
+ dynsym[SYM_OATLASTWORD].st_size = 4;
+ SetBindingAndType(&dynsym[SYM_OATLASTWORD], STB_GLOBAL, STT_OBJECT);
+ dynsym[SYM_OATLASTWORD].st_other = STV_DEFAULT;
+ dynsym[SYM_OATLASTWORD].st_shndx = SH_TEXT;
+
+ // .dynstr initialized above as dynstr
+
+ // .hash
+ Elf32_Word hash[HASH_NUM]; // Note this is Elf32_Word even on 64-bit
+ hash[HASH_NBUCKET] = 1;
+ hash[HASH_NCHAIN] = SYM_NUM;
+ hash[HASH_BUCKET0] = SYM_OATDATA;
+ hash[HASH_BUCKET0 + 1 + SYM_UNDEF] = SYM_UNDEF;
+ hash[HASH_BUCKET0 + 1 + SYM_OATDATA] = SYM_OATEXEC;
+ hash[HASH_BUCKET0 + 1 + SYM_OATEXEC] = SYM_OATLASTWORD;
+ hash[HASH_BUCKET0 + 1 + SYM_OATLASTWORD] = SYM_UNDEF;
+
+ // .rodata and .text content come from oat_contents
+
+ // .dynamic
+ Elf32_Dyn dynamic_headers[DH_NUM];
+ memset(&dynamic_headers, 0, sizeof(dynamic_headers));
+
+ dynamic_headers[DH_SONAME].d_tag = DT_SONAME;
+ dynamic_headers[DH_SONAME].d_un.d_val = dynstr_soname_offset;
+
+ dynamic_headers[DH_HASH].d_tag = DT_HASH;
+ dynamic_headers[DH_HASH].d_un.d_ptr = hash_offset;
+
+ dynamic_headers[DH_SYMTAB].d_tag = DT_SYMTAB;
+ dynamic_headers[DH_SYMTAB].d_un.d_ptr = dynsym_offset;
+
+ dynamic_headers[DH_SYMENT].d_tag = DT_SYMENT;
+ dynamic_headers[DH_SYMENT].d_un.d_val = sizeof(Elf32_Sym);
+
+ dynamic_headers[DH_STRTAB].d_tag = DT_STRTAB;
+ dynamic_headers[DH_STRTAB].d_un.d_ptr = dynstr_offset;
+
+ dynamic_headers[DH_STRSZ].d_tag = DT_STRSZ;
+ dynamic_headers[DH_STRSZ].d_un.d_val = dynstr_size;
+
+ dynamic_headers[DH_NULL].d_tag = DT_NULL;
+ dynamic_headers[DH_NULL].d_un.d_val = 0;
+
+ // .shstrtab initialized above as shstrtab
+
+ // section headers (after all sections)
+ Elf32_Shdr section_headers[SH_NUM];
+ memset(&section_headers, 0, sizeof(section_headers));
+
+ section_headers[SH_NULL].sh_name = 0;
+ section_headers[SH_NULL].sh_type = SHT_NULL;
+ section_headers[SH_NULL].sh_flags = 0;
+ section_headers[SH_NULL].sh_addr = 0;
+ section_headers[SH_NULL].sh_offset = 0;
+ section_headers[SH_NULL].sh_size = 0;
+ section_headers[SH_NULL].sh_link = 0;
+ section_headers[SH_NULL].sh_info = 0;
+ section_headers[SH_NULL].sh_addralign = 0;
+ section_headers[SH_NULL].sh_entsize = 0;
+
+ section_headers[SH_DYNSYM].sh_name = shstrtab_dynsym_offset;
+ section_headers[SH_DYNSYM].sh_type = SHT_DYNSYM;
+ section_headers[SH_DYNSYM].sh_flags = SHF_ALLOC;
+ section_headers[SH_DYNSYM].sh_addr = dynsym_offset;
+ section_headers[SH_DYNSYM].sh_offset = dynsym_offset;
+ section_headers[SH_DYNSYM].sh_size = dynsym_size;
+ section_headers[SH_DYNSYM].sh_link = SH_DYNSTR;
+ section_headers[SH_DYNSYM].sh_info = 1; // 1 because we have not STB_LOCAL symbols
+ section_headers[SH_DYNSYM].sh_addralign = dynsym_alignment;
+ section_headers[SH_DYNSYM].sh_entsize = sizeof(Elf32_Sym);
+
+ section_headers[SH_DYNSTR].sh_name = shstrtab_dynstr_offset;
+ section_headers[SH_DYNSTR].sh_type = SHT_STRTAB;
+ section_headers[SH_DYNSTR].sh_flags = SHF_ALLOC;
+ section_headers[SH_DYNSTR].sh_addr = dynstr_offset;
+ section_headers[SH_DYNSTR].sh_offset = dynstr_offset;
+ section_headers[SH_DYNSTR].sh_size = dynstr_size;
+ section_headers[SH_DYNSTR].sh_link = 0;
+ section_headers[SH_DYNSTR].sh_info = 0;
+ section_headers[SH_DYNSTR].sh_addralign = dynstr_alignment;
+ section_headers[SH_DYNSTR].sh_entsize = 0;
+
+ section_headers[SH_HASH].sh_name = shstrtab_hash_offset;
+ section_headers[SH_HASH].sh_type = SHT_HASH;
+ section_headers[SH_HASH].sh_flags = SHF_ALLOC;
+ section_headers[SH_HASH].sh_addr = hash_offset;
+ section_headers[SH_HASH].sh_offset = hash_offset;
+ section_headers[SH_HASH].sh_size = hash_size;
+ section_headers[SH_HASH].sh_link = SH_DYNSYM;
+ section_headers[SH_HASH].sh_info = 0;
+ section_headers[SH_HASH].sh_addralign = hash_alignment;
+ section_headers[SH_HASH].sh_entsize = sizeof(Elf32_Word); // This is Elf32_Word even on 64-bit
+
+ section_headers[SH_RODATA].sh_name = shstrtab_rodata_offset;
+ section_headers[SH_RODATA].sh_type = SHT_PROGBITS;
+ section_headers[SH_RODATA].sh_flags = SHF_ALLOC;
+ section_headers[SH_RODATA].sh_addr = oat_data_offset;
+ section_headers[SH_RODATA].sh_offset = oat_data_offset;
+ section_headers[SH_RODATA].sh_size = oat_data_size;
+ section_headers[SH_RODATA].sh_link = 0;
+ section_headers[SH_RODATA].sh_info = 0;
+ section_headers[SH_RODATA].sh_addralign = oat_data_alignment;
+ section_headers[SH_RODATA].sh_entsize = 0;
+
+ section_headers[SH_TEXT].sh_name = shstrtab_text_offset;
+ section_headers[SH_TEXT].sh_type = SHT_PROGBITS;
+ section_headers[SH_TEXT].sh_flags = SHF_ALLOC | SHF_EXECINSTR;
+ section_headers[SH_TEXT].sh_addr = oat_exec_offset;
+ section_headers[SH_TEXT].sh_offset = oat_exec_offset;
+ section_headers[SH_TEXT].sh_size = oat_exec_size;
+ section_headers[SH_TEXT].sh_link = 0;
+ section_headers[SH_TEXT].sh_info = 0;
+ section_headers[SH_TEXT].sh_addralign = oat_exec_alignment;
+ section_headers[SH_TEXT].sh_entsize = 0;
+
+ // TODO: SHF_WRITE for .dynamic is considered processor specific, do we need it?
+ section_headers[SH_DYNAMIC].sh_name = shstrtab_dynamic_offset;
+ section_headers[SH_DYNAMIC].sh_type = SHT_DYNAMIC;
+ section_headers[SH_DYNAMIC].sh_flags = SHF_WRITE | SHF_ALLOC;
+ section_headers[SH_DYNAMIC].sh_addr = dynamic_offset;
+ section_headers[SH_DYNAMIC].sh_offset = dynamic_offset;
+ section_headers[SH_DYNAMIC].sh_size = dynamic_size;
+ section_headers[SH_DYNAMIC].sh_link = SH_DYNSTR;
+ section_headers[SH_DYNAMIC].sh_info = 0;
+ section_headers[SH_DYNAMIC].sh_addralign = dynamic_alignment;
+ section_headers[SH_DYNAMIC].sh_entsize = sizeof(Elf32_Dyn);
+
+ section_headers[SH_SHSTRTAB].sh_name = shstrtab_shstrtab_offset;
+ section_headers[SH_SHSTRTAB].sh_type = SHT_STRTAB;
+ section_headers[SH_SHSTRTAB].sh_flags = 0;
+ section_headers[SH_SHSTRTAB].sh_addr = shstrtab_offset;
+ section_headers[SH_SHSTRTAB].sh_offset = shstrtab_offset;
+ section_headers[SH_SHSTRTAB].sh_size = shstrtab_size;
+ section_headers[SH_SHSTRTAB].sh_link = 0;
+ section_headers[SH_SHSTRTAB].sh_info = 0;
+ section_headers[SH_SHSTRTAB].sh_addralign = shstrtab_alignment;
+ section_headers[SH_SHSTRTAB].sh_entsize = 0;
- // Get the dynstr string.
- std::string dynstr(dynsym_builder_.GenerateStrtab());
+ if (generateDebugInformation) {
+ section_headers[SH_DBG_INFO].sh_name = shstrtab_debug_info_offset;
+ section_headers[SH_DBG_INFO].sh_type = SHT_PROGBITS;
+ section_headers[SH_DBG_INFO].sh_flags = 0;
+ section_headers[SH_DBG_INFO].sh_addr = 0;
+ section_headers[SH_DBG_INFO].sh_offset = shdbg_info_offset;
+ section_headers[SH_DBG_INFO].sh_size = shdbg_info_size;
+ section_headers[SH_DBG_INFO].sh_link = 0;
+ section_headers[SH_DBG_INFO].sh_info = 0;
+ section_headers[SH_DBG_INFO].sh_addralign = shdbg_info_alignment;
+ section_headers[SH_DBG_INFO].sh_entsize = 0;
+
+ section_headers[SH_DBG_ABRV].sh_name = shstrtab_debug_abbrev_offset;
+ section_headers[SH_DBG_ABRV].sh_type = SHT_PROGBITS;
+ section_headers[SH_DBG_ABRV].sh_flags = 0;
+ section_headers[SH_DBG_ABRV].sh_addr = 0;
+ section_headers[SH_DBG_ABRV].sh_offset = shdbg_abbrev_offset;
+ section_headers[SH_DBG_ABRV].sh_size = shdbg_abbrev_size;
+ section_headers[SH_DBG_ABRV].sh_link = 0;
+ section_headers[SH_DBG_ABRV].sh_info = 0;
+ section_headers[SH_DBG_ABRV].sh_addralign = shdbg_abbrev_alignment;
+ section_headers[SH_DBG_ABRV].sh_entsize = 0;
+
+ section_headers[SH_DBG_FRM].sh_name = shstrtab_debug_frame_offset;
+ section_headers[SH_DBG_FRM].sh_type = SHT_PROGBITS;
+ section_headers[SH_DBG_FRM].sh_flags = 0;
+ section_headers[SH_DBG_FRM].sh_addr = 0;
+ section_headers[SH_DBG_FRM].sh_offset = shdbg_frm_offset;
+ section_headers[SH_DBG_FRM].sh_size = shdbg_frm_size;
+ section_headers[SH_DBG_FRM].sh_link = 0;
+ section_headers[SH_DBG_FRM].sh_info = 0;
+ section_headers[SH_DBG_FRM].sh_addralign = shdbg_frm_alignment;
+ section_headers[SH_DBG_FRM].sh_entsize = 0;
+
+ section_headers[SH_DBG_STR].sh_name = shstrtab_debug_str_offset;
+ section_headers[SH_DBG_STR].sh_type = SHT_PROGBITS;
+ section_headers[SH_DBG_STR].sh_flags = 0;
+ section_headers[SH_DBG_STR].sh_addr = 0;
+ section_headers[SH_DBG_STR].sh_offset = shdbg_str_offset;
+ section_headers[SH_DBG_STR].sh_size = shdbg_str_size;
+ section_headers[SH_DBG_STR].sh_link = 0;
+ section_headers[SH_DBG_STR].sh_info = 0;
+ section_headers[SH_DBG_STR].sh_addralign = shdbg_str_alignment;
+ section_headers[SH_DBG_STR].sh_entsize = 0;
+ }
+
+ // phase 3: writing file
+
+ // Elf32_Ehdr
+ if (!elf_file_->WriteFully(&elf_header, sizeof(elf_header))) {
+ PLOG(ERROR) << "Failed to write ELF header for " << elf_file_->GetPath();
+ return false;
+ }
- // Add the SONAME to the dynstr.
- uint32_t dynstr_soname_offset = dynstr.size();
- std::string file_name(elf_file_->GetPath());
- size_t directory_separator_pos = file_name.rfind('/');
- if (directory_separator_pos != std::string::npos) {
- file_name = file_name.substr(directory_separator_pos + 1);
+ // PHDR
+ if (static_cast<off_t>(phdr_offset) != lseek(elf_file_->Fd(), 0, SEEK_CUR)) {
+ PLOG(ERROR) << "Failed to be at expected ELF program header offset phdr_offset "
+ << " for " << elf_file_->GetPath();
+ return false;
}
- dynstr += file_name;
- dynstr += '\0';
- if (debug_logging_) {
- LOG(INFO) << "dynstr size (bytes) =" << dynstr.size()
- << std::hex << " " << dynstr.size();
- LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.size()
- << std::hex << " " << dynsym_builder_.size();
- }
-
- // get the strtab
- std::string strtab;
- if (IncludingDebugSymbols()) {
- strtab = symtab_builder_.GenerateStrtab();
- if (debug_logging_) {
- LOG(INFO) << "strtab size (bytes) =" << strtab.size()
- << std::hex << " " << strtab.size();
- LOG(INFO) << "symtab size (elements) =" << symtab_builder_.size()
- << std::hex << " " << symtab_builder_.size();
- }
+ if (!elf_file_->WriteFully(program_headers, sizeof(program_headers))) {
+ PLOG(ERROR) << "Failed to write ELF program headers for " << elf_file_->GetPath();
+ return false;
}
- // Get the section header string table.
- std::vector<Elf32_Shdr*> section_ptrs;
- std::string shstrtab;
- shstrtab += '\0';
-
- // Setup sym_undef
- Elf32_Shdr null_hdr;
- memset(&null_hdr, 0, sizeof(null_hdr));
- null_hdr.sh_type = SHT_NULL;
- null_hdr.sh_link = SHN_UNDEF;
- section_ptrs.push_back(&null_hdr);
-
- uint32_t section_index = 1;
-
- // setup .dynsym
- section_ptrs.push_back(&dynsym_builder_.section_);
- AssignSectionStr(&dynsym_builder_, &shstrtab);
- dynsym_builder_.section_index_ = section_index++;
-
- // Setup .dynstr
- section_ptrs.push_back(&dynsym_builder_.strtab_.section_);
- AssignSectionStr(&dynsym_builder_.strtab_, &shstrtab);
- dynsym_builder_.strtab_.section_index_ = section_index++;
-
- // Setup .hash
- section_ptrs.push_back(&hash_builder_.section_);
- AssignSectionStr(&hash_builder_, &shstrtab);
- hash_builder_.section_index_ = section_index++;
-
- // Setup .rodata
- section_ptrs.push_back(&rodata_builder_.section_);
- AssignSectionStr(&rodata_builder_, &shstrtab);
- rodata_builder_.section_index_ = section_index++;
-
- // Setup .text
- section_ptrs.push_back(&text_builder_.section_);
- AssignSectionStr(&text_builder_, &shstrtab);
- text_builder_.section_index_ = section_index++;
-
- // Setup .dynamic
- section_ptrs.push_back(&dynamic_builder_.section_);
- AssignSectionStr(&dynamic_builder_, &shstrtab);
- dynamic_builder_.section_index_ = section_index++;
-
- if (IncludingDebugSymbols()) {
- // Setup .symtab
- section_ptrs.push_back(&symtab_builder_.section_);
- AssignSectionStr(&symtab_builder_, &shstrtab);
- symtab_builder_.section_index_ = section_index++;
-
- // Setup .strtab
- section_ptrs.push_back(&symtab_builder_.strtab_.section_);
- AssignSectionStr(&symtab_builder_.strtab_, &shstrtab);
- symtab_builder_.strtab_.section_index_ = section_index++;
- }
- ElfRawSectionBuilder* it = other_builders_.data();
- for (uint32_t cnt = 0; cnt < other_builders_.size(); ++it, ++cnt) {
- // Setup all the other sections.
- section_ptrs.push_back(&it->section_);
- AssignSectionStr(it, &shstrtab);
- it->section_index_ = section_index++;
- }
-
- // Setup shstrtab
- section_ptrs.push_back(&shstrtab_builder_.section_);
- AssignSectionStr(&shstrtab_builder_, &shstrtab);
- shstrtab_builder_.section_index_ = section_index++;
-
- if (debug_logging_) {
- LOG(INFO) << ".shstrtab size (bytes) =" << shstrtab.size()
- << std::hex << " " << shstrtab.size();
- LOG(INFO) << "section list size (elements)=" << section_ptrs.size()
- << std::hex << " " << section_ptrs.size();
- }
-
- // Fill in the hash section.
- std::vector<Elf32_Word> hash = dynsym_builder_.GenerateHashContents();
-
- if (debug_logging_) {
- LOG(INFO) << ".hash size (bytes)=" << hash.size() * sizeof(Elf32_Word)
- << std::hex << " " << hash.size() * sizeof(Elf32_Word);
- }
-
- Elf32_Word base_offset = sizeof(Elf32_Ehdr) + sizeof(program_headers);
- std::vector<ElfFilePiece> pieces;
-
- // Get the layout in the sections.
- //
- // Get the layout of the dynsym section.
- dynsym_builder_.section_.sh_offset = RoundUp(base_offset, dynsym_builder_.section_.sh_addralign);
- dynsym_builder_.section_.sh_addr = dynsym_builder_.section_.sh_offset;
- dynsym_builder_.section_.sh_size = dynsym_builder_.size()*sizeof(Elf32_Sym);
- dynsym_builder_.section_.sh_link = dynsym_builder_.GetLink();
-
- // Get the layout of the dynstr section.
- dynsym_builder_.strtab_.section_.sh_offset = NextOffset(dynsym_builder_.strtab_.section_,
- dynsym_builder_.section_);
- dynsym_builder_.strtab_.section_.sh_addr = dynsym_builder_.strtab_.section_.sh_offset;
- dynsym_builder_.strtab_.section_.sh_size = dynstr.size();
- dynsym_builder_.strtab_.section_.sh_link = dynsym_builder_.strtab_.GetLink();
-
- // Get the layout of the hash section
- hash_builder_.section_.sh_offset = NextOffset(hash_builder_.section_,
- dynsym_builder_.strtab_.section_);
- hash_builder_.section_.sh_addr = hash_builder_.section_.sh_offset;
- hash_builder_.section_.sh_size = hash.size() * sizeof(Elf32_Word);
- hash_builder_.section_.sh_link = hash_builder_.GetLink();
-
- // Get the layout of the rodata section.
- rodata_builder_.section_.sh_offset = NextOffset(rodata_builder_.section_,
- hash_builder_.section_);
- rodata_builder_.section_.sh_addr = rodata_builder_.section_.sh_offset;
- rodata_builder_.section_.sh_size = rodata_builder_.size_;
- rodata_builder_.section_.sh_link = rodata_builder_.GetLink();
-
- // Get the layout of the text section.
- text_builder_.section_.sh_offset = NextOffset(text_builder_.section_, rodata_builder_.section_);
- text_builder_.section_.sh_addr = text_builder_.section_.sh_offset;
- text_builder_.section_.sh_size = text_builder_.size_;
- text_builder_.section_.sh_link = text_builder_.GetLink();
- CHECK_ALIGNED(rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size, kPageSize);
-
- // Get the layout of the dynamic section.
- dynamic_builder_.section_.sh_offset = NextOffset(dynamic_builder_.section_,
- text_builder_.section_);
- dynamic_builder_.section_.sh_addr = dynamic_builder_.section_.sh_offset;
- dynamic_builder_.section_.sh_size = dynamic_builder_.size()*sizeof(Elf32_Dyn);
- dynamic_builder_.section_.sh_link = dynamic_builder_.GetLink();
-
- Elf32_Shdr prev = dynamic_builder_.section_;
- if (IncludingDebugSymbols()) {
- // Get the layout of the symtab section.
- symtab_builder_.section_.sh_offset = NextOffset(symtab_builder_.section_,
- dynamic_builder_.section_);
- symtab_builder_.section_.sh_addr = 0;
- // Add to leave space for the null symbol.
- symtab_builder_.section_.sh_size = symtab_builder_.size()*sizeof(Elf32_Sym);
- symtab_builder_.section_.sh_link = symtab_builder_.GetLink();
-
- // Get the layout of the dynstr section.
- symtab_builder_.strtab_.section_.sh_offset = NextOffset(symtab_builder_.strtab_.section_,
- symtab_builder_.section_);
- symtab_builder_.strtab_.section_.sh_addr = 0;
- symtab_builder_.strtab_.section_.sh_size = strtab.size();
- symtab_builder_.strtab_.section_.sh_link = symtab_builder_.strtab_.GetLink();
-
- prev = symtab_builder_.strtab_.section_;
- }
- if (debug_logging_) {
- LOG(INFO) << "dynsym off=" << dynsym_builder_.section_.sh_offset
- << " dynsym size=" << dynsym_builder_.section_.sh_size;
- LOG(INFO) << "dynstr off=" << dynsym_builder_.strtab_.section_.sh_offset
- << " dynstr size=" << dynsym_builder_.strtab_.section_.sh_size;
- LOG(INFO) << "hash off=" << hash_builder_.section_.sh_offset
- << " hash size=" << hash_builder_.section_.sh_size;
- LOG(INFO) << "rodata off=" << rodata_builder_.section_.sh_offset
- << " rodata size=" << rodata_builder_.section_.sh_size;
- LOG(INFO) << "text off=" << text_builder_.section_.sh_offset
- << " text size=" << text_builder_.section_.sh_size;
- LOG(INFO) << "dynamic off=" << dynamic_builder_.section_.sh_offset
- << " dynamic size=" << dynamic_builder_.section_.sh_size;
- if (IncludingDebugSymbols()) {
- LOG(INFO) << "symtab off=" << symtab_builder_.section_.sh_offset
- << " symtab size=" << symtab_builder_.section_.sh_size;
- LOG(INFO) << "strtab off=" << symtab_builder_.strtab_.section_.sh_offset
- << " strtab size=" << symtab_builder_.strtab_.section_.sh_size;
- }
- }
- // Get the layout of the extra sections. (This will deal with the debug
- // sections if they are there)
- for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
- it->section_.sh_offset = NextOffset(it->section_, prev);
- it->section_.sh_addr = 0;
- it->section_.sh_size = it->GetBuffer()->size();
- it->section_.sh_link = it->GetLink();
- pieces.push_back(ElfFilePiece(it->name_, it->section_.sh_offset,
- it->GetBuffer()->data(), it->GetBuffer()->size()));
- prev = it->section_;
- if (debug_logging_) {
- LOG(INFO) << it->name_ << " off=" << it->section_.sh_offset
- << " " << it->name_ << " size=" << it->section_.sh_size;
- }
+ // .dynsym
+ DCHECK_LE(phdr_offset + phdr_size, dynsym_offset);
+ if (static_cast<off_t>(dynsym_offset) != lseek(elf_file_->Fd(), dynsym_offset, SEEK_SET)) {
+ PLOG(ERROR) << "Failed to seek to .dynsym offset location " << dynsym_offset
+ << " for " << elf_file_->GetPath();
+ return false;
}
- // Get the layout of the shstrtab section
- shstrtab_builder_.section_.sh_offset = NextOffset(shstrtab_builder_.section_, prev);
- shstrtab_builder_.section_.sh_addr = 0;
- shstrtab_builder_.section_.sh_size = shstrtab.size();
- shstrtab_builder_.section_.sh_link = shstrtab_builder_.GetLink();
- if (debug_logging_) {
- LOG(INFO) << "shstrtab off=" << shstrtab_builder_.section_.sh_offset
- << " shstrtab size=" << shstrtab_builder_.section_.sh_size;
- }
-
- // The section list comes after come after.
- Elf32_Word sections_offset = RoundUp(
- shstrtab_builder_.section_.sh_offset + shstrtab_builder_.section_.sh_size,
- sizeof(Elf32_Word));
-
- // Setup the actual symbol arrays.
- std::vector<Elf32_Sym> dynsym = dynsym_builder_.GenerateSymtab();
- CHECK_EQ(dynsym.size()*sizeof(Elf32_Sym), dynsym_builder_.section_.sh_size);
- std::vector<Elf32_Sym> symtab;
- if (IncludingDebugSymbols()) {
- symtab = symtab_builder_.GenerateSymtab();
- CHECK_EQ(symtab.size()*sizeof(Elf32_Sym), symtab_builder_.section_.sh_size);
- }
-
- // Setup the dynamic section.
- // This will add the 2 values we cannot know until now time, namely the size
- // and the soname_offset.
- std::vector<Elf32_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr.size(),
- dynstr_soname_offset);
- CHECK_EQ(dynamic.size()*sizeof(Elf32_Dyn), dynamic_builder_.section_.sh_size);
-
- // Finish setup of the program headers now that we know the layout of the
- // whole file.
- Elf32_Word load_r_size = rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size;
- program_headers[PH_LOAD_R__].p_filesz = load_r_size;
- program_headers[PH_LOAD_R__].p_memsz = load_r_size;
- program_headers[PH_LOAD_R__].p_align = rodata_builder_.section_.sh_addralign;
-
- Elf32_Word load_rx_size = text_builder_.section_.sh_size;
- program_headers[PH_LOAD_R_X].p_offset = text_builder_.section_.sh_offset;
- program_headers[PH_LOAD_R_X].p_vaddr = text_builder_.section_.sh_offset;
- program_headers[PH_LOAD_R_X].p_paddr = text_builder_.section_.sh_offset;
- program_headers[PH_LOAD_R_X].p_filesz = load_rx_size;
- program_headers[PH_LOAD_R_X].p_memsz = load_rx_size;
- program_headers[PH_LOAD_R_X].p_align = text_builder_.section_.sh_addralign;
-
- program_headers[PH_LOAD_RW_].p_offset = dynamic_builder_.section_.sh_offset;
- program_headers[PH_LOAD_RW_].p_vaddr = dynamic_builder_.section_.sh_offset;
- program_headers[PH_LOAD_RW_].p_paddr = dynamic_builder_.section_.sh_offset;
- program_headers[PH_LOAD_RW_].p_filesz = dynamic_builder_.section_.sh_size;
- program_headers[PH_LOAD_RW_].p_memsz = dynamic_builder_.section_.sh_size;
- program_headers[PH_LOAD_RW_].p_align = dynamic_builder_.section_.sh_addralign;
-
- program_headers[PH_DYNAMIC].p_offset = dynamic_builder_.section_.sh_offset;
- program_headers[PH_DYNAMIC].p_vaddr = dynamic_builder_.section_.sh_offset;
- program_headers[PH_DYNAMIC].p_paddr = dynamic_builder_.section_.sh_offset;
- program_headers[PH_DYNAMIC].p_filesz = dynamic_builder_.section_.sh_size;
- program_headers[PH_DYNAMIC].p_memsz = dynamic_builder_.section_.sh_size;
- program_headers[PH_DYNAMIC].p_align = dynamic_builder_.section_.sh_addralign;
-
- // Finish setup of the Ehdr values.
- elf_header_.e_phoff = phdr_offset;
- elf_header_.e_shoff = sections_offset;
- elf_header_.e_phnum = PH_NUM;
- elf_header_.e_shnum = section_ptrs.size();
- elf_header_.e_shstrndx = shstrtab_builder_.section_index_;
-
- // Add the rest of the pieces to the list.
- pieces.push_back(ElfFilePiece("Elf Header", 0, &elf_header_, sizeof(elf_header_)));
- pieces.push_back(ElfFilePiece("Program headers", phdr_offset,
- &program_headers, sizeof(program_headers)));
- pieces.push_back(ElfFilePiece(".dynamic", dynamic_builder_.section_.sh_offset,
- dynamic.data(), dynamic_builder_.section_.sh_size));
- pieces.push_back(ElfFilePiece(".dynsym", dynsym_builder_.section_.sh_offset,
- dynsym.data(), dynsym.size()*sizeof(Elf32_Sym)));
- pieces.push_back(ElfFilePiece(".dynstr", dynsym_builder_.strtab_.section_.sh_offset,
- dynstr.c_str(), dynstr.size()));
- pieces.push_back(ElfFilePiece(".hash", hash_builder_.section_.sh_offset,
- hash.data(), hash.size() * sizeof(Elf32_Word)));
- pieces.push_back(ElfFilePiece(".rodata", rodata_builder_.section_.sh_offset,
- NULL, rodata_builder_.section_.sh_size));
- pieces.push_back(ElfFilePiece(".text", text_builder_.section_.sh_offset,
- NULL, text_builder_.section_.sh_size));
- if (IncludingDebugSymbols()) {
- pieces.push_back(ElfFilePiece(".symtab", symtab_builder_.section_.sh_offset,
- symtab.data(), symtab.size() * sizeof(Elf32_Sym)));
- pieces.push_back(ElfFilePiece(".strtab", symtab_builder_.strtab_.section_.sh_offset,
- strtab.c_str(), strtab.size()));
- }
- pieces.push_back(ElfFilePiece(".shstrtab", shstrtab_builder_.section_.sh_offset,
- &shstrtab[0], shstrtab.size()));
- for (uint32_t i = 0; i < section_ptrs.size(); ++i) {
- // Just add all the sections in induvidually since they are all over the
- // place on the heap/stack.
- Elf32_Word cur_off = sections_offset + i * sizeof(Elf32_Shdr);
- pieces.push_back(ElfFilePiece("section table piece", cur_off,
- section_ptrs[i], sizeof(Elf32_Shdr)));
- }
-
- if (!WriteOutFile(pieces)) {
- LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
+ if (!elf_file_->WriteFully(dynsym, sizeof(dynsym))) {
+ PLOG(ERROR) << "Failed to write .dynsym for " << elf_file_->GetPath();
return false;
}
- // write out the actual oat file data.
- Elf32_Word oat_data_offset = rodata_builder_.section_.sh_offset;
- if (static_cast<off_t>(oat_data_offset) != lseek(elf_file_->Fd(), oat_data_offset, SEEK_SET)) {
- PLOG(ERROR) << "Failed to seek to .rodata offset " << oat_data_offset
+
+ // .dynstr
+ DCHECK_LE(dynsym_offset + dynsym_size, dynstr_offset);
+ if (static_cast<off_t>(dynstr_offset) != lseek(elf_file_->Fd(), dynstr_offset, SEEK_SET)) {
+ PLOG(ERROR) << "Failed to seek to .dynstr offset " << dynstr_offset
<< " for " << elf_file_->GetPath();
return false;
}
- std::unique_ptr<BufferedOutputStream> output_stream(
- new BufferedOutputStream(new FileOutputStream(elf_file_)));
- if (!oat_writer_->Write(output_stream.get())) {
- PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file_->GetPath();
+ if (!elf_file_->WriteFully(&dynstr[0], dynstr_size)) {
+ PLOG(ERROR) << "Failed to write .dynsym for " << elf_file_->GetPath();
return false;
}
- return true;
-}
-
-bool ElfWriterQuick::ElfBuilder::WriteOutFile(const std::vector<ElfFilePiece>& pieces) {
- // TODO It would be nice if this checked for overlap.
- for (auto it = pieces.begin(); it != pieces.end(); ++it) {
- if (it->data_) {
- if (static_cast<off_t>(it->offset_) != lseek(elf_file_->Fd(), it->offset_, SEEK_SET)) {
- PLOG(ERROR) << "Failed to seek to " << it->dbg_name_ << " offset location "
- << it->offset_ << " for " << elf_file_->GetPath();
- return false;
- }
- if (!elf_file_->WriteFully(it->data_, it->size_)) {
- PLOG(ERROR) << "Failed to write " << it->dbg_name_ << " for " << elf_file_->GetPath();
- return false;
- }
- }
+ // .hash
+ DCHECK_LE(dynstr_offset + dynstr_size, hash_offset);
+ if (static_cast<off_t>(hash_offset) != lseek(elf_file_->Fd(), hash_offset, SEEK_SET)) {
+ PLOG(ERROR) << "Failed to seek to .hash offset " << hash_offset
+ << " for " << elf_file_->GetPath();
+ return false;
}
- return true;
-}
-
-void ElfWriterQuick::ElfBuilder::SetupDynamic() {
- dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
- dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, &dynsym_builder_.strtab_);
- dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
- dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf32_Sym));
-}
-
-void ElfWriterQuick::ElfBuilder::SetupRequiredSymbols() {
- dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
- rodata_builder_.size_, STB_GLOBAL, STT_OBJECT);
- dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
- text_builder_.size_, STB_GLOBAL, STT_OBJECT);
- dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.size_ - 4,
- true, 4, STB_GLOBAL, STT_OBJECT);
-}
-
-void ElfWriterQuick::ElfDynamicBuilder::AddDynamicTag(Elf32_Sword tag, Elf32_Sword d_un) {
- if (tag == DT_NULL) {
- return;
+ if (!elf_file_->WriteFully(hash, sizeof(hash))) {
+ PLOG(ERROR) << "Failed to write .dynsym for " << elf_file_->GetPath();
+ return false;
}
- dynamics_.push_back({NULL, tag, d_un});
-}
-void ElfWriterQuick::ElfDynamicBuilder::AddDynamicTag(Elf32_Sword tag, Elf32_Sword d_un,
- ElfSectionBuilder* section) {
- if (tag == DT_NULL) {
- return;
+ // .rodata .text
+ DCHECK_LE(hash_offset + hash_size, oat_data_offset);
+ if (static_cast<off_t>(oat_data_offset) != lseek(elf_file_->Fd(), oat_data_offset, SEEK_SET)) {
+ PLOG(ERROR) << "Failed to seek to .rodata offset " << oat_data_offset
+ << " for " << elf_file_->GetPath();
+ return false;
}
- dynamics_.push_back({section, tag, d_un});
-}
-
-std::vector<Elf32_Dyn> ElfWriterQuick::ElfDynamicBuilder::GetDynamics(Elf32_Sword strsz,
- Elf32_Sword soname) {
- std::vector<Elf32_Dyn> ret;
- for (auto it = dynamics_.cbegin(); it != dynamics_.cend(); ++it) {
- if (it->section_) {
- // We are adding an address relative to a section.
- ret.push_back(
- {it->tag_, {it->off_ + static_cast<Elf32_Sword>(it->section_->section_.sh_addr)}});
- } else {
- ret.push_back({it->tag_, {it->off_}});
- }
+ std::unique_ptr<BufferedOutputStream> output_stream(new BufferedOutputStream(new FileOutputStream(elf_file_)));
+ if (!oat_writer->Write(output_stream.get())) {
+ PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file_->GetPath();
+ return false;
}
- ret.push_back({DT_STRSZ, {strsz}});
- ret.push_back({DT_SONAME, {soname}});
- ret.push_back({DT_NULL, {0}});
- return ret;
-}
-
-std::vector<Elf32_Sym> ElfWriterQuick::ElfSymtabBuilder::GenerateSymtab() {
- std::vector<Elf32_Sym> ret;
- Elf32_Sym undef_sym;
- memset(&undef_sym, 0, sizeof(undef_sym));
- undef_sym.st_shndx = SHN_UNDEF;
- ret.push_back(undef_sym);
-
- for (auto it = symbols_.cbegin(); it != symbols_.cend(); ++it) {
- Elf32_Sym sym;
- memset(&sym, 0, sizeof(sym));
- sym.st_name = it->name_idx_;
- if (it->is_relative_) {
- sym.st_value = it->addr_ + it->section_->section_.sh_offset;
- } else {
- sym.st_value = it->addr_;
- }
- sym.st_size = it->size_;
- sym.st_other = it->other_;
- sym.st_shndx = it->section_->section_index_;
- sym.st_info = it->info_;
- ret.push_back(sym);
+ // .dynamic
+ DCHECK_LE(oat_data_offset + oat_writer->GetSize(), dynamic_offset);
+ if (static_cast<off_t>(dynamic_offset) != lseek(elf_file_->Fd(), dynamic_offset, SEEK_SET)) {
+ PLOG(ERROR) << "Failed to seek to .dynamic offset " << dynamic_offset
+ << " for " << elf_file_->GetPath();
+ return false;
}
- return ret;
-}
-
-std::string ElfWriterQuick::ElfSymtabBuilder::GenerateStrtab() {
- std::string tab;
- tab += '\0';
- for (auto it = symbols_.begin(); it != symbols_.end(); ++it) {
- it->name_idx_ = tab.size();
- tab += it->name_;
- tab += '\0';
+ if (!elf_file_->WriteFully(&dynamic_headers[0], dynamic_size)) {
+ PLOG(ERROR) << "Failed to write .dynamic for " << elf_file_->GetPath();
+ return false;
}
- strtab_.section_.sh_size = tab.size();
- return tab;
-}
-void ElfWriterQuick::ElfBuilder::AssignSectionStr(
- ElfSectionBuilder* builder, std::string* strtab) {
- builder->section_.sh_name = strtab->size();
- *strtab += builder->name_;
- *strtab += '\0';
- if (debug_logging_) {
- LOG(INFO) << "adding section name \"" << builder->name_ << "\" "
- << "to shstrtab at offset " << builder->section_.sh_name;
+ // .shstrtab
+ DCHECK_LE(dynamic_offset + dynamic_size, shstrtab_offset);
+ if (static_cast<off_t>(shstrtab_offset) != lseek(elf_file_->Fd(), shstrtab_offset, SEEK_SET)) {
+ PLOG(ERROR) << "Failed to seek to .shstrtab offset " << shstrtab_offset
+ << " for " << elf_file_->GetPath();
+ return false;
}
-}
-
-// from bionic
-static unsigned elfhash(const char *_name) {
- const unsigned char *name = (const unsigned char *) _name;
- unsigned h = 0, g;
-
- while (*name) {
- h = (h << 4) + *name++;
- g = h & 0xf0000000;
- h ^= g;
- h ^= g >> 24;
+ if (!elf_file_->WriteFully(&shstrtab[0], shstrtab_size)) {
+ PLOG(ERROR) << "Failed to write .shstrtab for " << elf_file_->GetPath();
+ return false;
}
- return h;
-}
-
-std::vector<Elf32_Word> ElfWriterQuick::ElfSymtabBuilder::GenerateHashContents() {
- // Here is how The ELF hash table works.
- // There are 3 arrays to worry about.
- // * The symbol table where the symbol information is.
- // * The bucket array which is an array of indexes into the symtab and chain.
- // * The chain array which is also an array of indexes into the symtab and chain.
- //
- // Lets say the state is something like this.
- // +--------+ +--------+ +-----------+
- // | symtab | | bucket | | chain |
- // | NULL | | 1 | | STN_UNDEF |
- // | <sym1> | | 4 | | 2 |
- // | <sym2> | | | | 5 |
- // | <sym3> | | | | STN_UNDEF |
- // | <sym4> | | | | 3 |
- // | <sym5> | | | | STN_UNDEF |
- // +--------+ +--------+ +-----------+
- //
- // The lookup process (in python psudocode) is
- //
- // def GetSym(name):
- // # NB STN_UNDEF == 0
- // indx = bucket[elfhash(name) % num_buckets]
- // while indx != STN_UNDEF:
- // if GetSymbolName(symtab[indx]) == name:
- // return symtab[indx]
- // indx = chain[indx]
- // return SYMBOL_NOT_FOUND
- //
- // Between bucket and chain arrays every symtab index must be present exactly
- // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
-
- // Select number of buckets.
- // This is essentially arbitrary.
- Elf32_Word nbuckets;
- Elf32_Word chain_size = size();
- if (symbols_.size() < 8) {
- nbuckets = 2;
- } else if (symbols_.size() < 32) {
- nbuckets = 4;
- } else if (symbols_.size() < 256) {
- nbuckets = 16;
- } else {
- // Have about 32 ids per bucket.
- nbuckets = RoundUp(symbols_.size()/32, 2);
- }
- std::vector<Elf32_Word> hash;
- hash.push_back(nbuckets);
- hash.push_back(chain_size);
- uint32_t bucket_offset = hash.size();
- uint32_t chain_offset = bucket_offset + nbuckets;
- hash.resize(hash.size() + nbuckets + chain_size, 0);
-
- Elf32_Word* buckets = hash.data() + bucket_offset;
- Elf32_Word* chain = hash.data() + chain_offset;
-
- // Set up the actual hash table.
- for (Elf32_Word i = 0; i < symbols_.size(); i++) {
- // Add 1 since we need to have the null symbol that is not in the symbols
- // list.
- Elf32_Word index = i + 1;
- Elf32_Word hash_val = static_cast<Elf32_Word>(elfhash(symbols_[i].name_.c_str())) % nbuckets;
- if (buckets[hash_val] == 0) {
- buckets[hash_val] = index;
- } else {
- hash_val = buckets[hash_val];
- CHECK_LT(hash_val, chain_size);
- while (chain[hash_val] != 0) {
- hash_val = chain[hash_val];
- CHECK_LT(hash_val, chain_size);
- }
- chain[hash_val] = index;
- // Check for loops. Works because if this is non-empty then there must be
- // another cell which already contains the same symbol index as this one,
- // which means some symbol has more then one name, which isn't allowed.
- CHECK_EQ(chain[index], static_cast<Elf32_Word>(0));
+ if (generateDebugInformation) {
+ // .debug_info
+ DCHECK_LE(shstrtab_offset + shstrtab_size, shdbg_info_offset);
+ if (static_cast<off_t>(shdbg_info_offset) != lseek(elf_file_->Fd(), shdbg_info_offset, SEEK_SET)) {
+ PLOG(ERROR) << "Failed to seek to .shdbg_info offset " << shdbg_info_offset
+ << " for " << elf_file_->GetPath();
+ return false;
+ }
+ if (!elf_file_->WriteFully(&dbg_info[0], shdbg_info_size)) {
+ PLOG(ERROR) << "Failed to write .debug_info for " << elf_file_->GetPath();
+ return false;
}
- }
-
- return hash;
-}
-
-void ElfWriterQuick::ElfBuilder::SetupEhdr() {
- memset(&elf_header_, 0, sizeof(elf_header_));
- elf_header_.e_ident[EI_MAG0] = ELFMAG0;
- elf_header_.e_ident[EI_MAG1] = ELFMAG1;
- elf_header_.e_ident[EI_MAG2] = ELFMAG2;
- elf_header_.e_ident[EI_MAG3] = ELFMAG3;
- elf_header_.e_ident[EI_CLASS] = ELFCLASS32;
- elf_header_.e_ident[EI_DATA] = ELFDATA2LSB;
- elf_header_.e_ident[EI_VERSION] = EV_CURRENT;
- elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX;
- elf_header_.e_ident[EI_ABIVERSION] = 0;
- elf_header_.e_type = ET_DYN;
- elf_header_.e_version = 1;
- elf_header_.e_entry = 0;
- elf_header_.e_ehsize = sizeof(Elf32_Ehdr);
- elf_header_.e_phentsize = sizeof(Elf32_Phdr);
- elf_header_.e_shentsize = sizeof(Elf32_Shdr);
- elf_header_.e_phoff = sizeof(Elf32_Ehdr);
-}
-void ElfWriterQuick::ElfBuilder::SetISA(InstructionSet isa) {
- switch (isa) {
- case kArm:
- // Fall through.
- case kThumb2: {
- elf_header_.e_machine = EM_ARM;
- elf_header_.e_flags = EF_ARM_EABI_VER5;
- break;
+ // .debug_abbrev
+ DCHECK_LE(shdbg_info_offset + shdbg_info_size, shdbg_abbrev_offset);
+ if (static_cast<off_t>(shdbg_abbrev_offset) != lseek(elf_file_->Fd(), shdbg_abbrev_offset, SEEK_SET)) {
+ PLOG(ERROR) << "Failed to seek to .shdbg_abbrev offset " << shdbg_abbrev_offset
+ << " for " << elf_file_->GetPath();
+ return false;
}
- case kArm64: {
- elf_header_.e_machine = EM_AARCH64;
- elf_header_.e_flags = 0;
- break;
+ if (!elf_file_->WriteFully(&dbg_abbrev[0], shdbg_abbrev_size)) {
+ PLOG(ERROR) << "Failed to write .debug_abbrev for " << elf_file_->GetPath();
+ return false;
}
- case kX86: {
- elf_header_.e_machine = EM_386;
- elf_header_.e_flags = 0;
- break;
+
+ // .debug_frame
+ DCHECK_LE(shdbg_abbrev_offset + shdbg_abbrev_size, shdbg_frm_offset);
+ if (static_cast<off_t>(shdbg_frm_offset) != lseek(elf_file_->Fd(), shdbg_frm_offset, SEEK_SET)) {
+ PLOG(ERROR) << "Failed to seek to .shdbg_frm offset " << shdbg_frm_offset
+ << " for " << elf_file_->GetPath();
+ return false;
}
- case kX86_64: {
- elf_header_.e_machine = EM_X86_64;
- elf_header_.e_flags = 0;
- break;
+ if (!elf_file_->WriteFully(&((*compiler_driver_->GetCallFrameInformation())[0]), shdbg_frm_size)) {
+ PLOG(ERROR) << "Failed to write .debug_frame for " << elf_file_->GetPath();
+ return false;
}
- case kMips: {
- elf_header_.e_machine = EM_MIPS;
- elf_header_.e_flags = (EF_MIPS_NOREORDER |
- EF_MIPS_PIC |
- EF_MIPS_CPIC |
- EF_MIPS_ABI_O32 |
- EF_MIPS_ARCH_32R2);
- break;
+
+ // .debug_str
+ DCHECK_LE(shdbg_frm_offset + shdbg_frm_size, shdbg_str_offset);
+ if (static_cast<off_t>(shdbg_str_offset) != lseek(elf_file_->Fd(), shdbg_str_offset, SEEK_SET)) {
+ PLOG(ERROR) << "Failed to seek to .shdbg_str offset " << shdbg_str_offset
+ << " for " << elf_file_->GetPath();
+ return false;
}
- default: {
- fatal_error_ = true;
- LOG(FATAL) << "Unknown instruction set: " << isa;
- break;
+ if (!elf_file_->WriteFully(&dbg_str[0], shdbg_str_size)) {
+ PLOG(ERROR) << "Failed to write .debug_frame for " << elf_file_->GetPath();
+ return false;
}
}
-}
-
-void ElfWriterQuick::ElfSymtabBuilder::AddSymbol(
- const std::string& name, const ElfSectionBuilder* section, Elf32_Addr addr,
- bool is_relative, Elf32_Word size, uint8_t binding, uint8_t type, uint8_t other) {
- CHECK(section);
- ElfSymtabBuilder::ElfSymbolState state {name, section, addr, size, is_relative,
- MakeStInfo(binding, type), other, 0};
- symbols_.push_back(state);
-}
-bool ElfWriterQuick::Create(File* elf_file,
- OatWriter* oat_writer,
- const std::vector<const DexFile*>& dex_files,
- const std::string& android_root,
- bool is_host,
- const CompilerDriver& driver) {
- ElfWriterQuick elf_writer(driver, elf_file);
- return elf_writer.Write(oat_writer, dex_files, android_root, is_host);
-}
-
-bool ElfWriterQuick::Write(OatWriter* oat_writer,
- const std::vector<const DexFile*>& dex_files_unused,
- const std::string& android_root_unused,
- bool is_host_unused) {
- const bool debug = false;
- const OatHeader& oat_header = oat_writer->GetOatHeader();
- Elf32_Word oat_data_size = oat_header.GetExecutableOffset();
- uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size;
-
- ElfBuilder builder(oat_writer, elf_file_, compiler_driver_->GetInstructionSet(), 0,
- oat_data_size, oat_data_size, oat_exec_size, false, debug);
-
- bool generateDebugInformation = compiler_driver_->GetCallFrameInformation() != nullptr;
+ // section headers (after all sections)
if (generateDebugInformation) {
- ElfRawSectionBuilder debug_info(".debug_info", SHT_PROGBITS, 0, NULL, 0, 1, 0);
- ElfRawSectionBuilder debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, NULL, 0, 1, 0);
- ElfRawSectionBuilder debug_str(".debug_str", SHT_PROGBITS, 0, NULL, 0, 1, 0);
- ElfRawSectionBuilder debug_frame(".debug_frame", SHT_PROGBITS, 0, NULL, 0, 4, 0);
- debug_frame.SetBuffer(*compiler_driver_->GetCallFrameInformation());
-
- FillInCFIInformation(oat_writer, debug_info.GetBuffer(),
- debug_abbrev.GetBuffer(), debug_str.GetBuffer());
- builder.RegisterRawSection(debug_info);
- builder.RegisterRawSection(debug_abbrev);
- builder.RegisterRawSection(debug_frame);
- builder.RegisterRawSection(debug_str);
+ DCHECK_LE(shdbg_str_offset + shdbg_str_size, shdr_offset);
+ } else {
+ DCHECK_LE(shstrtab_offset + shstrtab_size, shdr_offset);
+ }
+ if (static_cast<off_t>(shdr_offset) != lseek(elf_file_->Fd(), shdr_offset, SEEK_SET)) {
+ PLOG(ERROR) << "Failed to seek to ELF section headers offset " << shdr_offset
+ << " for " << elf_file_->GetPath();
+ return false;
+ }
+ if (!elf_file_->WriteFully(section_headers, sizeof(section_headers))) {
+ PLOG(ERROR) << "Failed to write ELF section headers for " << elf_file_->GetPath();
+ return false;
}
- return builder.Write();
-}
+ VLOG(compiler) << "ELF file written successfully: " << elf_file_->GetPath();
+ return true;
+} // NOLINT(readability/fn_size)
static void UpdateWord(std::vector<uint8_t>*buf, int offset, int data) {
(*buf)[offset+0] = data;
diff --git a/compiler/elf_writer_quick.h b/compiler/elf_writer_quick.h
index fe7ce18736..dec75dc83f 100644
--- a/compiler/elf_writer_quick.h
+++ b/compiler/elf_writer_quick.h
@@ -17,9 +17,7 @@
#ifndef ART_COMPILER_ELF_WRITER_QUICK_H_
#define ART_COMPILER_ELF_WRITER_QUICK_H_
-#include "elf_utils.h"
#include "elf_writer.h"
-#include "instruction_set.h"
namespace art {
@@ -47,265 +45,6 @@ class ElfWriterQuick FINAL : public ElfWriter {
: ElfWriter(driver, elf_file) {}
~ElfWriterQuick() {}
- class ElfBuilder;
- class ElfSectionBuilder {
- public:
- ElfSectionBuilder(const std::string& sec_name, Elf32_Word type, Elf32_Word flags,
- const ElfSectionBuilder *link, Elf32_Word info, Elf32_Word align,
- Elf32_Word entsize)
- : name_(sec_name), link_(link) {
- memset(&section_, 0, sizeof(section_));
- section_.sh_type = type;
- section_.sh_flags = flags;
- section_.sh_info = info;
- section_.sh_addralign = align;
- section_.sh_entsize = entsize;
- }
-
- virtual ~ElfSectionBuilder() {}
-
- Elf32_Shdr section_;
- Elf32_Word section_index_ = 0;
-
- protected:
- const std::string name_;
- const ElfSectionBuilder* link_;
-
- Elf32_Word GetLink() {
- return (link_) ? link_->section_index_ : 0;
- }
-
- private:
- friend class ElfBuilder;
- };
-
- class ElfDynamicBuilder : public ElfSectionBuilder {
- public:
- void AddDynamicTag(Elf32_Sword tag, Elf32_Sword d_un);
- void AddDynamicTag(Elf32_Sword tag, Elf32_Sword offset, ElfSectionBuilder* section);
-
- ElfDynamicBuilder(const std::string& sec_name, ElfSectionBuilder *link)
- : ElfSectionBuilder(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC, link,
- 0, kPageSize, sizeof(Elf32_Dyn)) {}
- ~ElfDynamicBuilder() {}
-
- protected:
- struct ElfDynamicState {
- ElfSectionBuilder* section_;
- Elf32_Sword tag_;
- Elf32_Sword off_;
- };
- std::vector<ElfDynamicState> dynamics_;
- Elf32_Word size() {
- // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of
- // these must be added when we actually put the file together because
- // their values are very dependent on state.
- return dynamics_.size() + 3;
- }
-
- // Create the actual dynamic vector. strsz should be the size of the .dynstr
- // table and soname_off should be the offset of the soname in .dynstr.
- // Since niether can be found prior to final layout we will wait until here
- // to add them.
- std::vector<Elf32_Dyn> GetDynamics(Elf32_Sword strsz, Elf32_Sword soname_off);
-
- private:
- friend class ElfBuilder;
- };
-
- class ElfRawSectionBuilder : public ElfSectionBuilder {
- public:
- ElfRawSectionBuilder(const std::string& sec_name, Elf32_Word type, Elf32_Word flags,
- const ElfSectionBuilder* link, Elf32_Word info, Elf32_Word align,
- Elf32_Word entsize)
- : ElfSectionBuilder(sec_name, type, flags, link, info, align, entsize) {}
- ~ElfRawSectionBuilder() {}
- std::vector<uint8_t>* GetBuffer() { return &buf_; }
- void SetBuffer(std::vector<uint8_t> buf) { buf_ = buf; }
-
- protected:
- std::vector<uint8_t> buf_;
-
- private:
- friend class ElfBuilder;
- };
-
- class ElfOatSectionBuilder : public ElfSectionBuilder {
- public:
- ElfOatSectionBuilder(const std::string& sec_name, Elf32_Word size, Elf32_Word offset,
- Elf32_Word type, Elf32_Word flags)
- : ElfSectionBuilder(sec_name, type, flags, NULL, 0, kPageSize, 0),
- offset_(offset), size_(size) {}
- ~ElfOatSectionBuilder() {}
-
- protected:
- // Offset of the content within the file.
- Elf32_Word offset_;
- // Size of the content within the file.
- Elf32_Word size_;
-
- private:
- friend class ElfBuilder;
- };
-
- class ElfSymtabBuilder : public ElfSectionBuilder {
- public:
- // Add a symbol with given name to this symtab. The symbol refers to
- // 'relative_addr' within the given section and has the given attributes.
- void AddSymbol(const std::string& name,
- const ElfSectionBuilder* section,
- Elf32_Addr addr,
- bool is_relative,
- Elf32_Word size,
- uint8_t binding,
- uint8_t type,
- uint8_t other = 0);
-
- ElfSymtabBuilder(const std::string& sec_name, Elf32_Word type,
- const std::string& str_name, Elf32_Word str_type, bool alloc)
- : ElfSectionBuilder(sec_name, type, ((alloc)?SHF_ALLOC:0), &strtab_, 0,
- sizeof(Elf32_Word), sizeof(Elf32_Sym)),
- str_name_(str_name), str_type_(str_type),
- strtab_(str_name, str_type, ((alloc) ? SHF_ALLOC : 0), NULL, 0, 1, 1) {}
- ~ElfSymtabBuilder() {}
-
- protected:
- std::vector<Elf32_Word> GenerateHashContents();
- std::string GenerateStrtab();
- std::vector<Elf32_Sym> GenerateSymtab();
-
- Elf32_Word size() {
- // 1 is for the implicit NULL symbol.
- return symbols_.size() + 1;
- }
-
- struct ElfSymbolState {
- const std::string name_;
- const ElfSectionBuilder* section_;
- Elf32_Addr addr_;
- Elf32_Word size_;
- bool is_relative_;
- uint8_t info_;
- uint8_t other_;
- // Used during Write() to temporarially hold name index in the strtab.
- Elf32_Word name_idx_;
- };
-
- // Information for the strsym for dynstr sections.
- const std::string str_name_;
- Elf32_Word str_type_;
- // The symbols in the same order they will be in the symbol table.
- std::vector<ElfSymbolState> symbols_;
- ElfSectionBuilder strtab_;
-
- private:
- friend class ElfBuilder;
- };
-
- class ElfBuilder FINAL {
- public:
- ElfBuilder(OatWriter* oat_writer,
- File* elf_file,
- InstructionSet isa,
- Elf32_Word rodata_relative_offset,
- Elf32_Word rodata_size,
- Elf32_Word text_relative_offset,
- Elf32_Word text_size,
- const bool add_symbols,
- bool debug = false)
- : oat_writer_(oat_writer),
- elf_file_(elf_file),
- add_symbols_(add_symbols),
- debug_logging_(debug),
- text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS,
- SHF_ALLOC | SHF_EXECINSTR),
- rodata_builder_(".rodata", rodata_size, rodata_relative_offset,
- SHT_PROGBITS, SHF_ALLOC),
- dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true),
- symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false),
- hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0,
- sizeof(Elf32_Word), sizeof(Elf32_Word)),
- dynamic_builder_(".dynamic", &dynsym_builder_),
- shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, NULL, 0, 1, 1) {
- SetupEhdr();
- SetupDynamic();
- SetupRequiredSymbols();
- SetISA(isa);
- }
- ~ElfBuilder() {}
-
- bool Write();
- ElfSymtabBuilder* GetDefaultDynsymBuilder() { return &dynsym_builder_; }
-
- // Adds the given raw section to the builder. This will copy it. The caller
- // is responsible for deallocating their copy.
- void RegisterRawSection(ElfRawSectionBuilder bld) {
- other_builders_.push_back(bld);
- }
-
- private:
- OatWriter* oat_writer_;
- File* elf_file_;
- const bool add_symbols_;
- const bool debug_logging_;
-
- bool fatal_error_ = false;
-
- Elf32_Ehdr elf_header_;
-
- public:
- ElfOatSectionBuilder text_builder_;
- ElfOatSectionBuilder rodata_builder_;
- ElfSymtabBuilder dynsym_builder_;
- ElfSymtabBuilder symtab_builder_;
- ElfSectionBuilder hash_builder_;
- ElfDynamicBuilder dynamic_builder_;
- ElfSectionBuilder shstrtab_builder_;
- std::vector<ElfRawSectionBuilder> other_builders_;
-
- private:
- void SetISA(InstructionSet isa);
- void SetupEhdr();
-
- // Sets up a bunch of the required Dynamic Section entries.
- // Namely it will initialize all the mandatory ones that it can.
- // Specifically:
- // DT_HASH
- // DT_STRTAB
- // DT_SYMTAB
- // DT_SYMENT
- //
- // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
- void SetupDynamic();
-
- // Sets up the basic dynamic symbols that are needed, namely all those we
- // can know already.
- //
- // Specifically adds:
- // oatdata
- // oatexec
- // oatlastword
- void SetupRequiredSymbols();
- void AssignSectionStr(ElfSectionBuilder *builder, std::string* strtab);
- struct ElfFilePiece {
- ElfFilePiece(const std::string& name, Elf32_Word offset, const void* data, Elf32_Word size)
- : dbg_name_(name), offset_(offset), data_(data), size_(size) {}
- ~ElfFilePiece() {}
-
- const std::string& dbg_name_;
- Elf32_Word offset_;
- const void *data_;
- Elf32_Word size_;
- static bool Compare(ElfFilePiece a, ElfFilePiece b) {
- return a.offset_ < b.offset_;
- }
- };
-
- // Write each of the pieces out to the file.
- bool WriteOutFile(const std::vector<ElfFilePiece>& pieces);
- bool IncludingDebugSymbols() { return add_symbols_ && symtab_builder_.size() > 1; }
- };
-
/*
* @brief Generate the DWARF debug_info and debug_abbrev sections
* @param oat_writer The Oat file Writer.