12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112 |
- //===- ELFObject.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_LIB_OBJCOPY_ELF_ELFOBJECT_H
- #define LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_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/ObjCopy/CommonConfig.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;
- Error visit(const SymbolTableSection &Sec) override = 0;
- Error visit(const RelocationSection &Sec) override = 0;
- Error visit(const GnuDebugLinkSection &Sec) override = 0;
- Error visit(const GroupSection &Sec) override = 0;
- Error visit(const SectionIndexSection &Sec) override = 0;
- Error visit(const CompressedSection &Sec) override = 0;
- 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
- uint32_t ChType = 0;
- DebugCompressionType CompressionType;
- uint64_t DecompressedSize;
- uint64_t DecompressedAlign;
- SmallVector<uint8_t, 128> CompressedData;
- public:
- CompressedSection(const SectionBase &Sec,
- DebugCompressionType CompressionType, bool Is64Bits);
- CompressedSection(ArrayRef<uint8_t> CompressedData, uint32_t ChType,
- uint64_t DecompressedSize, uint64_t DecompressedAlign);
- uint64_t getDecompressedSize() const { return DecompressedSize; }
- uint64_t getDecompressedAlign() const { return DecompressedAlign; }
- uint64_t getChType() const { return ChType; }
- Error accept(SectionVisitor &Visitor) const override;
- Error accept(MutableSectionVisitor &Visitor) override;
- static bool classof(const SectionBase *S) {
- return S->OriginalFlags & ELF::SHF_COMPRESSED;
- }
- };
- class DecompressedSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
- public:
- uint32_t ChType;
- explicit DecompressedSection(const CompressedSection &Sec)
- : SectionBase(Sec), ChType(Sec.getChType()) {
- Size = Sec.getDecompressedSize();
- Align = Sec.getDecompressedAlign();
- Flags = OriginalFlags = (Flags & ~ELF::SHF_COMPRESSED);
- }
- 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_MIPS_ACOMMON = ELF::SHN_MIPS_ACOMMON,
- SYMBOL_MIPS_TEXT = ELF::SHN_MIPS_TEXT,
- SYMBOL_MIPS_DATA = ELF::SHN_MIPS_DATA,
- SYMBOL_MIPS_SCOMMON = ELF::SHN_MIPS_SCOMMON,
- SYMBOL_MIPS_SUNDEFINED = ELF::SHN_MIPS_SUNDEFINED,
- 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;
- std::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,
- std::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;
- std::optional<StringRef> ExtractPartition;
- public:
- Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;
- explicit ELFReader(Binary *B, std::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;
- bool Is64Bits;
- 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_LIB_OBJCOPY_ELF_ELFOBJECT_H
|