Revert "Revert "Rewrite ElfWriterQuick to make it more modular.""
This reverts commit 35f72251e722cad03a08e8ceacbd5c244eab5c29.
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 09f2eae..f2a4e95 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -29,21 +29,16 @@
namespace art {
-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);
+static constexpr Elf32_Word NextOffset(const Elf32_Shdr& cur, const Elf32_Shdr& prev) {
+ return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign);
}
-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;
+static uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
+ return ((binding) << 4) + ((type) & 0xf);
+}
+
+bool ElfWriterQuick::ElfBuilder::Write() {
+ // The basic layout of the elf file. Order may be different in final output.
// +-------------------------+
// | Elf32_Ehdr |
// +-------------------------+
@@ -67,12 +62,14 @@
// | boot.oat\0 |
// +-------------------------+
// | .hash |
- // | 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|
+ // | 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] |
// +-------------------------+
// | .rodata |
// | oatdata..oatexec-4 |
@@ -88,6 +85,12 @@
// | 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 |
@@ -98,7 +101,20 @@
// | .rodata\0 |
// | .text\0 |
// | .shstrtab\0 |
- // | .debug_frame\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)
// +-------------------------+
// | Elf32_Shdr NULL |
// | Elf32_Shdr .dynsym |
@@ -108,20 +124,20 @@
// | Elf32_Shdr .rodata |
// | Elf32_Shdr .dynamic |
// | Elf32_Shdr .shstrtab |
+ // | Elf32_Shdr .debug_str | (Optional)
// | Elf32_Shdr .debug_info | (Optional)
- // | Elf32_Shdr .debug_abbrev| (Optional)
// | Elf32_Shdr .debug_frame | (Optional)
+ // | Elf32_Shdr .debug_abbrev| (Optional)
// +-------------------------+
- // phase 1: computing offsets
- uint32_t expected_offset = 0;
- // Elf32_Ehdr
- expected_offset += sizeof(Elf32_Ehdr);
+ if (fatal_error_) {
+ return false;
+ }
+ // Step 1. Figure out all the offsets.
- // PHDR
- uint32_t phdr_alignment = sizeof(Elf32_Word);
- uint32_t phdr_offset = expected_offset;
+ // What phdr is.
+ uint32_t phdr_offset = sizeof(Elf32_Ehdr);
const uint8_t PH_PHDR = 0;
const uint8_t PH_LOAD_R__ = 1;
const uint8_t PH_LOAD_R_X = 2;
@@ -129,41 +145,40 @@
const uint8_t PH_DYNAMIC = 4;
const uint8_t PH_NUM = 5;
uint32_t phdr_size = sizeof(Elf32_Phdr) * PH_NUM;
- expected_offset += phdr_size;
- if (debug) {
+ if (debug_logging_) {
LOG(INFO) << "phdr_offset=" << phdr_offset << std::hex << " " << phdr_offset;
LOG(INFO) << "phdr_size=" << phdr_size << std::hex << " " << phdr_size;
}
+ 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;
+ program_headers[PH_PHDR].p_paddr = phdr_offset;
+ 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);
- // .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;
- }
+ 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_flags = PF_R;
- // .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';
+ program_headers[PH_LOAD_R_X].p_type = PT_LOAD;
+ program_headers[PH_LOAD_R_X].p_flags = PF_R | PF_X;
+
+ program_headers[PH_LOAD_RW_].p_type = PT_LOAD;
+ program_headers[PH_LOAD_RW_].p_flags = PF_R | PF_W;
+
+ program_headers[PH_DYNAMIC].p_type = PT_DYNAMIC;
+ program_headers[PH_DYNAMIC].p_flags = PF_R | PF_W;
+
+ // Get the dynstr string.
+ std::string dynstr(dynsym_builder_.GenerateStrtab());
+
+ // 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('/');
@@ -172,672 +187,651 @@
}
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;
+ 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();
}
- // .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;
+ // 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();
+ }
}
- // .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);
+ // Get the section header string table.
+ std::vector<Elf32_Shdr*> section_ptrs;
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;
+
+ // 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++;
}
- // 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);
+ // 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();
}
- 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;
+ // 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);
}
- 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;
+ 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_;
}
-
- 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;
+ 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;
}
}
- 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;
- program_headers[PH_PHDR].p_paddr = phdr_offset;
- 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 = 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(§ion_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;
-
- 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;
+ // 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;
+ }
+ }
+ // 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;
}
- // phase 3: writing file
+ // 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));
- // Elf32_Ehdr
- if (!elf_file_->WriteFully(&elf_header, sizeof(elf_header))) {
- PLOG(ERROR) << "Failed to write ELF header for " << elf_file_->GetPath();
+ // 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();
return false;
}
-
- // 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;
- }
- if (!elf_file_->WriteFully(program_headers, sizeof(program_headers))) {
- PLOG(ERROR) << "Failed to write ELF program headers for " << elf_file_->GetPath();
- return false;
- }
-
- // .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;
- }
- if (!elf_file_->WriteFully(dynsym, sizeof(dynsym))) {
- PLOG(ERROR) << "Failed to write .dynsym for " << elf_file_->GetPath();
- return false;
- }
-
- // .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;
- }
- if (!elf_file_->WriteFully(&dynstr[0], dynstr_size)) {
- PLOG(ERROR) << "Failed to write .dynsym 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;
- }
- if (!elf_file_->WriteFully(hash, sizeof(hash))) {
- PLOG(ERROR) << "Failed to write .dynsym for " << elf_file_->GetPath();
- return false;
- }
-
- // .rodata .text
- DCHECK_LE(hash_offset + hash_size, oat_data_offset);
+ // 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
<< " 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())) {
+ 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;
}
- // .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;
- }
- if (!elf_file_->WriteFully(&dynamic_headers[0], dynamic_size)) {
- PLOG(ERROR) << "Failed to write .dynamic for " << elf_file_->GetPath();
- return false;
- }
-
- // .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;
- }
- if (!elf_file_->WriteFully(&shstrtab[0], shstrtab_size)) {
- PLOG(ERROR) << "Failed to write .shstrtab for " << elf_file_->GetPath();
- return false;
- }
-
- 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;
- }
-
- // .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;
- }
- if (!elf_file_->WriteFully(&dbg_abbrev[0], shdbg_abbrev_size)) {
- PLOG(ERROR) << "Failed to write .debug_abbrev for " << elf_file_->GetPath();
- return false;
- }
-
- // .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;
- }
- if (!elf_file_->WriteFully(&((*compiler_driver_->GetCallFrameInformation())[0]), shdbg_frm_size)) {
- PLOG(ERROR) << "Failed to write .debug_frame for " << elf_file_->GetPath();
- return false;
- }
-
- // .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;
- }
- if (!elf_file_->WriteFully(&dbg_str[0], shdbg_str_size)) {
- PLOG(ERROR) << "Failed to write .debug_frame for " << elf_file_->GetPath();
- return false;
- }
- }
-
- // section headers (after all sections)
- if (generateDebugInformation) {
- 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;
- }
-
- VLOG(compiler) << "ELF file written successfully: " << elf_file_->GetPath();
return true;
-} // NOLINT(readability/fn_size)
+}
+
+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;
+ }
+ }
+ }
+ 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;
+ }
+ 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;
+ }
+ 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_}});
+ }
+ }
+ 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);
+ }
+ 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';
+ }
+ 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;
+ }
+}
+
+// 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;
+ }
+ 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));
+ }
+ }
+
+ 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;
+ }
+ 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: {
+ fatal_error_ = true;
+ LOG(FATAL) << "Unknown instruction set: " << isa;
+ break;
+ }
+ }
+}
+
+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;
+ 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);
+ }
+
+ return builder.Write();
+}
static void UpdateWord(std::vector<uint8_t>*buf, int offset, int data) {
(*buf)[offset+0] = data;