diff options
Diffstat (limited to 'compiler/elf_builder.h')
-rw-r--r-- | compiler/elf_builder.h | 133 |
1 files changed, 99 insertions, 34 deletions
diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h index 124ed03c21..323c933ab1 100644 --- a/compiler/elf_builder.h +++ b/compiler/elf_builder.h @@ -584,11 +584,12 @@ class ElfBuilder FINAL { // | Elf_Ehdr | // +-------------------------+ // | Elf_Phdr PHDR | - // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .rodata + // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .eh_frame .eh_frame_hdr .rodata // | Elf_Phdr LOAD R X | .text // | Elf_Phdr LOAD RW | .bss (Optional) // | Elf_Phdr LOAD RW | .dynamic // | Elf_Phdr DYNAMIC | .dynamic + // | Elf_Phdr EH_FRAME R | .eh_frame_hdr // +-------------------------+ // | .dynsym | // | Elf_Sym STN_UNDEF | @@ -615,6 +616,10 @@ class ElfBuilder FINAL { // | ... | // | Elf_Word chain[c - 1] | // +-------------------------+ + // | .eh_frame | (Optional) + // +-------------------------+ + // | .eh_frame_hdr | (Optional) + // +-------------------------+ // | .rodata | // | oatdata..oatexec-4 | // +-------------------------+ @@ -648,22 +653,21 @@ class ElfBuilder FINAL { // | .shstrtab\0 | // | .symtab\0 | (Optional) // | .strtab\0 | (Optional) - // | .debug_str\0 | (Optional) - // | .debug_info\0 | (Optional) // | .eh_frame\0 | (Optional) - // | .debug_line\0 | (Optional) + // | .eh_frame_hdr\0 | (Optional) + // | .debug_info\0 | (Optional) // | .debug_abbrev\0 | (Optional) + // | .debug_str\0 | (Optional) + // | .debug_line\0 | (Optional) // +-------------------------+ (Optional) // | .debug_info | (Optional) // +-------------------------+ (Optional) // | .debug_abbrev | (Optional) // +-------------------------+ (Optional) - // | .eh_frame | (Optional) + // | .debug_str | (Optional) // +-------------------------+ (Optional) // | .debug_line | (Optional) // +-------------------------+ (Optional) - // | .debug_str | (Optional) - // +-------------------------+ (Optional) // | Elf_Shdr NULL | // | Elf_Shdr .dynsym | // | Elf_Shdr .dynstr | @@ -673,11 +677,12 @@ class ElfBuilder FINAL { // | Elf_Shdr .bss | (Optional) // | Elf_Shdr .dynamic | // | Elf_Shdr .shstrtab | + // | Elf_Shdr .eh_frame | (Optional) + // | Elf_Shdr .eh_frame_hdr | (Optional) // | Elf_Shdr .debug_info | (Optional) // | Elf_Shdr .debug_abbrev | (Optional) - // | Elf_Shdr .eh_frame | (Optional) - // | Elf_Shdr .debug_line | (Optional) // | Elf_Shdr .debug_str | (Optional) + // | Elf_Shdr .debug_line | (Optional) // +-------------------------+ if (fatal_error_) { @@ -718,6 +723,9 @@ class ElfBuilder FINAL { program_headers_[PH_DYNAMIC].p_type = PT_DYNAMIC; program_headers_[PH_DYNAMIC].p_flags = PF_R | PF_W; + program_headers_[PH_EH_FRAME_HDR].p_type = PT_NULL; + program_headers_[PH_EH_FRAME_HDR].p_flags = PF_R; + // Get the dynstr string. dynstr_ = dynsym_builder_.GenerateStrtab(); @@ -828,10 +836,37 @@ class ElfBuilder FINAL { hash_builder_.GetSection()->sh_size = hash_.size() * sizeof(Elf_Word); hash_builder_.GetSection()->sh_link = hash_builder_.GetLink(); + // Get the layout of the extra sections with SHF_ALLOC flag. + // This will deal with .eh_frame and .eh_frame_hdr. + // .eh_frame contains relative pointers to .text which we + // want to fixup between the calls to Init() and Write(). + // Therefore we handle those sections here as opposed to Write(). + // It also has the nice side effect of including .eh_frame + // with the rest of LOAD_R segment. It must come before .rodata + // because .rodata and .text must be next to each other. + Elf_Shdr* prev = hash_builder_.GetSection(); + for (auto* it : other_builders_) { + if ((it->GetSection()->sh_flags & SHF_ALLOC) != 0) { + it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev); + it->GetSection()->sh_addr = it->GetSection()->sh_offset; + it->GetSection()->sh_size = it->GetBuffer()->size(); + it->GetSection()->sh_link = it->GetLink(); + prev = it->GetSection(); + } + } + // If the sections exist, check that they have been handled. + const auto* eh_frame = FindRawSection(".eh_frame"); + if (eh_frame != nullptr) { + DCHECK_NE(eh_frame->GetSection()->sh_offset, 0u); + } + const auto* eh_frame_hdr = FindRawSection(".eh_frame_hdr"); + if (eh_frame_hdr != nullptr) { + DCHECK_NE(eh_frame_hdr->GetSection()->sh_offset, 0u); + } + // Get the layout of the rodata section. rodata_builder_.GetSection()->sh_offset = - NextOffset<Elf_Word, Elf_Shdr>(*rodata_builder_.GetSection(), - *hash_builder_.GetSection()); + NextOffset<Elf_Word, Elf_Shdr>(*rodata_builder_.GetSection(), *prev); rodata_builder_.GetSection()->sh_addr = rodata_builder_.GetSection()->sh_offset; rodata_builder_.GetSection()->sh_size = rodata_builder_.GetSize(); rodata_builder_.GetSection()->sh_link = rodata_builder_.GetLink(); @@ -909,9 +944,7 @@ class ElfBuilder FINAL { } // Setup all the other sections. - for (ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *builder = other_builders_.data(), - *end = builder + other_builders_.size(); - builder != end; ++builder) { + for (auto* builder : other_builders_) { section_ptrs_.push_back(builder->GetSection()); AssignSectionStr(builder, &shstrtab_); builder->SetSectionIndex(section_index_); @@ -958,20 +991,22 @@ class ElfBuilder FINAL { } } - // 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->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev); - it->GetSection()->sh_addr = 0; - it->GetSection()->sh_size = it->GetBuffer()->size(); - it->GetSection()->sh_link = it->GetLink(); - - // We postpone adding an ElfFilePiece to keep the order in "pieces." - - prev = it->GetSection(); - if (debug_logging_) { - LOG(INFO) << it->GetName() << " off=" << it->GetSection()->sh_offset - << " size=" << it->GetSection()->sh_size; + // Get the layout of the extra sections without SHF_ALLOC flag. + // (This will deal with the debug sections if they are there) + for (auto* it : other_builders_) { + if ((it->GetSection()->sh_flags & SHF_ALLOC) == 0) { + it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev); + it->GetSection()->sh_addr = 0; + it->GetSection()->sh_size = it->GetBuffer()->size(); + it->GetSection()->sh_link = it->GetLink(); + + // We postpone adding an ElfFilePiece to keep the order in "pieces." + + prev = it->GetSection(); + if (debug_logging_) { + LOG(INFO) << it->GetName() << " off=" << it->GetSection()->sh_offset + << " size=" << it->GetSection()->sh_size; + } } } @@ -1044,6 +1079,26 @@ class ElfBuilder FINAL { program_headers_[PH_DYNAMIC].p_memsz = dynamic_builder_.GetSection()->sh_size; program_headers_[PH_DYNAMIC].p_align = dynamic_builder_.GetSection()->sh_addralign; + const auto* eh_frame_hdr = FindRawSection(".eh_frame_hdr"); + if (eh_frame_hdr != nullptr) { + const auto* eh_frame = FindRawSection(".eh_frame"); + // Check layout: + // 1) eh_frame is before eh_frame_hdr. + // 2) There's no gap. + CHECK(eh_frame != nullptr); + CHECK_LE(eh_frame->GetSection()->sh_offset, eh_frame_hdr->GetSection()->sh_offset); + CHECK_EQ(eh_frame->GetSection()->sh_offset + eh_frame->GetSection()->sh_size, + eh_frame_hdr->GetSection()->sh_offset); + + program_headers_[PH_EH_FRAME_HDR].p_type = PT_GNU_EH_FRAME; + program_headers_[PH_EH_FRAME_HDR].p_offset = eh_frame_hdr->GetSection()->sh_offset; + program_headers_[PH_EH_FRAME_HDR].p_vaddr = eh_frame_hdr->GetSection()->sh_addr; + program_headers_[PH_EH_FRAME_HDR].p_paddr = eh_frame_hdr->GetSection()->sh_addr; + program_headers_[PH_EH_FRAME_HDR].p_filesz = eh_frame_hdr->GetSection()->sh_size; + program_headers_[PH_EH_FRAME_HDR].p_memsz = eh_frame_hdr->GetSection()->sh_size; + program_headers_[PH_EH_FRAME_HDR].p_align = eh_frame_hdr->GetSection()->sh_addralign; + } + // Finish setup of the Ehdr values. elf_header_.e_phoff = PHDR_OFFSET; elf_header_.e_shoff = sections_offset; @@ -1108,7 +1163,7 @@ class ElfBuilder FINAL { } // Postponed debug info. - for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) { + for (auto* it : other_builders_) { pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(it->GetName(), it->GetSection()->sh_offset, it->GetBuffer()->data(), it->GetBuffer()->size())); @@ -1125,12 +1180,21 @@ class ElfBuilder FINAL { return true; } - // Adds the given raw section to the builder. This will copy it. The caller - // is responsible for deallocating their copy. - void RegisterRawSection(ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> bld) { + // Adds the given raw section to the builder. It does not take ownership. + void RegisterRawSection(ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* bld) { other_builders_.push_back(bld); } + const ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* + FindRawSection(const char* name) { + for (const auto* other_builder : other_builders_) { + if (other_builder->GetName() == name) { + return other_builder; + } + } + return nullptr; + } + private: void SetISA(InstructionSet isa) { switch (isa) { @@ -1282,7 +1346,8 @@ class ElfBuilder FINAL { PH_LOAD_RW_BSS = 3, PH_LOAD_RW_DYNAMIC = 4, PH_DYNAMIC = 5, - PH_NUM = 6, + PH_EH_FRAME_HDR = 6, + PH_NUM = 7, }; static const uint32_t PHDR_SIZE = sizeof(Elf_Phdr) * PH_NUM; Elf_Phdr program_headers_[PH_NUM]; @@ -1306,7 +1371,7 @@ class ElfBuilder FINAL { ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> hash_builder_; ElfDynamicBuilder<Elf_Word, Elf_Sword, Elf_Dyn, Elf_Shdr> dynamic_builder_; ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> shstrtab_builder_; - std::vector<ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>> other_builders_; + std::vector<ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>*> other_builders_; DISALLOW_COPY_AND_ASSIGN(ElfBuilder); }; |