diff options
Diffstat (limited to 'llvm/tools/llvm-objcopy/Object.h')
-rw-r--r-- | llvm/tools/llvm-objcopy/Object.h | 325 |
1 files changed, 91 insertions, 234 deletions
diff --git a/llvm/tools/llvm-objcopy/Object.h b/llvm/tools/llvm-objcopy/Object.h index 15a286e71c4..6ac7edd32ae 100644 --- a/llvm/tools/llvm-objcopy/Object.h +++ b/llvm/tools/llvm-objcopy/Object.h @@ -16,7 +16,6 @@ #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELFObjectFile.h" -#include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/JamCRC.h" #include <cstddef> #include <cstdint> @@ -27,159 +26,25 @@ namespace llvm { +class FileOutputBuffer; class SectionBase; -class Section; -class OwnedDataSection; -class StringTableSection; -class SymbolTableSection; -class RelocationSection; -class DynamicRelocationSection; -class GnuDebugLinkSection; class Segment; -class Object; class SectionTableRef { private: - MutableArrayRef<std::unique_ptr<SectionBase>> Sections; + ArrayRef<std::unique_ptr<SectionBase>> Sections; public: - using iterator = pointee_iterator<std::unique_ptr<SectionBase> *>; - - SectionTableRef(MutableArrayRef<std::unique_ptr<SectionBase>> Secs) + SectionTableRef(ArrayRef<std::unique_ptr<SectionBase>> Secs) : Sections(Secs) {} SectionTableRef(const SectionTableRef &) = default; - iterator begin() { return iterator(Sections.data()); } - iterator end() { return iterator(Sections.data() + Sections.size()); } - SectionBase *getSection(uint16_t Index, Twine ErrMsg); template <class T> T *getSectionOfType(uint16_t Index, Twine IndexErrMsg, Twine TypeErrMsg); }; -enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE }; - -class SectionVisitor { -public: - virtual ~SectionVisitor(); - - virtual void visit(const Section &Sec) = 0; - virtual void visit(const OwnedDataSection &Sec) = 0; - virtual void visit(const StringTableSection &Sec) = 0; - virtual void visit(const SymbolTableSection &Sec) = 0; - virtual void visit(const RelocationSection &Sec) = 0; - virtual void visit(const DynamicRelocationSection &Sec) = 0; - virtual void visit(const GnuDebugLinkSection &Sec) = 0; -}; - -class SectionWriter : public SectionVisitor { -protected: - FileOutputBuffer &Out; - -public: - virtual ~SectionWriter(){}; - - void visit(const Section &Sec) override; - void visit(const OwnedDataSection &Sec) override; - void visit(const StringTableSection &Sec) override; - void visit(const DynamicRelocationSection &Sec) override; - virtual void visit(const SymbolTableSection &Sec) override = 0; - virtual void visit(const RelocationSection &Sec) override = 0; - virtual void visit(const GnuDebugLinkSection &Sec) override = 0; - - SectionWriter(FileOutputBuffer &Buf) : Out(Buf) {} -}; - -template <class ELFT> class ELFSectionWriter : public SectionWriter { -private: - using Elf_Word = typename ELFT::Word; - using Elf_Rel = typename ELFT::Rel; - using Elf_Rela = typename ELFT::Rela; - -public: - virtual ~ELFSectionWriter() {} - void visit(const SymbolTableSection &Sec) override; - void visit(const RelocationSection &Sec) override; - void visit(const GnuDebugLinkSection &Sec) override; - - ELFSectionWriter(FileOutputBuffer &Buf) : SectionWriter(Buf) {} -}; - -#define MAKE_SEC_WRITER_FRIEND \ - template friend class SectionWriter; \ - template <class ELFT> friend class ELFSectionWriter; - -class BinarySectionWriter : public SectionWriter { -public: - virtual ~BinarySectionWriter() {} - - void visit(const SymbolTableSection &Sec) override; - void visit(const RelocationSection &Sec) override; - void visit(const GnuDebugLinkSection &Sec) override; - BinarySectionWriter(FileOutputBuffer &Buf) : SectionWriter(Buf) {} -}; - -class Writer { -protected: - StringRef File; - Object &Obj; - std::unique_ptr<FileOutputBuffer> BufPtr; - - void createBuffer(uint64_t Size); - -public: - virtual ~Writer(); - - virtual void finalize() = 0; - virtual void write() = 0; - - Writer(StringRef File, Object &Obj) : File(File), Obj(Obj) {} -}; - -template <class ELFT> class ELFWriter : public Writer { -private: - using Elf_Shdr = typename ELFT::Shdr; - using Elf_Phdr = typename ELFT::Phdr; - using Elf_Ehdr = typename ELFT::Ehdr; - - void writeEhdr(); - void writePhdr(const Segment &Seg); - void writeShdr(const SectionBase &Sec); - - void writePhdrs(); - void writeShdrs(); - void writeSectionData(); - - void assignOffsets(); - - std::unique_ptr<ELFSectionWriter<ELFT>> SecWriter; - - size_t totalSize() const; - -public: - virtual ~ELFWriter() {} - bool WriteSectionHeaders = true; - - void finalize() override; - void write() override; - ELFWriter(StringRef File, Object &Obj, bool WSH) - : Writer(File, Obj), WriteSectionHeaders(WSH) {} -}; - -class BinaryWriter : public Writer { -private: - std::unique_ptr<BinarySectionWriter> SecWriter; - - uint64_t TotalSize; - -public: - ~BinaryWriter() {} - void finalize() override; - void write() override; - BinaryWriter(StringRef File, Object &Obj) : Writer(File, Obj) {} -}; - class SectionBase { public: StringRef Name; @@ -204,7 +69,8 @@ public: virtual void initialize(SectionTableRef SecTable); virtual void finalize(); virtual void removeSectionReferences(const SectionBase *Sec); - virtual void accept(SectionVisitor &Visitor) const = 0; + template <class ELFT> void writeHeader(FileOutputBuffer &Out) const; + virtual void writeSection(FileOutputBuffer &Out) const = 0; }; class Segment { @@ -247,23 +113,21 @@ public: void removeSection(const SectionBase *Sec) { Sections.erase(Sec); } void addSection(const SectionBase *Sec) { Sections.insert(Sec); } + template <class ELFT> void writeHeader(FileOutputBuffer &Out) const; + void writeSegment(FileOutputBuffer &Out) const; }; class Section : public SectionBase { - MAKE_SEC_WRITER_FRIEND - private: ArrayRef<uint8_t> Contents; public: Section(ArrayRef<uint8_t> Data) : Contents(Data) {} - void accept(SectionVisitor &Visitor) const override; + void writeSection(FileOutputBuffer &Out) const override; }; class OwnedDataSection : public SectionBase { - MAKE_SEC_WRITER_FRIEND - private: std::vector<uint8_t> Data; @@ -273,10 +137,8 @@ public: Name = SecName; Type = ELF::SHT_PROGBITS; Size = Data.size(); - OriginalOffset = std::numeric_limits<uint64_t>::max(); } - - void accept(SectionVisitor &Sec) const override; + void writeSection(FileOutputBuffer &Out) const override; }; // There are two types of string tables that can exist, dynamic and not dynamic. @@ -288,8 +150,6 @@ public: // classof method checks that the particular instance is not allocated. This // then agrees with the makeSection method used to construct most sections. class StringTableSection : public SectionBase { - MAKE_SEC_WRITER_FRIEND - private: StringTableBuilder StrTabBuilder; @@ -301,7 +161,7 @@ public: void addString(StringRef Name); uint32_t findIndex(StringRef Name) const; void finalize() override; - void accept(SectionVisitor &Visitor) const override; + void writeSection(FileOutputBuffer &Out) const override; static bool classof(const SectionBase *S) { if (S->Flags & ELF::SHF_ALLOC) @@ -340,8 +200,6 @@ struct Symbol { }; class SymbolTableSection : public SectionBase { - MAKE_SEC_WRITER_FRIEND - protected: std::vector<std::unique_ptr<Symbol>> Symbols; StringTableSection *SymbolNames = nullptr; @@ -360,13 +218,17 @@ public: void localize(std::function<bool(const Symbol &)> ToLocalize); void initialize(SectionTableRef SecTable) override; void finalize() override; - void accept(SectionVisitor &Visitor) const override; static bool classof(const SectionBase *S) { return S->Type == ELF::SHT_SYMTAB; } }; +// Only writeSection depends on the ELF type so we implement it in a subclass. +template <class ELFT> class SymbolTableSectionImpl : public SymbolTableSection { + void writeSection(FileOutputBuffer &Out) const override; +}; + struct Relocation { const Symbol *RelocSymbol = nullptr; uint64_t Offset; @@ -413,16 +275,20 @@ public: void finalize() override; }; +template <class ELFT> class RelocationSection : public RelocSectionWithSymtabBase<SymbolTableSection> { - MAKE_SEC_WRITER_FRIEND - private: + using Elf_Rel = typename ELFT::Rel; + using Elf_Rela = typename ELFT::Rela; + std::vector<Relocation> Relocations; + template <class T> void writeRel(T *Buf) const; + public: void addRelocation(Relocation Rel) { Relocations.push_back(Rel); } - void accept(SectionVisitor &Visitor) const override; + void writeSection(FileOutputBuffer &Out) const override; static bool classof(const SectionBase *S) { if (S->Flags & ELF::SHF_ALLOC) @@ -465,15 +331,13 @@ public: class DynamicRelocationSection : public RelocSectionWithSymtabBase<DynamicSymbolTableSection> { - MAKE_SEC_WRITER_FRIEND - private: ArrayRef<uint8_t> Contents; public: DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {} - void accept(SectionVisitor &) const override; + void writeSection(FileOutputBuffer &Out) const override; static bool classof(const SectionBase *S) { if (!(S->Flags & ELF::SHF_ALLOC)) @@ -482,10 +346,12 @@ public: } }; -class GnuDebugLinkSection : public SectionBase { - MAKE_SEC_WRITER_FRIEND - +template <class ELFT> class GnuDebugLinkSection : public SectionBase { private: + // Elf_Word is 4-bytes on every format but has the same endianess as the elf + // type ELFT. We'll need to write the CRC32 out in the proper endianess so + // we'll make sure to use this type. + using Elf_Word = typename ELFT::Word; StringRef FileName; uint32_t CRC32; @@ -495,101 +361,92 @@ private: public: // If we add this section from an external source we can use this ctor. GnuDebugLinkSection(StringRef File); - void accept(SectionVisitor &Visitor) const override; -}; - -class Reader { -public: - virtual ~Reader(); - virtual std::unique_ptr<Object> create() const = 0; + void writeSection(FileOutputBuffer &Out) const override; }; -using object::OwningBinary; -using object::Binary; -using object::ELFFile; -using object::ELFObjectFile; - -template <class ELFT> class ELFBuilder { +template <class ELFT> class Object { private: + using SecPtr = std::unique_ptr<SectionBase>; + using SegPtr = std::unique_ptr<Segment>; + using Elf_Shdr = typename ELFT::Shdr; + using Elf_Ehdr = typename ELFT::Ehdr; + using Elf_Phdr = typename ELFT::Phdr; - const ELFFile<ELFT> &ElfFile; - Object &Obj; + void initSymbolTable(const object::ELFFile<ELFT> &ElfFile, + SymbolTableSection *SymTab, SectionTableRef SecTable); + SecPtr makeSection(const object::ELFFile<ELFT> &ElfFile, + const Elf_Shdr &Shdr); + void readProgramHeaders(const object::ELFFile<ELFT> &ElfFile); + SectionTableRef readSectionHeaders(const object::ELFFile<ELFT> &ElfFile); - void readProgramHeaders(); - void initSymbolTable(SymbolTableSection *SymTab); - void readSectionHeaders(); - SectionBase &makeSection(const Elf_Shdr &Shdr); +protected: + StringTableSection *SectionNames = nullptr; + SymbolTableSection *SymbolTable = nullptr; + std::vector<SecPtr> Sections; + std::vector<SegPtr> Segments; -public: - ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj) - : ElfFile(*ElfObj.getELFFile()), Obj(Obj) {} + void writeHeader(FileOutputBuffer &Out) const; + void writeProgramHeaders(FileOutputBuffer &Out) const; + void writeSectionData(FileOutputBuffer &Out) const; + void writeSectionHeaders(FileOutputBuffer &Out) const; - void build(); -}; +public: + uint8_t Ident[16]; + uint64_t Entry; + uint64_t SHOffset; + uint32_t Type; + uint32_t Machine; + uint32_t Version; + uint32_t Flags; + bool WriteSectionHeaders = true; -class ELFReader : public Reader { -private: - std::unique_ptr<Binary> Binary; - std::shared_ptr<MemoryBuffer> Data; + Object(const object::ELFObjectFile<ELFT> &Obj); + virtual ~Object() = default; -public: - ElfType getElfType() const; - std::unique_ptr<Object> create() const override; - ELFReader(StringRef File); + SymbolTableSection *getSymTab() const { return SymbolTable; } + const SectionBase *getSectionHeaderStrTab() const { return SectionNames; } + void removeSections(std::function<bool(const SectionBase &)> ToRemove); + void addSection(StringRef SecName, ArrayRef<uint8_t> Data); + void addGnuDebugLink(StringRef File); + virtual size_t totalSize() const = 0; + virtual void finalize() = 0; + virtual void write(FileOutputBuffer &Out) const = 0; }; -class Object { +template <class ELFT> class ELFObject : public Object<ELFT> { private: using SecPtr = std::unique_ptr<SectionBase>; using SegPtr = std::unique_ptr<Segment>; - std::shared_ptr<MemoryBuffer> OwnedData; - std::vector<SecPtr> Sections; - std::vector<SegPtr> Segments; + using Elf_Shdr = typename ELFT::Shdr; + using Elf_Ehdr = typename ELFT::Ehdr; + using Elf_Phdr = typename ELFT::Phdr; -public: - template <class T> - using Range = iterator_range< - pointee_iterator<typename std::vector<std::unique_ptr<T>>::iterator>>; + void sortSections(); + void assignOffsets(); - template <class T> - using ConstRange = iterator_range<pointee_iterator< - typename std::vector<std::unique_ptr<T>>::const_iterator>>; +public: + ELFObject(const object::ELFObjectFile<ELFT> &Obj) : Object<ELFT>(Obj) {} - uint8_t Ident[16]; - uint64_t Entry; - uint64_t SHOffset; - uint32_t Type; - uint32_t Machine; - uint32_t Version; - uint32_t Flags; + void finalize() override; + size_t totalSize() const override; + void write(FileOutputBuffer &Out) const override; +}; - StringTableSection *SectionNames = nullptr; - SymbolTableSection *SymbolTable = nullptr; +template <class ELFT> class BinaryObject : public Object<ELFT> { +private: + using SecPtr = std::unique_ptr<SectionBase>; + using SegPtr = std::unique_ptr<Segment>; - Object(std::shared_ptr<MemoryBuffer> Data) : OwnedData(Data) {} - virtual ~Object() = default; + uint64_t TotalSize; - void sortSections(); - SectionTableRef sections() { return SectionTableRef(Sections); } - ConstRange<SectionBase> sections() const { - return make_pointee_range(Sections); - } - Range<Segment> segments() { return make_pointee_range(Segments); } - ConstRange<Segment> segments() const { return make_pointee_range(Segments); } +public: + BinaryObject(const object::ELFObjectFile<ELFT> &Obj) : Object<ELFT>(Obj) {} - void removeSections(std::function<bool(const SectionBase &)> ToRemove); - template <class T, class... Ts> T &addSection(Ts &&... Args) { - auto Sec = llvm::make_unique<T>(std::forward<Ts>(Args)...); - auto Ptr = Sec.get(); - Sections.emplace_back(std::move(Sec)); - return *Ptr; - } - Segment &addSegment(ArrayRef<uint8_t> Data) { - Segments.emplace_back(llvm::make_unique<Segment>(Data)); - return *Segments.back(); - } + void finalize() override; + size_t totalSize() const override; + void write(FileOutputBuffer &Out) const override; }; } // end namespace llvm |