diff options
author | Rui Ueyama <ruiu@google.com> | 2015-04-14 19:48:57 +0000 |
---|---|---|
committer | Rui Ueyama <ruiu@google.com> | 2015-04-14 19:48:57 +0000 |
commit | 06f70a087ba765ad0d1d38e87a416ab957498af8 (patch) | |
tree | 53c6fe3dcaf3970a1aafa8d8d22b2875bf488f02 | |
parent | befc11e007911ed63bb72e13c5f2240d68f4e39a (diff) | |
download | bcm5719-llvm-06f70a087ba765ad0d1d38e87a416ab957498af8.tar.gz bcm5719-llvm-06f70a087ba765ad0d1d38e87a416ab957498af8.zip |
ELF: Split HeaderChunks.h to HeaderChunks.{h,cpp}.
llvm-svn: 234932
-rw-r--r-- | lld/lib/ReaderWriter/ELF/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/HeaderChunks.cpp | 205 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/HeaderChunks.h | 188 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp | 1 |
4 files changed, 216 insertions, 179 deletions
diff --git a/lld/lib/ReaderWriter/ELF/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/CMakeLists.txt index 3d28cc75719..59184293de9 100644 --- a/lld/lib/ReaderWriter/ELF/CMakeLists.txt +++ b/lld/lib/ReaderWriter/ELF/CMakeLists.txt @@ -3,6 +3,7 @@ add_llvm_library(lldELF ELFFile.cpp ELFLinkingContext.cpp FileCommon.cpp + HeaderChunks.cpp OutputELFWriter.cpp Reader.cpp SectionChunks.cpp diff --git a/lld/lib/ReaderWriter/ELF/HeaderChunks.cpp b/lld/lib/ReaderWriter/ELF/HeaderChunks.cpp new file mode 100644 index 00000000000..0bd4b3e03cf --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/HeaderChunks.cpp @@ -0,0 +1,205 @@ +//===- lib/ReaderWriter/ELF/HeaderChunks.cpp ------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "HeaderChunks.h" +#include "TargetLayout.h" +#include "llvm/ADT/STLExtras.h" + +namespace lld { +namespace elf { + +template <class ELFT> void ELFHeader<ELFT>::finalize() { + _eh.e_ident[llvm::ELF::EI_CLASS] = + (ELFT::Is64Bits) ? llvm::ELF::ELFCLASS64 : llvm::ELF::ELFCLASS32; + _eh.e_ident[llvm::ELF::EI_DATA] = + (ELFT::TargetEndianness == llvm::support::little) + ? llvm::ELF::ELFDATA2LSB + : llvm::ELF::ELFDATA2MSB; + _eh.e_type = this->_ctx.getOutputELFType(); + _eh.e_machine = this->_ctx.getOutputMachine(); +} + +template <class ELFT> +ELFHeader<ELFT>::ELFHeader(const ELFLinkingContext &ctx) + : Chunk<ELFT>("elfhdr", Chunk<ELFT>::Kind::ELFHeader, ctx) { + this->_alignment = ELFT::Is64Bits ? 8 : 4; + this->_fsize = sizeof(Elf_Ehdr); + this->_msize = sizeof(Elf_Ehdr); + memset(_eh.e_ident, 0, llvm::ELF::EI_NIDENT); + e_ident(llvm::ELF::EI_MAG0, 0x7f); + e_ident(llvm::ELF::EI_MAG1, 'E'); + e_ident(llvm::ELF::EI_MAG2, 'L'); + e_ident(llvm::ELF::EI_MAG3, 'F'); + e_ehsize(sizeof(Elf_Ehdr)); + e_flags(0); +} + +template <class ELFT> +void ELFHeader<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer) { + uint8_t *chunkBuffer = buffer.getBufferStart(); + uint8_t *atomContent = chunkBuffer + this->fileOffset(); + memcpy(atomContent, &_eh, fileSize()); +} + +template <class ELFT> +bool ProgramHeader<ELFT>::addSegment(Segment<ELFT> *segment) { + bool allocatedNew = false; + ELFLinkingContext::OutputMagic outputMagic = this->_ctx.getOutputMagic(); + // For segments that are not a loadable segment, we + // just pick the values directly from the segment as there + // wouldnt be any slices within that + if (segment->segmentType() != llvm::ELF::PT_LOAD) { + Elf_Phdr *phdr = allocateProgramHeader(allocatedNew); + phdr->p_type = segment->segmentType(); + phdr->p_offset = segment->fileOffset(); + phdr->p_vaddr = segment->virtualAddr(); + phdr->p_paddr = segment->virtualAddr(); + phdr->p_filesz = segment->fileSize(); + phdr->p_memsz = segment->memSize(); + phdr->p_flags = segment->flags(); + phdr->p_align = segment->alignment(); + this->_fsize = fileSize(); + this->_msize = this->_fsize; + return allocatedNew; + } + // For all other segments, use the slice + // to derive program headers + for (auto slice : segment->slices()) { + Elf_Phdr *phdr = allocateProgramHeader(allocatedNew); + phdr->p_type = segment->segmentType(); + phdr->p_offset = slice->fileOffset(); + phdr->p_vaddr = slice->virtualAddr(); + phdr->p_paddr = slice->virtualAddr(); + phdr->p_filesz = slice->fileSize(); + phdr->p_memsz = slice->memSize(); + phdr->p_flags = segment->flags(); + phdr->p_align = slice->alignment(); + uint64_t segPageSize = segment->pageSize(); + uint64_t sliceAlign = slice->alignment(); + // Alignment of PT_LOAD segments are set to the page size, but if the + // alignment of the slice is greater than the page size, set the alignment + // of the segment appropriately. + if (outputMagic != ELFLinkingContext::OutputMagic::NMAGIC && + outputMagic != ELFLinkingContext::OutputMagic::OMAGIC) { + phdr->p_align = + (phdr->p_type == llvm::ELF::PT_LOAD) + ? (segPageSize < sliceAlign) ? sliceAlign : segPageSize + : sliceAlign; + } else + phdr->p_align = slice->alignment(); + } + this->_fsize = fileSize(); + this->_msize = this->_fsize; + + return allocatedNew; +} + +template <class ELFT> +void ProgramHeader<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer) { + uint8_t *chunkBuffer = buffer.getBufferStart(); + uint8_t *dest = chunkBuffer + this->fileOffset(); + for (auto phi : _ph) { + memcpy(dest, phi, sizeof(Elf_Phdr)); + dest += sizeof(Elf_Phdr); + } +} + +template <class ELFT> +typename ProgramHeader<ELFT>::Elf_Phdr * +ProgramHeader<ELFT>::allocateProgramHeader(bool &allocatedNew) { + Elf_Phdr *phdr; + if (_phi == _ph.end()) { + phdr = new (_allocator) Elf_Phdr; + _ph.push_back(phdr); + _phi = _ph.end(); + allocatedNew = true; + } else { + phdr = (*_phi); + ++_phi; + } + return phdr; +} + +template <class ELFT> +SectionHeader<ELFT>::SectionHeader(const ELFLinkingContext &ctx, int32_t order) + : Chunk<ELFT>("shdr", Chunk<ELFT>::Kind::SectionHeader, ctx) { + this->_fsize = 0; + this->_alignment = 8; + this->setOrder(order); + // The first element in the list is always NULL + Elf_Shdr *nullshdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr; + ::memset(nullshdr, 0, sizeof(Elf_Shdr)); + _sectionInfo.push_back(nullshdr); + this->_fsize += sizeof(Elf_Shdr); +} + +template <class ELFT> +void SectionHeader<ELFT>::appendSection(OutputSection<ELFT> *section) { + Elf_Shdr *shdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr; + shdr->sh_name = _stringSection->addString(section->name()); + shdr->sh_type = section->type(); + shdr->sh_flags = section->flags(); + shdr->sh_offset = section->fileOffset(); + shdr->sh_addr = section->virtualAddr(); + if (section->isLoadableSection()) + shdr->sh_size = section->memSize(); + else + shdr->sh_size = section->fileSize(); + shdr->sh_link = section->link(); + shdr->sh_info = section->shinfo(); + shdr->sh_addralign = section->alignment(); + shdr->sh_entsize = section->entsize(); + _sectionInfo.push_back(shdr); +} + +template <class ELFT> +void SectionHeader<ELFT>::updateSection(Section<ELFT> *section) { + Elf_Shdr *shdr = _sectionInfo[section->ordinal()]; + shdr->sh_type = section->getType(); + shdr->sh_flags = section->getFlags(); + shdr->sh_offset = section->fileOffset(); + shdr->sh_addr = section->virtualAddr(); + shdr->sh_size = section->fileSize(); + shdr->sh_link = section->getLink(); + shdr->sh_info = section->getInfo(); + shdr->sh_addralign = section->alignment(); + shdr->sh_entsize = section->getEntSize(); +} + +template <class ELFT> +void SectionHeader<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout, + llvm::FileOutputBuffer &buffer) { + uint8_t *chunkBuffer = buffer.getBufferStart(); + uint8_t *dest = chunkBuffer + this->fileOffset(); + for (auto shi : _sectionInfo) { + memcpy(dest, shi, sizeof(Elf_Shdr)); + dest += sizeof(Elf_Shdr); + } + _stringSection->write(writer, layout, buffer); +} + +template class ELFHeader<ELF32LE>; +template class ELFHeader<ELF32BE>; +template class ELFHeader<ELF64LE>; +template class ELFHeader<ELF64BE>; + +template class ProgramHeader<ELF32LE>; +template class ProgramHeader<ELF32BE>; +template class ProgramHeader<ELF64LE>; +template class ProgramHeader<ELF64BE>; + +template class SectionHeader<ELF32LE>; +template class SectionHeader<ELF32BE>; +template class SectionHeader<ELF64LE>; +template class SectionHeader<ELF64BE>; + +} // end namespace elf +} // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/HeaderChunks.h b/lld/lib/ReaderWriter/ELF/HeaderChunks.h index 51c7f90cc75..51fbe38f1a0 100644 --- a/lld/lib/ReaderWriter/ELF/HeaderChunks.h +++ b/lld/lib/ReaderWriter/ELF/HeaderChunks.h @@ -11,18 +11,18 @@ #define LLD_READER_WRITER_ELF_HEADER_CHUNKS_H #include "SegmentChunks.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Object/ELF.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileOutputBuffer.h" -#include "llvm/Support/Format.h" /// \brief An Header represents the Elf[32/64]_Ehdr structure at the /// start of an ELF executable file. namespace lld { namespace elf { + template <class ELFT> class ELFHeader : public Chunk<ELFT> { public: typedef llvm::object::Elf_Ehdr_Impl<ELFT> Elf_Ehdr; @@ -46,7 +46,7 @@ public: uint64_t fileSize() const override { return sizeof(Elf_Ehdr); } static bool classof(const Chunk<ELFT> *c) { - return c->Kind() == Chunk<ELFT>::Kind::ELFHeader; + return c->kind() == Chunk<ELFT>::Kind::ELFHeader; } int getContentType() const override { @@ -56,44 +56,12 @@ public: void write(ELFWriter *writer, TargetLayout<ELFT> &layout, llvm::FileOutputBuffer &buffer) override; - void finalize() override { - _eh.e_ident[llvm::ELF::EI_CLASS] = - (ELFT::Is64Bits) ? llvm::ELF::ELFCLASS64 : llvm::ELF::ELFCLASS32; - _eh.e_ident[llvm::ELF::EI_DATA] = - (ELFT::TargetEndianness == llvm::support::little) - ? llvm::ELF::ELFDATA2LSB - : llvm::ELF::ELFDATA2MSB; - _eh.e_type = this->_ctx.getOutputELFType(); - _eh.e_machine = this->_ctx.getOutputMachine(); - } + void finalize() override; private: Elf_Ehdr _eh; }; -template <class ELFT> -ELFHeader<ELFT>::ELFHeader(const ELFLinkingContext &ctx) - : Chunk<ELFT>("elfhdr", Chunk<ELFT>::Kind::ELFHeader, ctx) { - this->_alignment = ELFT::Is64Bits ? 8 : 4; - this->_fsize = sizeof(Elf_Ehdr); - this->_msize = sizeof(Elf_Ehdr); - memset(_eh.e_ident, 0, llvm::ELF::EI_NIDENT); - e_ident(llvm::ELF::EI_MAG0, 0x7f); - e_ident(llvm::ELF::EI_MAG1, 'E'); - e_ident(llvm::ELF::EI_MAG2, 'L'); - e_ident(llvm::ELF::EI_MAG3, 'F'); - e_ehsize(sizeof(Elf_Ehdr)); - e_flags(0); -} - -template <class ELFT> -void ELFHeader<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout, - llvm::FileOutputBuffer &buffer) { - uint8_t *chunkBuffer = buffer.getBufferStart(); - uint8_t *atomContent = chunkBuffer + this->fileOffset(); - memcpy(atomContent, &_eh, fileSize()); -} - /// \brief An ProgramHeader represents the Elf[32/64]_Phdr structure at the /// start of an ELF executable file. template<class ELFT> @@ -110,13 +78,11 @@ public: } bool addSegment(Segment<ELFT> *segment); - void resetProgramHeaders() { _phi = _ph.begin(); } - uint64_t fileSize() const override { return sizeof(Elf_Phdr) * _ph.size(); } static bool classof(const Chunk<ELFT> *c) { - return c->Kind() == Chunk<ELFT>::Kind::ProgramHeader; + return c->kind() == Chunk<ELFT>::Kind::ProgramHeader; } void write(ELFWriter *writer, TargetLayout<ELFT> &layout, @@ -128,7 +94,6 @@ public: ReversePhIterT rend() { return _ph.rend(); } int64_t entsize() { return sizeof(Elf_Phdr); } - int64_t numHeaders() { return _ph.size(); } int getContentType() const override { @@ -136,88 +101,13 @@ public: } private: - Elf_Phdr *allocateProgramHeader(bool &allocatedNew) { - Elf_Phdr *phdr; - if (_phi == _ph.end()) { - phdr = new (_allocator) Elf_Phdr; - _ph.push_back(phdr); - _phi = _ph.end(); - allocatedNew = true; - } else { - phdr = (*_phi); - ++_phi; - } - return phdr; - } + Elf_Phdr *allocateProgramHeader(bool &allocatedNew); std::vector<Elf_Phdr *> _ph; PhIterT _phi; llvm::BumpPtrAllocator _allocator; }; -template <class ELFT> -bool ProgramHeader<ELFT>::addSegment(Segment<ELFT> *segment) { - bool allocatedNew = false; - ELFLinkingContext::OutputMagic outputMagic = this->_ctx.getOutputMagic(); - // For segments that are not a loadable segment, we - // just pick the values directly from the segment as there - // wouldnt be any slices within that - if (segment->segmentType() != llvm::ELF::PT_LOAD) { - Elf_Phdr *phdr = allocateProgramHeader(allocatedNew); - phdr->p_type = segment->segmentType(); - phdr->p_offset = segment->fileOffset(); - phdr->p_vaddr = segment->virtualAddr(); - phdr->p_paddr = segment->virtualAddr(); - phdr->p_filesz = segment->fileSize(); - phdr->p_memsz = segment->memSize(); - phdr->p_flags = segment->flags(); - phdr->p_align = segment->alignment(); - this->_fsize = fileSize(); - this->_msize = this->_fsize; - return allocatedNew; - } - // For all other segments, use the slice - // to derive program headers - for (auto slice : segment->slices()) { - Elf_Phdr *phdr = allocateProgramHeader(allocatedNew); - phdr->p_type = segment->segmentType(); - phdr->p_offset = slice->fileOffset(); - phdr->p_vaddr = slice->virtualAddr(); - phdr->p_paddr = slice->virtualAddr(); - phdr->p_filesz = slice->fileSize(); - phdr->p_memsz = slice->memSize(); - phdr->p_flags = segment->flags(); - phdr->p_align = slice->alignment(); - uint64_t segPageSize = segment->pageSize(); - uint64_t sliceAlign = slice->alignment(); - // Alignment of PT_LOAD segments are set to the page size, but if the - // alignment of the slice is greater than the page size, set the alignment - // of the segment appropriately. - if (outputMagic != ELFLinkingContext::OutputMagic::NMAGIC && - outputMagic != ELFLinkingContext::OutputMagic::OMAGIC) { - phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) - ? (segPageSize < sliceAlign) ? sliceAlign : segPageSize - : sliceAlign; - } else - phdr->p_align = slice->alignment(); - } - this->_fsize = fileSize(); - this->_msize = this->_fsize; - - return allocatedNew; -} - -template <class ELFT> -void ProgramHeader<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout, - llvm::FileOutputBuffer &buffer) { - uint8_t *chunkBuffer = buffer.getBufferStart(); - uint8_t *dest = chunkBuffer + this->fileOffset(); - for (auto phi : _ph) { - memcpy(dest, phi, sizeof(Elf_Phdr)); - dest += sizeof(Elf_Phdr); - } -} - /// \brief An SectionHeader represents the Elf[32/64]_Shdr structure /// at the end of the file template<class ELFT> @@ -226,13 +116,11 @@ public: typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr; SectionHeader(const ELFLinkingContext &, int32_t order); - void appendSection(OutputSection<ELFT> *section); - void updateSection(Section<ELFT> *section); static bool classof(const Chunk<ELFT> *c) { - return c->getChunkKind() == Chunk<ELFT>::Kind::SectionHeader; + return c->kind() == Chunk<ELFT>::Kind::SectionHeader; } void setStringSection(StringTable<ELFT> *s) { @@ -256,68 +144,10 @@ public: private: StringTable<ELFT> *_stringSection; - std::vector<Elf_Shdr*> _sectionInfo; - llvm::BumpPtrAllocator _sectionAllocate; + std::vector<Elf_Shdr *> _sectionInfo; + llvm::BumpPtrAllocator _sectionAllocate; }; -template <class ELFT> -SectionHeader<ELFT>::SectionHeader(const ELFLinkingContext &ctx, int32_t order) - : Chunk<ELFT>("shdr", Chunk<ELFT>::Kind::SectionHeader, ctx) { - this->_fsize = 0; - this->_alignment = 8; - this->setOrder(order); - // The first element in the list is always NULL - Elf_Shdr *nullshdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr; - ::memset(nullshdr, 0, sizeof (Elf_Shdr)); - _sectionInfo.push_back(nullshdr); - this->_fsize += sizeof (Elf_Shdr); -} - -template <class ELFT> -void SectionHeader<ELFT>::appendSection(OutputSection<ELFT> *section) { - Elf_Shdr *shdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr; - shdr->sh_name = _stringSection->addString(section->name()); - shdr->sh_type = section->type(); - shdr->sh_flags = section->flags(); - shdr->sh_offset = section->fileOffset(); - shdr->sh_addr = section->virtualAddr(); - if (section->isLoadableSection()) - shdr->sh_size = section->memSize(); - else - shdr->sh_size = section->fileSize(); - shdr->sh_link = section->link(); - shdr->sh_info = section->shinfo(); - shdr->sh_addralign = section->alignment(); - shdr->sh_entsize = section->entsize(); - _sectionInfo.push_back(shdr); -} - -template<class ELFT> -void -SectionHeader<ELFT>::updateSection(Section<ELFT> *section) { - Elf_Shdr *shdr = _sectionInfo[section->ordinal()]; - shdr->sh_type = section->getType(); - shdr->sh_flags = section->getFlags(); - shdr->sh_offset = section->fileOffset(); - shdr->sh_addr = section->virtualAddr(); - shdr->sh_size = section->fileSize(); - shdr->sh_link = section->getLink(); - shdr->sh_info = section->getInfo(); - shdr->sh_addralign = section->alignment(); - shdr->sh_entsize = section->getEntSize(); -} - -template <class ELFT> -void SectionHeader<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout, - llvm::FileOutputBuffer &buffer) { - uint8_t *chunkBuffer = buffer.getBufferStart(); - uint8_t *dest = chunkBuffer + this->fileOffset(); - for (auto shi : _sectionInfo) { - memcpy(dest, shi, sizeof(Elf_Shdr)); - dest += sizeof(Elf_Shdr); - } - _stringSection->write(writer, layout, buffer); -} } // end namespace elf } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp index 3b038f76a96..94906bd65e1 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp @@ -10,6 +10,7 @@ #include "MipsLinkingContext.h" #include "MipsRelocationHandler.h" #include "MipsTargetLayout.h" +#include "llvm/Support/Format.h" using namespace lld; using namespace elf; |