summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-objcopy/Object.h
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-objcopy/Object.h')
-rw-r--r--llvm/tools/llvm-objcopy/Object.h325
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
OpenPOWER on IntegriCloud