123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113 |
- //===- Object.h -------------------------------------------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_TOOLS_OBJCOPY_OBJECT_H
- #define LLVM_TOOLS_OBJCOPY_OBJECT_H
- #include "CommonConfig.h"
- #include "llvm/ADT/ArrayRef.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/ADT/Twine.h"
- #include "llvm/BinaryFormat/ELF.h"
- #include "llvm/MC/StringTableBuilder.h"
- #include "llvm/Object/ELFObjectFile.h"
- #include "llvm/Support/Errc.h"
- #include "llvm/Support/FileOutputBuffer.h"
- #include "llvm/Support/MemoryBuffer.h"
- #include <cstddef>
- #include <cstdint>
- #include <functional>
- #include <memory>
- #include <set>
- #include <vector>
- namespace llvm {
- enum class DebugCompressionType;
- namespace objcopy {
- namespace elf {
- class SectionBase;
- class Section;
- class OwnedDataSection;
- class StringTableSection;
- class SymbolTableSection;
- class RelocationSection;
- class DynamicRelocationSection;
- class GnuDebugLinkSection;
- class GroupSection;
- class SectionIndexSection;
- class CompressedSection;
- class DecompressedSection;
- class Segment;
- class Object;
- struct Symbol;
- class SectionTableRef {
- ArrayRef<std::unique_ptr<SectionBase>> Sections;
- public:
- using iterator = pointee_iterator<const std::unique_ptr<SectionBase> *>;
- explicit SectionTableRef(ArrayRef<std::unique_ptr<SectionBase>> Secs)
- : Sections(Secs) {}
- SectionTableRef(const SectionTableRef &) = default;
- iterator begin() const { return iterator(Sections.data()); }
- iterator end() const { return iterator(Sections.data() + Sections.size()); }
- size_t size() const { return Sections.size(); }
- Expected<SectionBase *> getSection(uint32_t Index, Twine ErrMsg);
- template <class T>
- Expected<T *> getSectionOfType(uint32_t Index, Twine IndexErrMsg,
- Twine TypeErrMsg);
- };
- enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE };
- class SectionVisitor {
- public:
- virtual ~SectionVisitor() = default;
- virtual Error visit(const Section &Sec) = 0;
- virtual Error visit(const OwnedDataSection &Sec) = 0;
- virtual Error visit(const StringTableSection &Sec) = 0;
- virtual Error visit(const SymbolTableSection &Sec) = 0;
- virtual Error visit(const RelocationSection &Sec) = 0;
- virtual Error visit(const DynamicRelocationSection &Sec) = 0;
- virtual Error visit(const GnuDebugLinkSection &Sec) = 0;
- virtual Error visit(const GroupSection &Sec) = 0;
- virtual Error visit(const SectionIndexSection &Sec) = 0;
- virtual Error visit(const CompressedSection &Sec) = 0;
- virtual Error visit(const DecompressedSection &Sec) = 0;
- };
- class MutableSectionVisitor {
- public:
- virtual ~MutableSectionVisitor() = default;
- virtual Error visit(Section &Sec) = 0;
- virtual Error visit(OwnedDataSection &Sec) = 0;
- virtual Error visit(StringTableSection &Sec) = 0;
- virtual Error visit(SymbolTableSection &Sec) = 0;
- virtual Error visit(RelocationSection &Sec) = 0;
- virtual Error visit(DynamicRelocationSection &Sec) = 0;
- virtual Error visit(GnuDebugLinkSection &Sec) = 0;
- virtual Error visit(GroupSection &Sec) = 0;
- virtual Error visit(SectionIndexSection &Sec) = 0;
- virtual Error visit(CompressedSection &Sec) = 0;
- virtual Error visit(DecompressedSection &Sec) = 0;
- };
- class SectionWriter : public SectionVisitor {
- protected:
- WritableMemoryBuffer &Out;
- public:
- virtual ~SectionWriter() = default;
- Error visit(const Section &Sec) override;
- Error visit(const OwnedDataSection &Sec) override;
- Error visit(const StringTableSection &Sec) override;
- Error visit(const DynamicRelocationSection &Sec) override;
- virtual Error visit(const SymbolTableSection &Sec) override = 0;
- virtual Error visit(const RelocationSection &Sec) override = 0;
- virtual Error visit(const GnuDebugLinkSection &Sec) override = 0;
- virtual Error visit(const GroupSection &Sec) override = 0;
- virtual Error visit(const SectionIndexSection &Sec) override = 0;
- virtual Error visit(const CompressedSection &Sec) override = 0;
- virtual Error visit(const DecompressedSection &Sec) override = 0;
- explicit SectionWriter(WritableMemoryBuffer &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;
- using Elf_Sym = typename ELFT::Sym;
- public:
- virtual ~ELFSectionWriter() {}
- Error visit(const SymbolTableSection &Sec) override;
- Error visit(const RelocationSection &Sec) override;
- Error visit(const GnuDebugLinkSection &Sec) override;
- Error visit(const GroupSection &Sec) override;
- Error visit(const SectionIndexSection &Sec) override;
- Error visit(const CompressedSection &Sec) override;
- Error visit(const DecompressedSection &Sec) override;
- explicit ELFSectionWriter(WritableMemoryBuffer &Buf) : SectionWriter(Buf) {}
- };
- template <class ELFT> class ELFSectionSizer : public MutableSectionVisitor {
- private:
- using Elf_Rel = typename ELFT::Rel;
- using Elf_Rela = typename ELFT::Rela;
- using Elf_Sym = typename ELFT::Sym;
- using Elf_Word = typename ELFT::Word;
- using Elf_Xword = typename ELFT::Xword;
- public:
- Error visit(Section &Sec) override;
- Error visit(OwnedDataSection &Sec) override;
- Error visit(StringTableSection &Sec) override;
- Error visit(DynamicRelocationSection &Sec) override;
- Error visit(SymbolTableSection &Sec) override;
- Error visit(RelocationSection &Sec) override;
- Error visit(GnuDebugLinkSection &Sec) override;
- Error visit(GroupSection &Sec) override;
- Error visit(SectionIndexSection &Sec) override;
- Error visit(CompressedSection &Sec) override;
- Error visit(DecompressedSection &Sec) override;
- };
- #define MAKE_SEC_WRITER_FRIEND \
- friend class SectionWriter; \
- friend class IHexSectionWriterBase; \
- friend class IHexSectionWriter; \
- template <class ELFT> friend class ELFSectionWriter; \
- template <class ELFT> friend class ELFSectionSizer;
- class BinarySectionWriter : public SectionWriter {
- public:
- virtual ~BinarySectionWriter() {}
- Error visit(const SymbolTableSection &Sec) override;
- Error visit(const RelocationSection &Sec) override;
- Error visit(const GnuDebugLinkSection &Sec) override;
- Error visit(const GroupSection &Sec) override;
- Error visit(const SectionIndexSection &Sec) override;
- Error visit(const CompressedSection &Sec) override;
- Error visit(const DecompressedSection &Sec) override;
- explicit BinarySectionWriter(WritableMemoryBuffer &Buf)
- : SectionWriter(Buf) {}
- };
- using IHexLineData = SmallVector<char, 64>;
- struct IHexRecord {
- // Memory address of the record.
- uint16_t Addr;
- // Record type (see below).
- uint16_t Type;
- // Record data in hexadecimal form.
- StringRef HexData;
- // Helper method to get file length of the record
- // including newline character
- static size_t getLength(size_t DataSize) {
- // :LLAAAATT[DD...DD]CC'
- return DataSize * 2 + 11;
- }
- // Gets length of line in a file (getLength + CRLF).
- static size_t getLineLength(size_t DataSize) {
- return getLength(DataSize) + 2;
- }
- // Given type, address and data returns line which can
- // be written to output file.
- static IHexLineData getLine(uint8_t Type, uint16_t Addr,
- ArrayRef<uint8_t> Data);
- // Parses the line and returns record if possible.
- // Line should be trimmed from whitespace characters.
- static Expected<IHexRecord> parse(StringRef Line);
- // Calculates checksum of stringified record representation
- // S must NOT contain leading ':' and trailing whitespace
- // characters
- static uint8_t getChecksum(StringRef S);
- enum Type {
- // Contains data and a 16-bit starting address for the data.
- // The byte count specifies number of data bytes in the record.
- Data = 0,
- // Must occur exactly once per file in the last line of the file.
- // The data field is empty (thus byte count is 00) and the address
- // field is typically 0000.
- EndOfFile = 1,
- // The data field contains a 16-bit segment base address (thus byte
- // count is always 02) compatible with 80x86 real mode addressing.
- // The address field (typically 0000) is ignored. The segment address
- // from the most recent 02 record is multiplied by 16 and added to each
- // subsequent data record address to form the physical starting address
- // for the data. This allows addressing up to one megabyte of address
- // space.
- SegmentAddr = 2,
- // or 80x86 processors, specifies the initial content of the CS:IP
- // registers. The address field is 0000, the byte count is always 04,
- // the first two data bytes are the CS value, the latter two are the
- // IP value.
- StartAddr80x86 = 3,
- // Allows for 32 bit addressing (up to 4GiB). The record's address field
- // is ignored (typically 0000) and its byte count is always 02. The two
- // data bytes (big endian) specify the upper 16 bits of the 32 bit
- // absolute address for all subsequent type 00 records
- ExtendedAddr = 4,
- // The address field is 0000 (not used) and the byte count is always 04.
- // The four data bytes represent a 32-bit address value. In the case of
- // 80386 and higher CPUs, this address is loaded into the EIP register.
- StartAddr = 5,
- // We have no other valid types
- InvalidType = 6
- };
- };
- // Base class for IHexSectionWriter. This class implements writing algorithm,
- // but doesn't actually write records. It is used for output buffer size
- // calculation in IHexWriter::finalize.
- class IHexSectionWriterBase : public BinarySectionWriter {
- // 20-bit segment address
- uint32_t SegmentAddr = 0;
- // Extended linear address
- uint32_t BaseAddr = 0;
- // Write segment address corresponding to 'Addr'
- uint64_t writeSegmentAddr(uint64_t Addr);
- // Write extended linear (base) address corresponding to 'Addr'
- uint64_t writeBaseAddr(uint64_t Addr);
- protected:
- // Offset in the output buffer
- uint64_t Offset = 0;
- void writeSection(const SectionBase *Sec, ArrayRef<uint8_t> Data);
- virtual void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data);
- public:
- explicit IHexSectionWriterBase(WritableMemoryBuffer &Buf)
- : BinarySectionWriter(Buf) {}
- uint64_t getBufferOffset() const { return Offset; }
- Error visit(const Section &Sec) final;
- Error visit(const OwnedDataSection &Sec) final;
- Error visit(const StringTableSection &Sec) override;
- Error visit(const DynamicRelocationSection &Sec) final;
- using BinarySectionWriter::visit;
- };
- // Real IHEX section writer
- class IHexSectionWriter : public IHexSectionWriterBase {
- public:
- IHexSectionWriter(WritableMemoryBuffer &Buf) : IHexSectionWriterBase(Buf) {}
- void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data) override;
- Error visit(const StringTableSection &Sec) override;
- };
- class Writer {
- protected:
- Object &Obj;
- std::unique_ptr<WritableMemoryBuffer> Buf;
- raw_ostream &Out;
- public:
- virtual ~Writer();
- virtual Error finalize() = 0;
- virtual Error write() = 0;
- Writer(Object &O, raw_ostream &Out) : Obj(O), Out(Out) {}
- };
- template <class ELFT> class ELFWriter : public Writer {
- private:
- using Elf_Addr = typename ELFT::Addr;
- using Elf_Shdr = typename ELFT::Shdr;
- using Elf_Phdr = typename ELFT::Phdr;
- using Elf_Ehdr = typename ELFT::Ehdr;
- void initEhdrSegment();
- void writeEhdr();
- void writePhdr(const Segment &Seg);
- void writeShdr(const SectionBase &Sec);
- void writePhdrs();
- void writeShdrs();
- Error writeSectionData();
- void writeSegmentData();
- void assignOffsets();
- std::unique_ptr<ELFSectionWriter<ELFT>> SecWriter;
- size_t totalSize() const;
- public:
- virtual ~ELFWriter() {}
- bool WriteSectionHeaders;
- // For --only-keep-debug, select an alternative section/segment layout
- // algorithm.
- bool OnlyKeepDebug;
- Error finalize() override;
- Error write() override;
- ELFWriter(Object &Obj, raw_ostream &Out, bool WSH, bool OnlyKeepDebug);
- };
- class BinaryWriter : public Writer {
- private:
- std::unique_ptr<BinarySectionWriter> SecWriter;
- uint64_t TotalSize = 0;
- public:
- ~BinaryWriter() {}
- Error finalize() override;
- Error write() override;
- BinaryWriter(Object &Obj, raw_ostream &Out) : Writer(Obj, Out) {}
- };
- class IHexWriter : public Writer {
- struct SectionCompare {
- bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const;
- };
- std::set<const SectionBase *, SectionCompare> Sections;
- size_t TotalSize = 0;
- Error checkSection(const SectionBase &Sec);
- uint64_t writeEntryPointRecord(uint8_t *Buf);
- uint64_t writeEndOfFileRecord(uint8_t *Buf);
- public:
- ~IHexWriter() {}
- Error finalize() override;
- Error write() override;
- IHexWriter(Object &Obj, raw_ostream &Out) : Writer(Obj, Out) {}
- };
- class SectionBase {
- public:
- std::string Name;
- Segment *ParentSegment = nullptr;
- uint64_t HeaderOffset = 0;
- uint32_t Index = 0;
- uint32_t OriginalIndex = 0;
- uint64_t OriginalFlags = 0;
- uint64_t OriginalType = ELF::SHT_NULL;
- uint64_t OriginalOffset = std::numeric_limits<uint64_t>::max();
- uint64_t Addr = 0;
- uint64_t Align = 1;
- uint32_t EntrySize = 0;
- uint64_t Flags = 0;
- uint64_t Info = 0;
- uint64_t Link = ELF::SHN_UNDEF;
- uint64_t NameIndex = 0;
- uint64_t Offset = 0;
- uint64_t Size = 0;
- uint64_t Type = ELF::SHT_NULL;
- ArrayRef<uint8_t> OriginalData;
- bool HasSymbol = false;
- SectionBase() = default;
- SectionBase(const SectionBase &) = default;
- virtual ~SectionBase() = default;
- virtual Error initialize(SectionTableRef SecTable);
- virtual void finalize();
- // Remove references to these sections. The list of sections must be sorted.
- virtual Error
- removeSectionReferences(bool AllowBrokenLinks,
- function_ref<bool(const SectionBase *)> ToRemove);
- virtual Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
- virtual Error accept(SectionVisitor &Visitor) const = 0;
- virtual Error accept(MutableSectionVisitor &Visitor) = 0;
- virtual void markSymbols();
- virtual void
- replaceSectionReferences(const DenseMap<SectionBase *, SectionBase *> &);
- virtual bool hasContents() const { return false; }
- // Notify the section that it is subject to removal.
- virtual void onRemove();
- };
- class Segment {
- private:
- struct SectionCompare {
- bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const {
- // Some sections might have the same address if one of them is empty. To
- // fix this we can use the lexicographic ordering on ->Addr and the
- // original index.
- if (Lhs->OriginalOffset == Rhs->OriginalOffset)
- return Lhs->OriginalIndex < Rhs->OriginalIndex;
- return Lhs->OriginalOffset < Rhs->OriginalOffset;
- }
- };
- public:
- uint32_t Type = 0;
- uint32_t Flags = 0;
- uint64_t Offset = 0;
- uint64_t VAddr = 0;
- uint64_t PAddr = 0;
- uint64_t FileSize = 0;
- uint64_t MemSize = 0;
- uint64_t Align = 0;
- uint32_t Index = 0;
- uint64_t OriginalOffset = 0;
- Segment *ParentSegment = nullptr;
- ArrayRef<uint8_t> Contents;
- std::set<const SectionBase *, SectionCompare> Sections;
- explicit Segment(ArrayRef<uint8_t> Data) : Contents(Data) {}
- Segment() = default;
- const SectionBase *firstSection() const {
- if (!Sections.empty())
- return *Sections.begin();
- return nullptr;
- }
- void removeSection(const SectionBase *Sec) { Sections.erase(Sec); }
- void addSection(const SectionBase *Sec) { Sections.insert(Sec); }
- ArrayRef<uint8_t> getContents() const { return Contents; }
- };
- class Section : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
- ArrayRef<uint8_t> Contents;
- SectionBase *LinkSection = nullptr;
- public:
- explicit Section(ArrayRef<uint8_t> Data) : Contents(Data) {}
- Error accept(SectionVisitor &Visitor) const override;
- Error accept(MutableSectionVisitor &Visitor) override;
- Error removeSectionReferences(
- bool AllowBrokenLinks,
- function_ref<bool(const SectionBase *)> ToRemove) override;
- Error initialize(SectionTableRef SecTable) override;
- void finalize() override;
- bool hasContents() const override {
- return Type != ELF::SHT_NOBITS && Type != ELF::SHT_NULL;
- }
- };
- class OwnedDataSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
- std::vector<uint8_t> Data;
- public:
- OwnedDataSection(StringRef SecName, ArrayRef<uint8_t> Data)
- : Data(std::begin(Data), std::end(Data)) {
- Name = SecName.str();
- Type = OriginalType = ELF::SHT_PROGBITS;
- Size = Data.size();
- OriginalOffset = std::numeric_limits<uint64_t>::max();
- }
- OwnedDataSection(const Twine &SecName, uint64_t SecAddr, uint64_t SecFlags,
- uint64_t SecOff) {
- Name = SecName.str();
- Type = OriginalType = ELF::SHT_PROGBITS;
- Addr = SecAddr;
- Flags = OriginalFlags = SecFlags;
- OriginalOffset = SecOff;
- }
- OwnedDataSection(SectionBase &S, ArrayRef<uint8_t> Data)
- : SectionBase(S), Data(std::begin(Data), std::end(Data)) {
- Size = Data.size();
- }
- void appendHexData(StringRef HexData);
- Error accept(SectionVisitor &Sec) const override;
- Error accept(MutableSectionVisitor &Visitor) override;
- bool hasContents() const override { return true; }
- };
- class CompressedSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
- DebugCompressionType CompressionType;
- uint64_t DecompressedSize;
- uint64_t DecompressedAlign;
- SmallVector<char, 128> CompressedData;
- public:
- static Expected<CompressedSection>
- create(const SectionBase &Sec, DebugCompressionType CompressionType);
- static Expected<CompressedSection> create(ArrayRef<uint8_t> CompressedData,
- uint64_t DecompressedSize,
- uint64_t DecompressedAlign);
- uint64_t getDecompressedSize() const { return DecompressedSize; }
- uint64_t getDecompressedAlign() const { return DecompressedAlign; }
- Error accept(SectionVisitor &Visitor) const override;
- Error accept(MutableSectionVisitor &Visitor) override;
- static bool classof(const SectionBase *S) {
- return (S->OriginalFlags & ELF::SHF_COMPRESSED) ||
- (StringRef(S->Name).startswith(".zdebug"));
- }
- private:
- CompressedSection(const SectionBase &Sec,
- DebugCompressionType CompressionType, Error &Err);
- CompressedSection(ArrayRef<uint8_t> CompressedData, uint64_t DecompressedSize,
- uint64_t DecompressedAlign);
- };
- class DecompressedSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
- public:
- explicit DecompressedSection(const CompressedSection &Sec)
- : SectionBase(Sec) {
- Size = Sec.getDecompressedSize();
- Align = Sec.getDecompressedAlign();
- Flags = OriginalFlags = (Flags & ~ELF::SHF_COMPRESSED);
- if (StringRef(Name).startswith(".zdebug"))
- Name = "." + Name.substr(2);
- }
- Error accept(SectionVisitor &Visitor) const override;
- Error accept(MutableSectionVisitor &Visitor) override;
- };
- // There are two types of string tables that can exist, dynamic and not dynamic.
- // In the dynamic case the string table is allocated. Changing a dynamic string
- // table would mean altering virtual addresses and thus the memory image. So
- // dynamic string tables should not have an interface to modify them or
- // reconstruct them. This type lets us reconstruct a string table. To avoid
- // this class being used for dynamic string tables (which has happened) the
- // 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
- StringTableBuilder StrTabBuilder;
- public:
- StringTableSection() : StrTabBuilder(StringTableBuilder::ELF) {
- Type = OriginalType = ELF::SHT_STRTAB;
- }
- void addString(StringRef Name);
- uint32_t findIndex(StringRef Name) const;
- void prepareForLayout();
- Error accept(SectionVisitor &Visitor) const override;
- Error accept(MutableSectionVisitor &Visitor) override;
- static bool classof(const SectionBase *S) {
- if (S->OriginalFlags & ELF::SHF_ALLOC)
- return false;
- return S->OriginalType == ELF::SHT_STRTAB;
- }
- };
- // Symbols have a st_shndx field that normally stores an index but occasionally
- // stores a different special value. This enum keeps track of what the st_shndx
- // field means. Most of the values are just copies of the special SHN_* values.
- // SYMBOL_SIMPLE_INDEX means that the st_shndx is just an index of a section.
- enum SymbolShndxType {
- SYMBOL_SIMPLE_INDEX = 0,
- SYMBOL_ABS = ELF::SHN_ABS,
- SYMBOL_COMMON = ELF::SHN_COMMON,
- SYMBOL_LOPROC = ELF::SHN_LOPROC,
- SYMBOL_AMDGPU_LDS = ELF::SHN_AMDGPU_LDS,
- SYMBOL_HEXAGON_SCOMMON = ELF::SHN_HEXAGON_SCOMMON,
- SYMBOL_HEXAGON_SCOMMON_2 = ELF::SHN_HEXAGON_SCOMMON_2,
- SYMBOL_HEXAGON_SCOMMON_4 = ELF::SHN_HEXAGON_SCOMMON_4,
- SYMBOL_HEXAGON_SCOMMON_8 = ELF::SHN_HEXAGON_SCOMMON_8,
- SYMBOL_HIPROC = ELF::SHN_HIPROC,
- SYMBOL_LOOS = ELF::SHN_LOOS,
- SYMBOL_HIOS = ELF::SHN_HIOS,
- SYMBOL_XINDEX = ELF::SHN_XINDEX,
- };
- struct Symbol {
- uint8_t Binding;
- SectionBase *DefinedIn = nullptr;
- SymbolShndxType ShndxType;
- uint32_t Index;
- std::string Name;
- uint32_t NameIndex;
- uint64_t Size;
- uint8_t Type;
- uint64_t Value;
- uint8_t Visibility;
- bool Referenced = false;
- uint16_t getShndx() const;
- bool isCommon() const;
- };
- class SectionIndexSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
- private:
- std::vector<uint32_t> Indexes;
- SymbolTableSection *Symbols = nullptr;
- public:
- virtual ~SectionIndexSection() {}
- void addIndex(uint32_t Index) {
- assert(Size > 0);
- Indexes.push_back(Index);
- }
- void reserve(size_t NumSymbols) {
- Indexes.reserve(NumSymbols);
- Size = NumSymbols * 4;
- }
- void setSymTab(SymbolTableSection *SymTab) { Symbols = SymTab; }
- Error initialize(SectionTableRef SecTable) override;
- void finalize() override;
- Error accept(SectionVisitor &Visitor) const override;
- Error accept(MutableSectionVisitor &Visitor) override;
- SectionIndexSection() {
- Name = ".symtab_shndx";
- Align = 4;
- EntrySize = 4;
- Type = OriginalType = ELF::SHT_SYMTAB_SHNDX;
- }
- };
- class SymbolTableSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
- void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; }
- void assignIndices();
- protected:
- std::vector<std::unique_ptr<Symbol>> Symbols;
- StringTableSection *SymbolNames = nullptr;
- SectionIndexSection *SectionIndexTable = nullptr;
- using SymPtr = std::unique_ptr<Symbol>;
- public:
- SymbolTableSection() { Type = OriginalType = ELF::SHT_SYMTAB; }
- void addSymbol(Twine Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn,
- uint64_t Value, uint8_t Visibility, uint16_t Shndx,
- uint64_t SymbolSize);
- void prepareForLayout();
- // An 'empty' symbol table still contains a null symbol.
- bool empty() const { return Symbols.size() == 1; }
- void setShndxTable(SectionIndexSection *ShndxTable) {
- SectionIndexTable = ShndxTable;
- }
- const SectionIndexSection *getShndxTable() const { return SectionIndexTable; }
- void fillShndxTable();
- const SectionBase *getStrTab() const { return SymbolNames; }
- Expected<const Symbol *> getSymbolByIndex(uint32_t Index) const;
- Expected<Symbol *> getSymbolByIndex(uint32_t Index);
- void updateSymbols(function_ref<void(Symbol &)> Callable);
- Error removeSectionReferences(
- bool AllowBrokenLinks,
- function_ref<bool(const SectionBase *)> ToRemove) override;
- Error initialize(SectionTableRef SecTable) override;
- void finalize() override;
- Error accept(SectionVisitor &Visitor) const override;
- Error accept(MutableSectionVisitor &Visitor) override;
- Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
- void replaceSectionReferences(
- const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
- static bool classof(const SectionBase *S) {
- return S->OriginalType == ELF::SHT_SYMTAB;
- }
- };
- struct Relocation {
- Symbol *RelocSymbol = nullptr;
- uint64_t Offset;
- uint64_t Addend;
- uint32_t Type;
- };
- // All relocation sections denote relocations to apply to another section.
- // However, some relocation sections use a dynamic symbol table and others use
- // a regular symbol table. Because the types of the two symbol tables differ in
- // our system (because they should behave differently) we can't uniformly
- // represent all relocations with the same base class if we expose an interface
- // that mentions the symbol table type. So we split the two base types into two
- // different classes, one which handles the section the relocation is applied to
- // and another which handles the symbol table type. The symbol table type is
- // taken as a type parameter to the class (see RelocSectionWithSymtabBase).
- class RelocationSectionBase : public SectionBase {
- protected:
- SectionBase *SecToApplyRel = nullptr;
- public:
- const SectionBase *getSection() const { return SecToApplyRel; }
- void setSection(SectionBase *Sec) { SecToApplyRel = Sec; }
- StringRef getNamePrefix() const;
- static bool classof(const SectionBase *S) {
- return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;
- }
- };
- // Takes the symbol table type to use as a parameter so that we can deduplicate
- // that code between the two symbol table types.
- template <class SymTabType>
- class RelocSectionWithSymtabBase : public RelocationSectionBase {
- void setSymTab(SymTabType *SymTab) { Symbols = SymTab; }
- protected:
- RelocSectionWithSymtabBase() = default;
- SymTabType *Symbols = nullptr;
- public:
- Error initialize(SectionTableRef SecTable) override;
- void finalize() override;
- };
- class RelocationSection
- : public RelocSectionWithSymtabBase<SymbolTableSection> {
- MAKE_SEC_WRITER_FRIEND
- std::vector<Relocation> Relocations;
- const Object &Obj;
- public:
- RelocationSection(const Object &O) : Obj(O) {}
- void addRelocation(Relocation Rel) { Relocations.push_back(Rel); }
- Error accept(SectionVisitor &Visitor) const override;
- Error accept(MutableSectionVisitor &Visitor) override;
- Error removeSectionReferences(
- bool AllowBrokenLinks,
- function_ref<bool(const SectionBase *)> ToRemove) override;
- Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
- void markSymbols() override;
- void replaceSectionReferences(
- const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
- const Object &getObject() const { return Obj; }
- static bool classof(const SectionBase *S) {
- if (S->OriginalFlags & ELF::SHF_ALLOC)
- return false;
- return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;
- }
- };
- // TODO: The way stripping and groups interact is complicated
- // and still needs to be worked on.
- class GroupSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
- const SymbolTableSection *SymTab = nullptr;
- Symbol *Sym = nullptr;
- ELF::Elf32_Word FlagWord;
- SmallVector<SectionBase *, 3> GroupMembers;
- public:
- // TODO: Contents is present in several classes of the hierarchy.
- // This needs to be refactored to avoid duplication.
- ArrayRef<uint8_t> Contents;
- explicit GroupSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
- void setSymTab(const SymbolTableSection *SymTabSec) { SymTab = SymTabSec; }
- void setSymbol(Symbol *S) { Sym = S; }
- void setFlagWord(ELF::Elf32_Word W) { FlagWord = W; }
- void addMember(SectionBase *Sec) { GroupMembers.push_back(Sec); }
- Error accept(SectionVisitor &) const override;
- Error accept(MutableSectionVisitor &Visitor) override;
- void finalize() override;
- Error removeSectionReferences(
- bool AllowBrokenLinks,
- function_ref<bool(const SectionBase *)> ToRemove) override;
- Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
- void markSymbols() override;
- void replaceSectionReferences(
- const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
- void onRemove() override;
- static bool classof(const SectionBase *S) {
- return S->OriginalType == ELF::SHT_GROUP;
- }
- };
- class DynamicSymbolTableSection : public Section {
- public:
- explicit DynamicSymbolTableSection(ArrayRef<uint8_t> Data) : Section(Data) {}
- static bool classof(const SectionBase *S) {
- return S->OriginalType == ELF::SHT_DYNSYM;
- }
- };
- class DynamicSection : public Section {
- public:
- explicit DynamicSection(ArrayRef<uint8_t> Data) : Section(Data) {}
- static bool classof(const SectionBase *S) {
- return S->OriginalType == ELF::SHT_DYNAMIC;
- }
- };
- class DynamicRelocationSection
- : public RelocSectionWithSymtabBase<DynamicSymbolTableSection> {
- MAKE_SEC_WRITER_FRIEND
- private:
- ArrayRef<uint8_t> Contents;
- public:
- explicit DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
- Error accept(SectionVisitor &) const override;
- Error accept(MutableSectionVisitor &Visitor) override;
- Error removeSectionReferences(
- bool AllowBrokenLinks,
- function_ref<bool(const SectionBase *)> ToRemove) override;
- static bool classof(const SectionBase *S) {
- if (!(S->OriginalFlags & ELF::SHF_ALLOC))
- return false;
- return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;
- }
- };
- class GnuDebugLinkSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
- private:
- StringRef FileName;
- uint32_t CRC32;
- void init(StringRef File);
- public:
- // If we add this section from an external source we can use this ctor.
- explicit GnuDebugLinkSection(StringRef File, uint32_t PrecomputedCRC);
- Error accept(SectionVisitor &Visitor) const override;
- Error accept(MutableSectionVisitor &Visitor) override;
- };
- class Reader {
- public:
- virtual ~Reader();
- virtual Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const = 0;
- };
- using object::Binary;
- using object::ELFFile;
- using object::ELFObjectFile;
- using object::OwningBinary;
- class BasicELFBuilder {
- protected:
- std::unique_ptr<Object> Obj;
- void initFileHeader();
- void initHeaderSegment();
- StringTableSection *addStrTab();
- SymbolTableSection *addSymTab(StringTableSection *StrTab);
- Error initSections();
- public:
- BasicELFBuilder() : Obj(std::make_unique<Object>()) {}
- };
- class BinaryELFBuilder : public BasicELFBuilder {
- MemoryBuffer *MemBuf;
- uint8_t NewSymbolVisibility;
- void addData(SymbolTableSection *SymTab);
- public:
- BinaryELFBuilder(MemoryBuffer *MB, uint8_t NewSymbolVisibility)
- : MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {}
- Expected<std::unique_ptr<Object>> build();
- };
- class IHexELFBuilder : public BasicELFBuilder {
- const std::vector<IHexRecord> &Records;
- void addDataSections();
- public:
- IHexELFBuilder(const std::vector<IHexRecord> &Records) : Records(Records) {}
- Expected<std::unique_ptr<Object>> build();
- };
- template <class ELFT> class ELFBuilder {
- private:
- using Elf_Addr = typename ELFT::Addr;
- using Elf_Shdr = typename ELFT::Shdr;
- using Elf_Word = typename ELFT::Word;
- const ELFFile<ELFT> &ElfFile;
- Object &Obj;
- size_t EhdrOffset = 0;
- Optional<StringRef> ExtractPartition;
- void setParentSegment(Segment &Child);
- Error readProgramHeaders(const ELFFile<ELFT> &HeadersFile);
- Error initGroupSection(GroupSection *GroupSec);
- Error initSymbolTable(SymbolTableSection *SymTab);
- Error readSectionHeaders();
- Error readSections(bool EnsureSymtab);
- Error findEhdrOffset();
- Expected<SectionBase &> makeSection(const Elf_Shdr &Shdr);
- public:
- ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,
- Optional<StringRef> ExtractPartition);
- Error build(bool EnsureSymtab);
- };
- class BinaryReader : public Reader {
- MemoryBuffer *MemBuf;
- uint8_t NewSymbolVisibility;
- public:
- BinaryReader(MemoryBuffer *MB, const uint8_t NewSymbolVisibility)
- : MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {}
- Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;
- };
- class IHexReader : public Reader {
- MemoryBuffer *MemBuf;
- Expected<std::vector<IHexRecord>> parse() const;
- Error parseError(size_t LineNo, Error E) const {
- return LineNo == -1U
- ? createFileError(MemBuf->getBufferIdentifier(), std::move(E))
- : createFileError(MemBuf->getBufferIdentifier(), LineNo,
- std::move(E));
- }
- template <typename... Ts>
- Error parseError(size_t LineNo, char const *Fmt, const Ts &... Vals) const {
- Error E = createStringError(errc::invalid_argument, Fmt, Vals...);
- return parseError(LineNo, std::move(E));
- }
- public:
- IHexReader(MemoryBuffer *MB) : MemBuf(MB) {}
- Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;
- };
- class ELFReader : public Reader {
- Binary *Bin;
- Optional<StringRef> ExtractPartition;
- public:
- Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;
- explicit ELFReader(Binary *B, Optional<StringRef> ExtractPartition)
- : Bin(B), ExtractPartition(ExtractPartition) {}
- };
- class Object {
- private:
- using SecPtr = std::unique_ptr<SectionBase>;
- using SegPtr = std::unique_ptr<Segment>;
- std::vector<SecPtr> Sections;
- std::vector<SegPtr> Segments;
- std::vector<SecPtr> RemovedSections;
- DenseMap<SectionBase *, std::vector<uint8_t>> UpdatedSections;
- static bool sectionIsAlloc(const SectionBase &Sec) {
- return Sec.Flags & ELF::SHF_ALLOC;
- };
- public:
- template <class T>
- using ConstRange = iterator_range<pointee_iterator<
- typename std::vector<std::unique_ptr<T>>::const_iterator>>;
- // It is often the case that the ELF header and the program header table are
- // not present in any segment. This could be a problem during file layout,
- // because other segments may get assigned an offset where either of the
- // two should reside, which will effectively corrupt the resulting binary.
- // Other than that we use these segments to track program header offsets
- // when they may not follow the ELF header.
- Segment ElfHdrSegment;
- Segment ProgramHdrSegment;
- uint8_t OSABI;
- uint8_t ABIVersion;
- uint64_t Entry;
- uint64_t SHOff;
- uint32_t Type;
- uint32_t Machine;
- uint32_t Version;
- uint32_t Flags;
- bool HadShdrs = true;
- bool MustBeRelocatable = false;
- StringTableSection *SectionNames = nullptr;
- SymbolTableSection *SymbolTable = nullptr;
- SectionIndexSection *SectionIndexTable = nullptr;
- bool IsMips64EL = false;
- SectionTableRef sections() const { return SectionTableRef(Sections); }
- iterator_range<
- filter_iterator<pointee_iterator<std::vector<SecPtr>::const_iterator>,
- decltype(§ionIsAlloc)>>
- allocSections() const {
- return make_filter_range(make_pointee_range(Sections), sectionIsAlloc);
- }
- const auto &getUpdatedSections() const { return UpdatedSections; }
- Error updateSection(StringRef Name, ArrayRef<uint8_t> Data);
- SectionBase *findSection(StringRef Name) {
- auto SecIt =
- find_if(Sections, [&](const SecPtr &Sec) { return Sec->Name == Name; });
- return SecIt == Sections.end() ? nullptr : SecIt->get();
- }
- SectionTableRef removedSections() { return SectionTableRef(RemovedSections); }
- ConstRange<Segment> segments() const { return make_pointee_range(Segments); }
- Error removeSections(bool AllowBrokenLinks,
- std::function<bool(const SectionBase &)> ToRemove);
- Error replaceSections(const DenseMap<SectionBase *, SectionBase *> &FromTo);
- Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
- template <class T, class... Ts> T &addSection(Ts &&... Args) {
- auto Sec = std::make_unique<T>(std::forward<Ts>(Args)...);
- auto Ptr = Sec.get();
- MustBeRelocatable |= isa<RelocationSection>(*Ptr);
- Sections.emplace_back(std::move(Sec));
- Ptr->Index = Sections.size();
- return *Ptr;
- }
- Error addNewSymbolTable();
- Segment &addSegment(ArrayRef<uint8_t> Data) {
- Segments.emplace_back(std::make_unique<Segment>(Data));
- return *Segments.back();
- }
- bool isRelocatable() const {
- return (Type != ELF::ET_DYN && Type != ELF::ET_EXEC) || MustBeRelocatable;
- }
- };
- } // end namespace elf
- } // end namespace objcopy
- } // end namespace llvm
- #endif // LLVM_TOOLS_OBJCOPY_OBJECT_H
|