brintos

brintos / llvm-project-archived public Read only

0
0
Text · 40.2 KiB · 2783ef2 Raw
1255 lines · c
1//===- ELFObject.h ----------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H10#define LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H11 12#include "llvm/ADT/ArrayRef.h"13#include "llvm/ADT/StringRef.h"14#include "llvm/ADT/Twine.h"15#include "llvm/BinaryFormat/ELF.h"16#include "llvm/MC/StringTableBuilder.h"17#include "llvm/ObjCopy/CommonConfig.h"18#include "llvm/Object/ELFObjectFile.h"19#include "llvm/Support/Errc.h"20#include "llvm/Support/FileOutputBuffer.h"21#include "llvm/Support/MemoryBuffer.h"22#include <cstddef>23#include <cstdint>24#include <functional>25#include <memory>26#include <set>27#include <vector>28 29namespace llvm {30enum class DebugCompressionType;31namespace objcopy {32namespace elf {33 34class SectionBase;35class Section;36class OwnedDataSection;37class StringTableSection;38class SymbolTableSection;39class RelocationSection;40class DynamicRelocationSection;41class GnuDebugLinkSection;42class GroupSection;43class SectionIndexSection;44class CompressedSection;45class DecompressedSection;46class Segment;47class Object;48struct Symbol;49 50class SectionTableRef {51  ArrayRef<std::unique_ptr<SectionBase>> Sections;52 53public:54  using iterator = pointee_iterator<const std::unique_ptr<SectionBase> *>;55 56  explicit SectionTableRef(ArrayRef<std::unique_ptr<SectionBase>> Secs)57      : Sections(Secs) {}58  SectionTableRef(const SectionTableRef &) = default;59 60  iterator begin() const { return iterator(Sections.data()); }61  iterator end() const { return iterator(Sections.data() + Sections.size()); }62  size_t size() const { return Sections.size(); }63 64  Expected<SectionBase *> getSection(uint32_t Index, Twine ErrMsg);65 66  template <class T>67  Expected<T *> getSectionOfType(uint32_t Index, Twine IndexErrMsg,68                                 Twine TypeErrMsg);69};70 71enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE };72 73class SectionVisitor {74public:75  virtual ~SectionVisitor() = default;76 77  virtual Error visit(const Section &Sec) = 0;78  virtual Error visit(const OwnedDataSection &Sec) = 0;79  virtual Error visit(const StringTableSection &Sec) = 0;80  virtual Error visit(const SymbolTableSection &Sec) = 0;81  virtual Error visit(const RelocationSection &Sec) = 0;82  virtual Error visit(const DynamicRelocationSection &Sec) = 0;83  virtual Error visit(const GnuDebugLinkSection &Sec) = 0;84  virtual Error visit(const GroupSection &Sec) = 0;85  virtual Error visit(const SectionIndexSection &Sec) = 0;86  virtual Error visit(const CompressedSection &Sec) = 0;87  virtual Error visit(const DecompressedSection &Sec) = 0;88};89 90class MutableSectionVisitor {91public:92  virtual ~MutableSectionVisitor() = default;93 94  virtual Error visit(Section &Sec) = 0;95  virtual Error visit(OwnedDataSection &Sec) = 0;96  virtual Error visit(StringTableSection &Sec) = 0;97  virtual Error visit(SymbolTableSection &Sec) = 0;98  virtual Error visit(RelocationSection &Sec) = 0;99  virtual Error visit(DynamicRelocationSection &Sec) = 0;100  virtual Error visit(GnuDebugLinkSection &Sec) = 0;101  virtual Error visit(GroupSection &Sec) = 0;102  virtual Error visit(SectionIndexSection &Sec) = 0;103  virtual Error visit(CompressedSection &Sec) = 0;104  virtual Error visit(DecompressedSection &Sec) = 0;105};106 107class SectionWriter : public SectionVisitor {108protected:109  WritableMemoryBuffer &Out;110 111public:112  ~SectionWriter() override = default;113 114  Error visit(const Section &Sec) override;115  Error visit(const OwnedDataSection &Sec) override;116  Error visit(const StringTableSection &Sec) override;117  Error visit(const DynamicRelocationSection &Sec) override;118  Error visit(const SymbolTableSection &Sec) override = 0;119  Error visit(const RelocationSection &Sec) override = 0;120  Error visit(const GnuDebugLinkSection &Sec) override = 0;121  Error visit(const GroupSection &Sec) override = 0;122  Error visit(const SectionIndexSection &Sec) override = 0;123  Error visit(const CompressedSection &Sec) override = 0;124  Error visit(const DecompressedSection &Sec) override = 0;125 126  explicit SectionWriter(WritableMemoryBuffer &Buf) : Out(Buf) {}127};128 129template <class ELFT> class ELFSectionWriter : public SectionWriter {130private:131  using Elf_Word = typename ELFT::Word;132  using Elf_Rel = typename ELFT::Rel;133  using Elf_Rela = typename ELFT::Rela;134  using Elf_Sym = typename ELFT::Sym;135 136public:137  ~ELFSectionWriter() override = default;138  Error visit(const SymbolTableSection &Sec) override;139  Error visit(const RelocationSection &Sec) override;140  Error visit(const GnuDebugLinkSection &Sec) override;141  Error visit(const GroupSection &Sec) override;142  Error visit(const SectionIndexSection &Sec) override;143  Error visit(const CompressedSection &Sec) override;144  Error visit(const DecompressedSection &Sec) override;145 146  explicit ELFSectionWriter(WritableMemoryBuffer &Buf) : SectionWriter(Buf) {}147};148 149template <class ELFT> class ELFSectionSizer : public MutableSectionVisitor {150private:151  using Elf_Rel = typename ELFT::Rel;152  using Elf_Rela = typename ELFT::Rela;153  using Elf_Sym = typename ELFT::Sym;154  using Elf_Word = typename ELFT::Word;155  using Elf_Xword = typename ELFT::Xword;156 157public:158  Error visit(Section &Sec) override;159  Error visit(OwnedDataSection &Sec) override;160  Error visit(StringTableSection &Sec) override;161  Error visit(DynamicRelocationSection &Sec) override;162  Error visit(SymbolTableSection &Sec) override;163  Error visit(RelocationSection &Sec) override;164  Error visit(GnuDebugLinkSection &Sec) override;165  Error visit(GroupSection &Sec) override;166  Error visit(SectionIndexSection &Sec) override;167  Error visit(CompressedSection &Sec) override;168  Error visit(DecompressedSection &Sec) override;169};170 171#define MAKE_SEC_WRITER_FRIEND                                                 \172  friend class SectionWriter;                                                  \173  friend class IHexSectionWriterBase;                                          \174  friend class IHexSectionWriter;                                              \175  friend class SRECSectionWriter;                                              \176  friend class SRECSectionWriterBase;                                          \177  friend class SRECSizeCalculator;                                             \178  template <class ELFT> friend class ELFSectionWriter;                         \179  template <class ELFT> friend class ELFSectionSizer;180 181class BinarySectionWriter : public SectionWriter {182public:183  ~BinarySectionWriter() override = default;184 185  Error visit(const SymbolTableSection &Sec) override;186  Error visit(const RelocationSection &Sec) override;187  Error visit(const GnuDebugLinkSection &Sec) override;188  Error visit(const GroupSection &Sec) override;189  Error visit(const SectionIndexSection &Sec) override;190  Error visit(const CompressedSection &Sec) override;191  Error visit(const DecompressedSection &Sec) override;192 193  explicit BinarySectionWriter(WritableMemoryBuffer &Buf)194      : SectionWriter(Buf) {}195};196 197using IHexLineData = SmallVector<char, 64>;198 199struct IHexRecord {200  // Memory address of the record.201  uint16_t Addr;202  // Record type (see below).203  uint16_t Type;204  // Record data in hexadecimal form.205  StringRef HexData;206 207  // Helper method to get file length of the record208  // including newline character209  static size_t getLength(size_t DataSize) {210    // :LLAAAATT[DD...DD]CC'211    return DataSize * 2 + 11;212  }213 214  // Gets length of line in a file (getLength + CRLF).215  static size_t getLineLength(size_t DataSize) {216    return getLength(DataSize) + 2;217  }218 219  // Given type, address and data returns line which can220  // be written to output file.221  static IHexLineData getLine(uint8_t Type, uint16_t Addr,222                              ArrayRef<uint8_t> Data);223 224  // Parses the line and returns record if possible.225  // Line should be trimmed from whitespace characters.226  static Expected<IHexRecord> parse(StringRef Line);227 228  // Calculates checksum of stringified record representation229  // S must NOT contain leading ':' and trailing whitespace230  // characters231  static uint8_t getChecksum(StringRef S);232 233  enum Type {234    // Contains data and a 16-bit starting address for the data.235    // The byte count specifies number of data bytes in the record.236    Data = 0,237    // Must occur exactly once per file in the last line of the file.238    // The data field is empty (thus byte count is 00) and the address239    // field is typically 0000.240    EndOfFile = 1,241    // The data field contains a 16-bit segment base address (thus byte242    // count is always 02) compatible with 80x86 real mode addressing.243    // The address field (typically 0000) is ignored. The segment address244    // from the most recent 02 record is multiplied by 16 and added to each245    // subsequent data record address to form the physical starting address246    // for the data. This allows addressing up to one megabyte of address247    // space.248    SegmentAddr = 2,249    // or 80x86 processors, specifies the initial content of the CS:IP250    // registers. The address field is 0000, the byte count is always 04,251    // the first two data bytes are the CS value, the latter two are the252    // IP value.253    StartAddr80x86 = 3,254    // Allows for 32 bit addressing (up to 4GiB). The record's address field255    // is ignored (typically 0000) and its byte count is always 02. The two256    // data bytes (big endian) specify the upper 16 bits of the 32 bit257    // absolute address for all subsequent type 00 records258    ExtendedAddr = 4,259    // The address field is 0000 (not used) and the byte count is always 04.260    // The four data bytes represent a 32-bit address value. In the case of261    // 80386 and higher CPUs, this address is loaded into the EIP register.262    StartAddr = 5,263    // We have no other valid types264    InvalidType = 6265  };266};267 268// Base class for IHexSectionWriter. This class implements writing algorithm,269// but doesn't actually write records. It is used for output buffer size270// calculation in IHexWriter::finalize.271class IHexSectionWriterBase : public BinarySectionWriter {272  // 20-bit segment address273  uint32_t SegmentAddr = 0;274  // Extended linear address275  uint32_t BaseAddr = 0;276 277  // Write segment address corresponding to 'Addr'278  uint64_t writeSegmentAddr(uint64_t Addr);279  // Write extended linear (base) address corresponding to 'Addr'280  uint64_t writeBaseAddr(uint64_t Addr);281 282protected:283  // Offset in the output buffer284  uint64_t Offset = 0;285 286  void writeSection(const SectionBase *Sec, ArrayRef<uint8_t> Data);287  virtual void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data);288 289public:290  explicit IHexSectionWriterBase(WritableMemoryBuffer &Buf)291      : BinarySectionWriter(Buf) {}292 293  uint64_t getBufferOffset() const { return Offset; }294  Error visit(const Section &Sec) final;295  Error visit(const OwnedDataSection &Sec) final;296  Error visit(const StringTableSection &Sec) override;297  Error visit(const DynamicRelocationSection &Sec) final;298  using BinarySectionWriter::visit;299};300 301// Real IHEX section writer302class IHexSectionWriter : public IHexSectionWriterBase {303public:304  IHexSectionWriter(WritableMemoryBuffer &Buf) : IHexSectionWriterBase(Buf) {}305 306  void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data) override;307  Error visit(const StringTableSection &Sec) override;308};309 310class Writer {311protected:312  Object &Obj;313  std::unique_ptr<WritableMemoryBuffer> Buf;314  raw_ostream &Out;315 316public:317  virtual ~Writer();318  virtual Error finalize() = 0;319  virtual Error write() = 0;320 321  Writer(Object &O, raw_ostream &Out) : Obj(O), Out(Out) {}322};323 324template <class ELFT> class ELFWriter : public Writer {325private:326  using Elf_Addr = typename ELFT::Addr;327  using Elf_Shdr = typename ELFT::Shdr;328  using Elf_Phdr = typename ELFT::Phdr;329  using Elf_Ehdr = typename ELFT::Ehdr;330 331  void initEhdrSegment();332 333  void writeEhdr();334  void writePhdr(const Segment &Seg);335  void writeShdr(const SectionBase &Sec);336 337  void writePhdrs();338  void writeShdrs();339  Error writeSectionData();340  void writeSegmentData();341 342  void assignOffsets();343 344  std::unique_ptr<ELFSectionWriter<ELFT>> SecWriter;345 346  size_t totalSize() const;347 348public:349  ~ELFWriter() override = default;350  bool WriteSectionHeaders;351 352  // For --only-keep-debug, select an alternative section/segment layout353  // algorithm.354  bool OnlyKeepDebug;355 356  Error finalize() override;357  Error write() override;358  ELFWriter(Object &Obj, raw_ostream &Out, bool WSH, bool OnlyKeepDebug);359};360 361class BinaryWriter : public Writer {362private:363  const uint8_t GapFill;364  const uint64_t PadTo;365  std::unique_ptr<BinarySectionWriter> SecWriter;366 367  uint64_t TotalSize = 0;368 369public:370  ~BinaryWriter() override = default;371  Error finalize() override;372  Error write() override;373  BinaryWriter(Object &Obj, raw_ostream &Out, const CommonConfig &Config)374      : Writer(Obj, Out), GapFill(Config.GapFill), PadTo(Config.PadTo) {}375};376 377// A base class for writing ascii hex formats such as srec and ihex.378class ASCIIHexWriter : public Writer {379public:380  ASCIIHexWriter(Object &Obj, raw_ostream &OS, StringRef OutputFile)381      : Writer(Obj, OS), OutputFileName(OutputFile) {}382  Error finalize() override;383 384protected:385  StringRef OutputFileName;386  size_t TotalSize = 0;387  std::vector<const SectionBase *> Sections;388 389  Error checkSection(const SectionBase &S) const;390  virtual Expected<size_t>391  getTotalSize(WritableMemoryBuffer &EmptyBuffer) const = 0;392};393 394class IHexWriter : public ASCIIHexWriter {395public:396  Error write() override;397  IHexWriter(Object &Obj, raw_ostream &Out, StringRef OutputFile)398      : ASCIIHexWriter(Obj, Out, OutputFile) {}399 400private:401  uint64_t writeEntryPointRecord(uint8_t *Buf);402  uint64_t writeEndOfFileRecord(uint8_t *Buf);403  Expected<size_t>404  getTotalSize(WritableMemoryBuffer &EmptyBuffer) const override;405};406 407class SRECWriter : public ASCIIHexWriter {408public:409  SRECWriter(Object &Obj, raw_ostream &OS, StringRef OutputFile)410      : ASCIIHexWriter(Obj, OS, OutputFile) {}411  Error write() override;412 413private:414  size_t writeHeader(uint8_t *Buf);415  size_t writeTerminator(uint8_t *Buf, uint8_t Type);416  Expected<size_t>417  getTotalSize(WritableMemoryBuffer &EmptyBuffer) const override;418};419 420using SRecLineData = SmallVector<char, 64>;421struct SRecord {422  uint8_t Type;423  uint32_t Address;424  ArrayRef<uint8_t> Data;425  SRecLineData toString() const;426  uint8_t getCount() const;427  // Get address size in characters.428  uint8_t getAddressSize() const;429  uint8_t getChecksum() const;430  size_t getSize() const;431  static SRecord getHeader(StringRef FileName);432  static uint8_t getType(uint32_t Address);433 434  enum Type : uint8_t {435    // Vendor specific text comment.436    S0 = 0,437    // Data that starts at a 16 bit address.438    S1 = 1,439    // Data that starts at a 24 bit address.440    S2 = 2,441    // Data that starts at a 32 bit address.442    S3 = 3,443    // Reserved.444    S4 = 4,445    // 16 bit count of S1/S2/S3 records (optional).446    S5 = 5,447    // 32 bit count of S1/S2/S3 records (optional).448    S6 = 6,449    // Terminates a series of S3 records.450    S7 = 7,451    // Terminates a series of S2 records.452    S8 = 8,453    // Terminates a series of S1 records.454    S9 = 9455  };456};457 458class SRECSectionWriterBase : public BinarySectionWriter {459public:460  explicit SRECSectionWriterBase(WritableMemoryBuffer &Buf,461                                 uint64_t StartOffset)462      : BinarySectionWriter(Buf), Offset(StartOffset), HeaderSize(StartOffset) {463  }464 465  using BinarySectionWriter::visit;466 467  void writeRecords(uint32_t Entry);468  uint64_t getBufferOffset() const { return Offset; }469  Error visit(const Section &S) override;470  Error visit(const OwnedDataSection &S) override;471  Error visit(const StringTableSection &S) override;472  Error visit(const DynamicRelocationSection &S) override;473  uint8_t getType() const { return Type; };474 475protected:476  // Offset in the output buffer.477  uint64_t Offset;478  // Sections start after the header.479  uint64_t HeaderSize;480  // Type of records to write.481  uint8_t Type = SRecord::S1;482  std::vector<SRecord> Records;483 484  void writeSection(const SectionBase &S, ArrayRef<uint8_t> Data);485  virtual void writeRecord(SRecord &Record, uint64_t Off) = 0;486};487 488// An SRECSectionWriterBase that visits sections but does not write anything.489// This class is only used to calculate the size of the output file.490class SRECSizeCalculator : public SRECSectionWriterBase {491public:492  SRECSizeCalculator(WritableMemoryBuffer &EmptyBuffer, uint64_t Offset)493      : SRECSectionWriterBase(EmptyBuffer, Offset) {}494 495protected:496  void writeRecord(SRecord &Record, uint64_t Off) override {}497};498 499class SRECSectionWriter : public SRECSectionWriterBase {500public:501  SRECSectionWriter(WritableMemoryBuffer &Buf, uint64_t Offset)502      : SRECSectionWriterBase(Buf, Offset) {}503  Error visit(const StringTableSection &Sec) override;504 505protected:506  void writeRecord(SRecord &Record, uint64_t Off) override;507};508 509class SectionBase {510public:511  std::string Name;512  Segment *ParentSegment = nullptr;513  uint64_t HeaderOffset = 0;514  uint32_t Index = 0;515 516  uint32_t OriginalIndex = 0;517  uint64_t OriginalFlags = 0;518  uint64_t OriginalType = ELF::SHT_NULL;519  uint64_t OriginalOffset = std::numeric_limits<uint64_t>::max();520 521  uint64_t Addr = 0;522  uint64_t Align = 1;523  uint32_t EntrySize = 0;524  uint64_t Flags = 0;525  uint64_t Info = 0;526  uint64_t Link = ELF::SHN_UNDEF;527  uint64_t NameIndex = 0;528  uint64_t Offset = 0;529  uint64_t Size = 0;530  uint64_t Type = ELF::SHT_NULL;531  ArrayRef<uint8_t> OriginalData;532  bool HasSymbol = false;533 534  SectionBase() = default;535  SectionBase(const SectionBase &) = default;536 537  virtual ~SectionBase() = default;538 539  virtual Error initialize(SectionTableRef SecTable);540  virtual void finalize();541  // Remove references to these sections. The list of sections must be sorted.542  virtual Error543  removeSectionReferences(bool AllowBrokenLinks,544                          function_ref<bool(const SectionBase *)> ToRemove);545  virtual Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);546  virtual Error accept(SectionVisitor &Visitor) const = 0;547  virtual Error accept(MutableSectionVisitor &Visitor) = 0;548  virtual void markSymbols();549  virtual void550  replaceSectionReferences(const DenseMap<SectionBase *, SectionBase *> &);551  virtual bool hasContents() const { return false; }552  virtual ArrayRef<uint8_t> getContents() const { return {}; }553  // Notify the section that it is subject to removal.554  virtual void onRemove();555 556  virtual void restoreSymTabLink(SymbolTableSection &) {}557};558 559class Segment {560private:561  struct SectionCompare {562    bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const {563      // Some sections might have the same address if one of them is empty. To564      // fix this we can use the lexicographic ordering on ->Addr and the565      // original index.566      if (Lhs->OriginalOffset == Rhs->OriginalOffset)567        return Lhs->OriginalIndex < Rhs->OriginalIndex;568      return Lhs->OriginalOffset < Rhs->OriginalOffset;569    }570  };571 572public:573  uint32_t Type = 0;574  uint32_t Flags = 0;575  uint64_t Offset = 0;576  uint64_t VAddr = 0;577  uint64_t PAddr = 0;578  uint64_t FileSize = 0;579  uint64_t MemSize = 0;580  uint64_t Align = 0;581 582  uint32_t Index = 0;583  uint64_t OriginalOffset = 0;584  Segment *ParentSegment = nullptr;585  ArrayRef<uint8_t> Contents;586  std::set<const SectionBase *, SectionCompare> Sections;587 588  explicit Segment(ArrayRef<uint8_t> Data) : Contents(Data) {}589  Segment() = default;590 591  const SectionBase *firstSection() const {592    if (!Sections.empty())593      return *Sections.begin();594    return nullptr;595  }596 597  void removeSection(const SectionBase *Sec) { Sections.erase(Sec); }598  void addSection(const SectionBase *Sec) { Sections.insert(Sec); }599 600  ArrayRef<uint8_t> getContents() const { return Contents; }601};602 603class Section : public SectionBase {604  MAKE_SEC_WRITER_FRIEND605 606  ArrayRef<uint8_t> Contents;607  SectionBase *LinkSection = nullptr;608  bool HasSymTabLink = false;609 610public:611  explicit Section(ArrayRef<uint8_t> Data) : Contents(Data) {}612 613  Error accept(SectionVisitor &Visitor) const override;614  Error accept(MutableSectionVisitor &Visitor) override;615  Error removeSectionReferences(616      bool AllowBrokenLinks,617      function_ref<bool(const SectionBase *)> ToRemove) override;618  Error initialize(SectionTableRef SecTable) override;619  void finalize() override;620  bool hasContents() const override {621    return Type != ELF::SHT_NOBITS && Type != ELF::SHT_NULL;622  }623  ArrayRef<uint8_t> getContents() const override { return Contents; }624 625  void restoreSymTabLink(SymbolTableSection &SymTab) override;626};627 628class OwnedDataSection : public SectionBase {629  MAKE_SEC_WRITER_FRIEND630 631  std::vector<uint8_t> Data;632 633public:634  OwnedDataSection(StringRef SecName, ArrayRef<uint8_t> Data)635      : Data(std::begin(Data), std::end(Data)) {636    Name = SecName.str();637    Type = OriginalType = ELF::SHT_PROGBITS;638    Size = Data.size();639    OriginalOffset = std::numeric_limits<uint64_t>::max();640  }641 642  OwnedDataSection(const Twine &SecName, uint64_t SecAddr, uint64_t SecFlags,643                   uint64_t SecOff) {644    Name = SecName.str();645    Type = OriginalType = ELF::SHT_PROGBITS;646    Addr = SecAddr;647    Flags = OriginalFlags = SecFlags;648    OriginalOffset = SecOff;649  }650 651  OwnedDataSection(SectionBase &S, ArrayRef<uint8_t> Data)652      : SectionBase(S), Data(std::begin(Data), std::end(Data)) {653    Size = Data.size();654  }655 656  void appendHexData(StringRef HexData);657  Error accept(SectionVisitor &Sec) const override;658  Error accept(MutableSectionVisitor &Visitor) override;659  bool hasContents() const override { return true; }660  ArrayRef<uint8_t> getContents() const override { return Data; }661};662 663class CompressedSection : public SectionBase {664  MAKE_SEC_WRITER_FRIEND665 666  uint32_t ChType = 0;667  DebugCompressionType CompressionType;668  uint64_t DecompressedSize;669  uint64_t DecompressedAlign;670  SmallVector<uint8_t, 128> CompressedData;671 672public:673  CompressedSection(const SectionBase &Sec,674    DebugCompressionType CompressionType, bool Is64Bits);675  CompressedSection(ArrayRef<uint8_t> CompressedData, uint32_t ChType,676                    uint64_t DecompressedSize, uint64_t DecompressedAlign);677 678  uint64_t getDecompressedSize() const { return DecompressedSize; }679  uint64_t getDecompressedAlign() const { return DecompressedAlign; }680  uint64_t getChType() const { return ChType; }681 682  Error accept(SectionVisitor &Visitor) const override;683  Error accept(MutableSectionVisitor &Visitor) override;684 685  static bool classof(const SectionBase *S) {686    return S->OriginalFlags & ELF::SHF_COMPRESSED;687  }688};689 690class DecompressedSection : public SectionBase {691  MAKE_SEC_WRITER_FRIEND692 693public:694  uint32_t ChType;695  explicit DecompressedSection(const CompressedSection &Sec)696      : SectionBase(Sec), ChType(Sec.getChType()) {697    Size = Sec.getDecompressedSize();698    Align = Sec.getDecompressedAlign();699    Flags = OriginalFlags = (Flags & ~ELF::SHF_COMPRESSED);700  }701 702  Error accept(SectionVisitor &Visitor) const override;703  Error accept(MutableSectionVisitor &Visitor) override;704};705 706// There are two types of string tables that can exist, dynamic and not dynamic.707// In the dynamic case the string table is allocated. Changing a dynamic string708// table would mean altering virtual addresses and thus the memory image. So709// dynamic string tables should not have an interface to modify them or710// reconstruct them. This type lets us reconstruct a string table. To avoid711// this class being used for dynamic string tables (which has happened) the712// classof method checks that the particular instance is not allocated. This713// then agrees with the makeSection method used to construct most sections.714class StringTableSection : public SectionBase {715  MAKE_SEC_WRITER_FRIEND716 717  StringTableBuilder StrTabBuilder;718 719public:720  StringTableSection() : StrTabBuilder(StringTableBuilder::ELF) {721    Type = OriginalType = ELF::SHT_STRTAB;722  }723 724  void addString(StringRef Name);725  uint32_t findIndex(StringRef Name) const;726  void prepareForLayout();727  Error accept(SectionVisitor &Visitor) const override;728  Error accept(MutableSectionVisitor &Visitor) override;729 730  static bool classof(const SectionBase *S) {731    if (S->OriginalFlags & ELF::SHF_ALLOC)732      return false;733    return S->OriginalType == ELF::SHT_STRTAB;734  }735};736 737// Symbols have a st_shndx field that normally stores an index but occasionally738// stores a different special value. This enum keeps track of what the st_shndx739// field means. Most of the values are just copies of the special SHN_* values.740// SYMBOL_SIMPLE_INDEX means that the st_shndx is just an index of a section.741enum SymbolShndxType {742  SYMBOL_SIMPLE_INDEX = 0,743  SYMBOL_ABS = ELF::SHN_ABS,744  SYMBOL_COMMON = ELF::SHN_COMMON,745  SYMBOL_LOPROC = ELF::SHN_LOPROC,746  SYMBOL_AMDGPU_LDS = ELF::SHN_AMDGPU_LDS,747  SYMBOL_HEXAGON_SCOMMON = ELF::SHN_HEXAGON_SCOMMON,748  SYMBOL_HEXAGON_SCOMMON_2 = ELF::SHN_HEXAGON_SCOMMON_2,749  SYMBOL_HEXAGON_SCOMMON_4 = ELF::SHN_HEXAGON_SCOMMON_4,750  SYMBOL_HEXAGON_SCOMMON_8 = ELF::SHN_HEXAGON_SCOMMON_8,751  SYMBOL_MIPS_ACOMMON = ELF::SHN_MIPS_ACOMMON,752  SYMBOL_MIPS_TEXT = ELF::SHN_MIPS_TEXT,753  SYMBOL_MIPS_DATA = ELF::SHN_MIPS_DATA,754  SYMBOL_MIPS_SCOMMON = ELF::SHN_MIPS_SCOMMON,755  SYMBOL_MIPS_SUNDEFINED = ELF::SHN_MIPS_SUNDEFINED,756  SYMBOL_HIPROC = ELF::SHN_HIPROC,757  SYMBOL_LOOS = ELF::SHN_LOOS,758  SYMBOL_HIOS = ELF::SHN_HIOS,759  SYMBOL_XINDEX = ELF::SHN_XINDEX,760};761 762struct Symbol {763  uint8_t Binding;764  SectionBase *DefinedIn = nullptr;765  SymbolShndxType ShndxType;766  uint32_t Index;767  std::string Name;768  uint32_t NameIndex;769  uint64_t Size;770  uint8_t Type;771  uint64_t Value;772  uint8_t Visibility;773  bool Referenced = false;774 775  uint16_t getShndx() const;776  bool isCommon() const;777};778 779class SectionIndexSection : public SectionBase {780  MAKE_SEC_WRITER_FRIEND781 782private:783  std::vector<uint32_t> Indexes;784  SymbolTableSection *Symbols = nullptr;785 786public:787  ~SectionIndexSection() override = default;788  void addIndex(uint32_t Index) {789    assert(Size > 0);790    Indexes.push_back(Index);791  }792 793  void reserve(size_t NumSymbols) {794    Indexes.reserve(NumSymbols);795    Size = NumSymbols * 4;796  }797  void setSymTab(SymbolTableSection *SymTab) { Symbols = SymTab; }798  Error initialize(SectionTableRef SecTable) override;799  void finalize() override;800  Error accept(SectionVisitor &Visitor) const override;801  Error accept(MutableSectionVisitor &Visitor) override;802 803  SectionIndexSection() {804    Name = ".symtab_shndx";805    Align = 4;806    EntrySize = 4;807    Type = OriginalType = ELF::SHT_SYMTAB_SHNDX;808  }809};810 811class SymbolTableSection : public SectionBase {812  MAKE_SEC_WRITER_FRIEND813 814  void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; }815  void assignIndices();816 817protected:818  std::vector<std::unique_ptr<Symbol>> Symbols;819  StringTableSection *SymbolNames = nullptr;820  SectionIndexSection *SectionIndexTable = nullptr;821  bool IndicesChanged = false;822 823  using SymPtr = std::unique_ptr<Symbol>;824 825public:826  SymbolTableSection() { Type = OriginalType = ELF::SHT_SYMTAB; }827 828  void addSymbol(Twine Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn,829                 uint64_t Value, uint8_t Visibility, uint16_t Shndx,830                 uint64_t SymbolSize);831  void prepareForLayout();832  // An 'empty' symbol table still contains a null symbol.833  bool empty() const { return Symbols.size() == 1; }834  bool indicesChanged() const { return IndicesChanged; }835  void setShndxTable(SectionIndexSection *ShndxTable) {836    SectionIndexTable = ShndxTable;837  }838  const SectionIndexSection *getShndxTable() const { return SectionIndexTable; }839  void fillShndxTable();840  const SectionBase *getStrTab() const { return SymbolNames; }841  Expected<const Symbol *> getSymbolByIndex(uint32_t Index) const;842  Expected<Symbol *> getSymbolByIndex(uint32_t Index);843  void updateSymbols(function_ref<void(Symbol &)> Callable);844 845  Error removeSectionReferences(846      bool AllowBrokenLinks,847      function_ref<bool(const SectionBase *)> ToRemove) override;848  Error initialize(SectionTableRef SecTable) override;849  void finalize() override;850  Error accept(SectionVisitor &Visitor) const override;851  Error accept(MutableSectionVisitor &Visitor) override;852  Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;853  void replaceSectionReferences(854      const DenseMap<SectionBase *, SectionBase *> &FromTo) override;855 856  static bool classof(const SectionBase *S) {857    return S->OriginalType == ELF::SHT_SYMTAB;858  }859};860 861struct Relocation {862  Symbol *RelocSymbol = nullptr;863  uint64_t Offset;864  uint64_t Addend;865  uint32_t Type;866};867 868// All relocation sections denote relocations to apply to another section.869// However, some relocation sections use a dynamic symbol table and others use870// a regular symbol table. Because the types of the two symbol tables differ in871// our system (because they should behave differently) we can't uniformly872// represent all relocations with the same base class if we expose an interface873// that mentions the symbol table type. So we split the two base types into two874// different classes, one which handles the section the relocation is applied to875// and another which handles the symbol table type. The symbol table type is876// taken as a type parameter to the class (see RelocSectionWithSymtabBase).877class RelocationSectionBase : public SectionBase {878protected:879  SectionBase *SecToApplyRel = nullptr;880 881public:882  const SectionBase *getSection() const { return SecToApplyRel; }883  void setSection(SectionBase *Sec) { SecToApplyRel = Sec; }884 885  StringRef getNamePrefix() const;886 887  static bool classof(const SectionBase *S) {888    return is_contained({ELF::SHT_REL, ELF::SHT_RELA, ELF::SHT_CREL},889                        S->OriginalType);890  }891};892 893// Takes the symbol table type to use as a parameter so that we can deduplicate894// that code between the two symbol table types.895template <class SymTabType>896class RelocSectionWithSymtabBase : public RelocationSectionBase {897  void setSymTab(SymTabType *SymTab) { Symbols = SymTab; }898 899protected:900  RelocSectionWithSymtabBase() = default;901 902  SymTabType *Symbols = nullptr;903 904public:905  Error initialize(SectionTableRef SecTable) override;906  void finalize() override;907};908 909class RelocationSection910    : public RelocSectionWithSymtabBase<SymbolTableSection> {911  MAKE_SEC_WRITER_FRIEND912 913  std::vector<Relocation> Relocations;914  const Object &Obj;915 916public:917  RelocationSection(const Object &O) : Obj(O) {}918  void addRelocation(const Relocation &Rel) { Relocations.push_back(Rel); }919  Error accept(SectionVisitor &Visitor) const override;920  Error accept(MutableSectionVisitor &Visitor) override;921  Error removeSectionReferences(922      bool AllowBrokenLinks,923      function_ref<bool(const SectionBase *)> ToRemove) override;924  Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;925  void markSymbols() override;926  void replaceSectionReferences(927      const DenseMap<SectionBase *, SectionBase *> &FromTo) override;928  const Object &getObject() const { return Obj; }929 930  static bool classof(const SectionBase *S) {931    if (S->OriginalFlags & ELF::SHF_ALLOC)932      return false;933    return RelocationSectionBase::classof(S);934  }935};936 937// TODO: The way stripping and groups interact is complicated938// and still needs to be worked on.939 940class GroupSection : public SectionBase {941  MAKE_SEC_WRITER_FRIEND942  const SymbolTableSection *SymTab = nullptr;943  Symbol *Sym = nullptr;944  ELF::Elf32_Word FlagWord;945  SmallVector<SectionBase *, 3> GroupMembers;946 947public:948  template <class T>949  using ConstRange = iterator_range<950      pointee_iterator<typename llvm::SmallVector<T *, 3>::const_iterator>>;951  // TODO: Contents is present in several classes of the hierarchy.952  // This needs to be refactored to avoid duplication.953  ArrayRef<uint8_t> Contents;954 955  explicit GroupSection(ArrayRef<uint8_t> Data) : Contents(Data) {}956 957  void setSymTab(const SymbolTableSection *SymTabSec) { SymTab = SymTabSec; }958  void setSymbol(Symbol *S) { Sym = S; }959  void setFlagWord(ELF::Elf32_Word W) { FlagWord = W; }960  void addMember(SectionBase *Sec) { GroupMembers.push_back(Sec); }961 962  Error accept(SectionVisitor &) const override;963  Error accept(MutableSectionVisitor &Visitor) override;964  void finalize() override;965  Error removeSectionReferences(966      bool AllowBrokenLinks,967      function_ref<bool(const SectionBase *)> ToRemove) override;968  Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;969  void markSymbols() override;970  void replaceSectionReferences(971      const DenseMap<SectionBase *, SectionBase *> &FromTo) override;972  void onRemove() override;973 974  ConstRange<SectionBase> members() const {975    return make_pointee_range(GroupMembers);976  }977 978  static bool classof(const SectionBase *S) {979    return S->OriginalType == ELF::SHT_GROUP;980  }981};982 983class DynamicSymbolTableSection : public Section {984public:985  explicit DynamicSymbolTableSection(ArrayRef<uint8_t> Data) : Section(Data) {}986 987  static bool classof(const SectionBase *S) {988    return S->OriginalType == ELF::SHT_DYNSYM;989  }990};991 992class DynamicSection : public Section {993public:994  explicit DynamicSection(ArrayRef<uint8_t> Data) : Section(Data) {}995 996  static bool classof(const SectionBase *S) {997    return S->OriginalType == ELF::SHT_DYNAMIC;998  }999};1000 1001class DynamicRelocationSection1002    : public RelocSectionWithSymtabBase<DynamicSymbolTableSection> {1003  MAKE_SEC_WRITER_FRIEND1004 1005private:1006  ArrayRef<uint8_t> Contents;1007 1008public:1009  explicit DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}1010 1011  Error accept(SectionVisitor &) const override;1012  Error accept(MutableSectionVisitor &Visitor) override;1013  Error removeSectionReferences(1014      bool AllowBrokenLinks,1015      function_ref<bool(const SectionBase *)> ToRemove) override;1016 1017  static bool classof(const SectionBase *S) {1018    if (!(S->OriginalFlags & ELF::SHF_ALLOC))1019      return false;1020    return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;1021  }1022};1023 1024class GnuDebugLinkSection : public SectionBase {1025  MAKE_SEC_WRITER_FRIEND1026 1027private:1028  StringRef FileName;1029  uint32_t CRC32;1030 1031  void init(StringRef File);1032 1033public:1034  // If we add this section from an external source we can use this ctor.1035  explicit GnuDebugLinkSection(StringRef File, uint32_t PrecomputedCRC);1036  Error accept(SectionVisitor &Visitor) const override;1037  Error accept(MutableSectionVisitor &Visitor) override;1038};1039 1040class Reader {1041public:1042  virtual ~Reader();1043  virtual Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const = 0;1044};1045 1046using object::Binary;1047using object::ELFFile;1048using object::ELFObjectFile;1049using object::OwningBinary;1050 1051class BasicELFBuilder {1052protected:1053  std::unique_ptr<Object> Obj;1054 1055  void initFileHeader();1056  void initHeaderSegment();1057  StringTableSection *addStrTab();1058  SymbolTableSection *addSymTab(StringTableSection *StrTab);1059  Error initSections();1060 1061public:1062  BasicELFBuilder();1063  ~BasicELFBuilder();1064};1065 1066class BinaryELFBuilder : public BasicELFBuilder {1067  MemoryBuffer *MemBuf;1068  uint8_t NewSymbolVisibility;1069  void addData(SymbolTableSection *SymTab);1070 1071public:1072  BinaryELFBuilder(MemoryBuffer *MB, uint8_t NewSymbolVisibility)1073      : MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {}1074 1075  Expected<std::unique_ptr<Object>> build();1076};1077 1078class IHexELFBuilder : public BasicELFBuilder {1079  const std::vector<IHexRecord> &Records;1080 1081  void addDataSections();1082 1083public:1084  IHexELFBuilder(const std::vector<IHexRecord> &Records) : Records(Records) {}1085 1086  Expected<std::unique_ptr<Object>> build();1087};1088 1089template <class ELFT> class ELFBuilder {1090private:1091  using Elf_Addr = typename ELFT::Addr;1092  using Elf_Shdr = typename ELFT::Shdr;1093  using Elf_Word = typename ELFT::Word;1094 1095  const ELFFile<ELFT> &ElfFile;1096  Object &Obj;1097  size_t EhdrOffset = 0;1098  std::optional<StringRef> ExtractPartition;1099 1100  void setParentSegment(Segment &Child);1101  Error readProgramHeaders(const ELFFile<ELFT> &HeadersFile);1102  Error initGroupSection(GroupSection *GroupSec);1103  Error initSymbolTable(SymbolTableSection *SymTab);1104  Error readSectionHeaders();1105  Error readSections(bool EnsureSymtab);1106  Error findEhdrOffset();1107  Expected<SectionBase &> makeSection(const Elf_Shdr &Shdr);1108 1109public:1110  ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,1111             std::optional<StringRef> ExtractPartition);1112 1113  Error build(bool EnsureSymtab);1114};1115 1116class BinaryReader : public Reader {1117  MemoryBuffer *MemBuf;1118  uint8_t NewSymbolVisibility;1119 1120public:1121  BinaryReader(MemoryBuffer *MB, const uint8_t NewSymbolVisibility)1122      : MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {}1123  Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;1124};1125 1126class IHexReader : public Reader {1127  MemoryBuffer *MemBuf;1128 1129  Expected<std::vector<IHexRecord>> parse() const;1130  Error parseError(size_t LineNo, Error E) const {1131    return LineNo == -1U1132               ? createFileError(MemBuf->getBufferIdentifier(), std::move(E))1133               : createFileError(MemBuf->getBufferIdentifier(), LineNo,1134                                 std::move(E));1135  }1136  template <typename... Ts>1137  Error parseError(size_t LineNo, char const *Fmt, const Ts &...Vals) const {1138    Error E = createStringError(errc::invalid_argument, Fmt, Vals...);1139    return parseError(LineNo, std::move(E));1140  }1141 1142public:1143  IHexReader(MemoryBuffer *MB) : MemBuf(MB) {}1144 1145  Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;1146};1147 1148class ELFReader : public Reader {1149  Binary *Bin;1150  std::optional<StringRef> ExtractPartition;1151 1152public:1153  Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;1154  explicit ELFReader(Binary *B, std::optional<StringRef> ExtractPartition)1155      : Bin(B), ExtractPartition(ExtractPartition) {}1156};1157 1158class Object {1159private:1160  using SecPtr = std::unique_ptr<SectionBase>;1161  using SegPtr = std::unique_ptr<Segment>;1162 1163  std::vector<SecPtr> Sections;1164  std::vector<SegPtr> Segments;1165  std::vector<SecPtr> RemovedSections;1166  DenseMap<SectionBase *, std::vector<uint8_t>> UpdatedSections;1167 1168  static bool sectionIsAlloc(const SectionBase &Sec) {1169    return Sec.Flags & ELF::SHF_ALLOC;1170  };1171 1172  Error updateSectionData(SecPtr &Sec, ArrayRef<uint8_t> Data);1173 1174public:1175  template <class T>1176  using ConstRange = iterator_range<pointee_iterator<1177      typename std::vector<std::unique_ptr<T>>::const_iterator>>;1178 1179  // It is often the case that the ELF header and the program header table are1180  // not present in any segment. This could be a problem during file layout,1181  // because other segments may get assigned an offset where either of the1182  // two should reside, which will effectively corrupt the resulting binary.1183  // Other than that we use these segments to track program header offsets1184  // when they may not follow the ELF header.1185  Segment ElfHdrSegment;1186  Segment ProgramHdrSegment;1187 1188  bool Is64Bits;1189  uint8_t OSABI;1190  uint8_t ABIVersion;1191  uint64_t Entry;1192  uint64_t SHOff;1193  uint32_t Type;1194  uint32_t Machine;1195  uint32_t Version;1196  uint32_t Flags;1197 1198  bool HadShdrs = true;1199  bool MustBeRelocatable = false;1200  StringTableSection *SectionNames = nullptr;1201  SymbolTableSection *SymbolTable = nullptr;1202  SectionIndexSection *SectionIndexTable = nullptr;1203 1204  bool IsMips64EL = false;1205 1206  SectionTableRef sections() const { return SectionTableRef(Sections); }1207  iterator_range<1208      filter_iterator<pointee_iterator<std::vector<SecPtr>::const_iterator>,1209                      decltype(&sectionIsAlloc)>>1210  allocSections() const {1211    return make_filter_range(make_pointee_range(Sections), sectionIsAlloc);1212  }1213 1214  const auto &getUpdatedSections() const { return UpdatedSections; }1215  Error updateSection(StringRef Name, ArrayRef<uint8_t> Data);1216  Error updateSectionData(SectionBase &S, ArrayRef<uint8_t> Data);1217 1218  SectionBase *findSection(StringRef Name) {1219    auto SecIt =1220        find_if(Sections, [&](const SecPtr &Sec) { return Sec->Name == Name; });1221    return SecIt == Sections.end() ? nullptr : SecIt->get();1222  }1223  SectionTableRef removedSections() { return SectionTableRef(RemovedSections); }1224 1225  ConstRange<Segment> segments() const { return make_pointee_range(Segments); }1226 1227  Error removeSections(bool AllowBrokenLinks,1228                       std::function<bool(const SectionBase &)> ToRemove);1229  Error compressOrDecompressSections(const CommonConfig &Config);1230  Error replaceSections(const DenseMap<SectionBase *, SectionBase *> &FromTo);1231  Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);1232  template <class T, class... Ts> T &addSection(Ts &&...Args) {1233    auto Sec = std::make_unique<T>(std::forward<Ts>(Args)...);1234    auto Ptr = Sec.get();1235    MustBeRelocatable |= isa<RelocationSection>(*Ptr);1236    Sections.emplace_back(std::move(Sec));1237    Ptr->Index = Sections.size();1238    return *Ptr;1239  }1240  Error addNewSymbolTable();1241  Segment &addSegment(ArrayRef<uint8_t> Data) {1242    Segments.emplace_back(std::make_unique<Segment>(Data));1243    return *Segments.back();1244  }1245  bool isRelocatable() const {1246    return (Type != ELF::ET_DYN && Type != ELF::ET_EXEC) || MustBeRelocatable;1247  }1248};1249 1250} // end namespace elf1251} // end namespace objcopy1252} // end namespace llvm1253 1254#endif // LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H1255