summaryrefslogtreecommitdiff
path: root/lib/ReaderWriter/ELF/HeaderChunks.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ReaderWriter/ELF/HeaderChunks.h')
-rw-r--r--lib/ReaderWriter/ELF/HeaderChunks.h278
1 files changed, 34 insertions, 244 deletions
diff --git a/lib/ReaderWriter/ELF/HeaderChunks.h b/lib/ReaderWriter/ELF/HeaderChunks.h
index eab132b9b2f69..51fbe38f1a008 100644
--- a/lib/ReaderWriter/ELF/HeaderChunks.h
+++ b/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;
@@ -33,9 +33,9 @@ public:
void e_type(uint16_t type) { _eh.e_type = type; }
void e_machine(uint16_t machine) { _eh.e_machine = machine; }
void e_version(uint32_t version) { _eh.e_version = version; }
- void e_entry(int64_t entry) { _eh.e_entry = entry; }
- void e_phoff(int64_t phoff) { _eh.e_phoff = phoff; }
- void e_shoff(int64_t shoff) { _eh.e_shoff = shoff; }
+ void e_entry(int64_t entry) { _eh.e_entry = entry; }
+ void e_phoff(int64_t phoff) { _eh.e_phoff = phoff; }
+ void e_shoff(int64_t shoff) { _eh.e_shoff = shoff; }
void e_flags(uint32_t flags) { _eh.e_flags = flags; }
void e_ehsize(uint16_t ehsize) { _eh.e_ehsize = ehsize; }
void e_phentsize(uint16_t phentsize) { _eh.e_phentsize = phentsize; }
@@ -43,57 +43,25 @@ public:
void e_shentsize(uint16_t shentsize) { _eh.e_shentsize = shentsize; }
void e_shnum(uint16_t shnum) { _eh.e_shnum = shnum; }
void e_shstrndx(uint16_t shstrndx) { _eh.e_shstrndx = shstrndx; }
- uint64_t fileSize() const { return sizeof(Elf_Ehdr); }
+ 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 { return Chunk<ELFT>::ContentType::Header; }
+ int getContentType() const override {
+ return Chunk<ELFT>::ContentType::Header;
+ }
void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer);
-
- virtual void doPreFlight() {}
-
- void 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->_context.getOutputELFType();
- _eh.e_machine = this->_context.getOutputMachine();
- }
+ llvm::FileOutputBuffer &buffer) override;
+
+ void finalize() override;
private:
Elf_Ehdr _eh;
};
-template <class ELFT>
-ELFHeader<ELFT>::ELFHeader(const ELFLinkingContext &context)
- : Chunk<ELFT>("elfhdr", Chunk<ELFT>::Kind::ELFHeader, context) {
- 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>
@@ -103,160 +71,43 @@ public:
typedef typename std::vector<Elf_Phdr *>::iterator PhIterT;
typedef typename std::reverse_iterator<PhIterT> ReversePhIterT;
- /// \brief Find a program header entry, given the type of entry that
- /// we are looking for
- class FindPhdr {
- public:
- FindPhdr(uint64_t type, uint64_t flags, uint64_t flagsClear)
- : _type(type)
- , _flags(flags)
- , _flagsClear(flagsClear) {
- }
-
- bool operator()(const llvm::object::Elf_Phdr_Impl<ELFT> *j) const {
- return ((j->p_type == _type) &&
- ((j->p_flags & _flags) == _flags) &&
- (!(j->p_flags & _flagsClear)));
- }
- private:
- uint64_t _type;
- uint64_t _flags;
- uint64_t _flagsClear;
- };
-
- ProgramHeader(const ELFLinkingContext &context)
- : Chunk<ELFT>("elfphdr", Chunk<ELFT>::Kind::ProgramHeader, context) {
+ ProgramHeader(const ELFLinkingContext &ctx)
+ : Chunk<ELFT>("elfphdr", Chunk<ELFT>::Kind::ProgramHeader, ctx) {
this->_alignment = ELFT::Is64Bits ? 8 : 4;
resetProgramHeaders();
}
bool addSegment(Segment<ELFT> *segment);
-
void resetProgramHeaders() { _phi = _ph.begin(); }
-
- uint64_t fileSize() const { return sizeof(Elf_Phdr) * _ph.size(); }
+ 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,
- llvm::FileOutputBuffer &buffer);
-
- /// \brief find a program header entry in the list of program headers
- ReversePhIterT
- findProgramHeader(uint64_t type, uint64_t flags, uint64_t flagClear) {
- return std::find_if(_ph.rbegin(), _ph.rend(),
- FindPhdr(type, flags, flagClear));
- }
-
- PhIterT begin() {
- return _ph.begin();
- }
-
- PhIterT end() {
- return _ph.end();
- }
+ llvm::FileOutputBuffer &buffer) override;
+ PhIterT begin() { return _ph.begin(); }
+ PhIterT end() { return _ph.end(); }
ReversePhIterT rbegin() { return _ph.rbegin(); }
-
ReversePhIterT rend() { return _ph.rend(); }
- virtual void doPreFlight() {}
-
- void finalize() {}
-
int64_t entsize() { return sizeof(Elf_Phdr); }
+ int64_t numHeaders() { return _ph.size(); }
- int64_t numHeaders() {
- return _ph.size();
+ int getContentType() const override {
+ return Chunk<ELFT>::ContentType::Header;
}
- int getContentType() const { return Chunk<ELFT>::ContentType::Header; }
-
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->_context.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>
@@ -265,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) {
@@ -279,85 +128,26 @@ public:
}
void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer);
+ llvm::FileOutputBuffer &buffer) override;
- virtual void doPreFlight() {}
-
- void finalize() {}
-
- uint64_t fileSize() const { return sizeof(Elf_Shdr) * _sectionInfo.size(); }
+ uint64_t fileSize() const override {
+ return sizeof(Elf_Shdr) * _sectionInfo.size();
+ }
uint64_t entsize() { return sizeof(Elf_Shdr); }
- int getContentType() const { return Chunk<ELFT>::ContentType::Header; }
+ int getContentType() const override {
+ return Chunk<ELFT>::ContentType::Header;
+ }
uint64_t numHeaders() { return _sectionInfo.size(); }
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 &context,
- int32_t order)
- : Chunk<ELFT>("shdr", Chunk<ELFT>::Kind::SectionHeader, context) {
- 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