Path: blob/main/contrib/llvm-project/llvm/lib/ObjCopy/ELF/ELFObject.h
35269 views
//===- ELFObject.h ----------------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H9#define LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H1011#include "llvm/ADT/ArrayRef.h"12#include "llvm/ADT/StringRef.h"13#include "llvm/ADT/Twine.h"14#include "llvm/BinaryFormat/ELF.h"15#include "llvm/MC/StringTableBuilder.h"16#include "llvm/ObjCopy/CommonConfig.h"17#include "llvm/Object/ELFObjectFile.h"18#include "llvm/Support/Errc.h"19#include "llvm/Support/FileOutputBuffer.h"20#include "llvm/Support/MemoryBuffer.h"21#include <cstddef>22#include <cstdint>23#include <functional>24#include <memory>25#include <set>26#include <vector>2728namespace llvm {29enum class DebugCompressionType;30namespace objcopy {31namespace elf {3233class SectionBase;34class Section;35class OwnedDataSection;36class StringTableSection;37class SymbolTableSection;38class RelocationSection;39class DynamicRelocationSection;40class GnuDebugLinkSection;41class GroupSection;42class SectionIndexSection;43class CompressedSection;44class DecompressedSection;45class Segment;46class Object;47struct Symbol;4849class SectionTableRef {50ArrayRef<std::unique_ptr<SectionBase>> Sections;5152public:53using iterator = pointee_iterator<const std::unique_ptr<SectionBase> *>;5455explicit SectionTableRef(ArrayRef<std::unique_ptr<SectionBase>> Secs)56: Sections(Secs) {}57SectionTableRef(const SectionTableRef &) = default;5859iterator begin() const { return iterator(Sections.data()); }60iterator end() const { return iterator(Sections.data() + Sections.size()); }61size_t size() const { return Sections.size(); }6263Expected<SectionBase *> getSection(uint32_t Index, Twine ErrMsg);6465template <class T>66Expected<T *> getSectionOfType(uint32_t Index, Twine IndexErrMsg,67Twine TypeErrMsg);68};6970enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE };7172class SectionVisitor {73public:74virtual ~SectionVisitor() = default;7576virtual Error visit(const Section &Sec) = 0;77virtual Error visit(const OwnedDataSection &Sec) = 0;78virtual Error visit(const StringTableSection &Sec) = 0;79virtual Error visit(const SymbolTableSection &Sec) = 0;80virtual Error visit(const RelocationSection &Sec) = 0;81virtual Error visit(const DynamicRelocationSection &Sec) = 0;82virtual Error visit(const GnuDebugLinkSection &Sec) = 0;83virtual Error visit(const GroupSection &Sec) = 0;84virtual Error visit(const SectionIndexSection &Sec) = 0;85virtual Error visit(const CompressedSection &Sec) = 0;86virtual Error visit(const DecompressedSection &Sec) = 0;87};8889class MutableSectionVisitor {90public:91virtual ~MutableSectionVisitor() = default;9293virtual Error visit(Section &Sec) = 0;94virtual Error visit(OwnedDataSection &Sec) = 0;95virtual Error visit(StringTableSection &Sec) = 0;96virtual Error visit(SymbolTableSection &Sec) = 0;97virtual Error visit(RelocationSection &Sec) = 0;98virtual Error visit(DynamicRelocationSection &Sec) = 0;99virtual Error visit(GnuDebugLinkSection &Sec) = 0;100virtual Error visit(GroupSection &Sec) = 0;101virtual Error visit(SectionIndexSection &Sec) = 0;102virtual Error visit(CompressedSection &Sec) = 0;103virtual Error visit(DecompressedSection &Sec) = 0;104};105106class SectionWriter : public SectionVisitor {107protected:108WritableMemoryBuffer &Out;109110public:111virtual ~SectionWriter() = default;112113Error visit(const Section &Sec) override;114Error visit(const OwnedDataSection &Sec) override;115Error visit(const StringTableSection &Sec) override;116Error visit(const DynamicRelocationSection &Sec) override;117Error visit(const SymbolTableSection &Sec) override = 0;118Error visit(const RelocationSection &Sec) override = 0;119Error visit(const GnuDebugLinkSection &Sec) override = 0;120Error visit(const GroupSection &Sec) override = 0;121Error visit(const SectionIndexSection &Sec) override = 0;122Error visit(const CompressedSection &Sec) override = 0;123Error visit(const DecompressedSection &Sec) override = 0;124125explicit SectionWriter(WritableMemoryBuffer &Buf) : Out(Buf) {}126};127128template <class ELFT> class ELFSectionWriter : public SectionWriter {129private:130using Elf_Word = typename ELFT::Word;131using Elf_Rel = typename ELFT::Rel;132using Elf_Rela = typename ELFT::Rela;133using Elf_Sym = typename ELFT::Sym;134135public:136virtual ~ELFSectionWriter() {}137Error visit(const SymbolTableSection &Sec) override;138Error visit(const RelocationSection &Sec) override;139Error visit(const GnuDebugLinkSection &Sec) override;140Error visit(const GroupSection &Sec) override;141Error visit(const SectionIndexSection &Sec) override;142Error visit(const CompressedSection &Sec) override;143Error visit(const DecompressedSection &Sec) override;144145explicit ELFSectionWriter(WritableMemoryBuffer &Buf) : SectionWriter(Buf) {}146};147148template <class ELFT> class ELFSectionSizer : public MutableSectionVisitor {149private:150using Elf_Rel = typename ELFT::Rel;151using Elf_Rela = typename ELFT::Rela;152using Elf_Sym = typename ELFT::Sym;153using Elf_Word = typename ELFT::Word;154using Elf_Xword = typename ELFT::Xword;155156public:157Error visit(Section &Sec) override;158Error visit(OwnedDataSection &Sec) override;159Error visit(StringTableSection &Sec) override;160Error visit(DynamicRelocationSection &Sec) override;161Error visit(SymbolTableSection &Sec) override;162Error visit(RelocationSection &Sec) override;163Error visit(GnuDebugLinkSection &Sec) override;164Error visit(GroupSection &Sec) override;165Error visit(SectionIndexSection &Sec) override;166Error visit(CompressedSection &Sec) override;167Error visit(DecompressedSection &Sec) override;168};169170#define MAKE_SEC_WRITER_FRIEND \171friend class SectionWriter; \172friend class IHexSectionWriterBase; \173friend class IHexSectionWriter; \174friend class SRECSectionWriter; \175friend class SRECSectionWriterBase; \176friend class SRECSizeCalculator; \177template <class ELFT> friend class ELFSectionWriter; \178template <class ELFT> friend class ELFSectionSizer;179180class BinarySectionWriter : public SectionWriter {181public:182virtual ~BinarySectionWriter() {}183184Error visit(const SymbolTableSection &Sec) override;185Error visit(const RelocationSection &Sec) override;186Error visit(const GnuDebugLinkSection &Sec) override;187Error visit(const GroupSection &Sec) override;188Error visit(const SectionIndexSection &Sec) override;189Error visit(const CompressedSection &Sec) override;190Error visit(const DecompressedSection &Sec) override;191192explicit BinarySectionWriter(WritableMemoryBuffer &Buf)193: SectionWriter(Buf) {}194};195196using IHexLineData = SmallVector<char, 64>;197198struct IHexRecord {199// Memory address of the record.200uint16_t Addr;201// Record type (see below).202uint16_t Type;203// Record data in hexadecimal form.204StringRef HexData;205206// Helper method to get file length of the record207// including newline character208static size_t getLength(size_t DataSize) {209// :LLAAAATT[DD...DD]CC'210return DataSize * 2 + 11;211}212213// Gets length of line in a file (getLength + CRLF).214static size_t getLineLength(size_t DataSize) {215return getLength(DataSize) + 2;216}217218// Given type, address and data returns line which can219// be written to output file.220static IHexLineData getLine(uint8_t Type, uint16_t Addr,221ArrayRef<uint8_t> Data);222223// Parses the line and returns record if possible.224// Line should be trimmed from whitespace characters.225static Expected<IHexRecord> parse(StringRef Line);226227// Calculates checksum of stringified record representation228// S must NOT contain leading ':' and trailing whitespace229// characters230static uint8_t getChecksum(StringRef S);231232enum Type {233// Contains data and a 16-bit starting address for the data.234// The byte count specifies number of data bytes in the record.235Data = 0,236// Must occur exactly once per file in the last line of the file.237// The data field is empty (thus byte count is 00) and the address238// field is typically 0000.239EndOfFile = 1,240// The data field contains a 16-bit segment base address (thus byte241// count is always 02) compatible with 80x86 real mode addressing.242// The address field (typically 0000) is ignored. The segment address243// from the most recent 02 record is multiplied by 16 and added to each244// subsequent data record address to form the physical starting address245// for the data. This allows addressing up to one megabyte of address246// space.247SegmentAddr = 2,248// or 80x86 processors, specifies the initial content of the CS:IP249// registers. The address field is 0000, the byte count is always 04,250// the first two data bytes are the CS value, the latter two are the251// IP value.252StartAddr80x86 = 3,253// Allows for 32 bit addressing (up to 4GiB). The record's address field254// is ignored (typically 0000) and its byte count is always 02. The two255// data bytes (big endian) specify the upper 16 bits of the 32 bit256// absolute address for all subsequent type 00 records257ExtendedAddr = 4,258// The address field is 0000 (not used) and the byte count is always 04.259// The four data bytes represent a 32-bit address value. In the case of260// 80386 and higher CPUs, this address is loaded into the EIP register.261StartAddr = 5,262// We have no other valid types263InvalidType = 6264};265};266267// Base class for IHexSectionWriter. This class implements writing algorithm,268// but doesn't actually write records. It is used for output buffer size269// calculation in IHexWriter::finalize.270class IHexSectionWriterBase : public BinarySectionWriter {271// 20-bit segment address272uint32_t SegmentAddr = 0;273// Extended linear address274uint32_t BaseAddr = 0;275276// Write segment address corresponding to 'Addr'277uint64_t writeSegmentAddr(uint64_t Addr);278// Write extended linear (base) address corresponding to 'Addr'279uint64_t writeBaseAddr(uint64_t Addr);280281protected:282// Offset in the output buffer283uint64_t Offset = 0;284285void writeSection(const SectionBase *Sec, ArrayRef<uint8_t> Data);286virtual void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data);287288public:289explicit IHexSectionWriterBase(WritableMemoryBuffer &Buf)290: BinarySectionWriter(Buf) {}291292uint64_t getBufferOffset() const { return Offset; }293Error visit(const Section &Sec) final;294Error visit(const OwnedDataSection &Sec) final;295Error visit(const StringTableSection &Sec) override;296Error visit(const DynamicRelocationSection &Sec) final;297using BinarySectionWriter::visit;298};299300// Real IHEX section writer301class IHexSectionWriter : public IHexSectionWriterBase {302public:303IHexSectionWriter(WritableMemoryBuffer &Buf) : IHexSectionWriterBase(Buf) {}304305void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data) override;306Error visit(const StringTableSection &Sec) override;307};308309class Writer {310protected:311Object &Obj;312std::unique_ptr<WritableMemoryBuffer> Buf;313raw_ostream &Out;314315public:316virtual ~Writer();317virtual Error finalize() = 0;318virtual Error write() = 0;319320Writer(Object &O, raw_ostream &Out) : Obj(O), Out(Out) {}321};322323template <class ELFT> class ELFWriter : public Writer {324private:325using Elf_Addr = typename ELFT::Addr;326using Elf_Shdr = typename ELFT::Shdr;327using Elf_Phdr = typename ELFT::Phdr;328using Elf_Ehdr = typename ELFT::Ehdr;329330void initEhdrSegment();331332void writeEhdr();333void writePhdr(const Segment &Seg);334void writeShdr(const SectionBase &Sec);335336void writePhdrs();337void writeShdrs();338Error writeSectionData();339void writeSegmentData();340341void assignOffsets();342343std::unique_ptr<ELFSectionWriter<ELFT>> SecWriter;344345size_t totalSize() const;346347public:348virtual ~ELFWriter() {}349bool WriteSectionHeaders;350351// For --only-keep-debug, select an alternative section/segment layout352// algorithm.353bool OnlyKeepDebug;354355Error finalize() override;356Error write() override;357ELFWriter(Object &Obj, raw_ostream &Out, bool WSH, bool OnlyKeepDebug);358};359360class BinaryWriter : public Writer {361private:362const uint8_t GapFill;363const uint64_t PadTo;364std::unique_ptr<BinarySectionWriter> SecWriter;365366uint64_t TotalSize = 0;367368public:369~BinaryWriter() {}370Error finalize() override;371Error write() override;372BinaryWriter(Object &Obj, raw_ostream &Out, const CommonConfig &Config)373: Writer(Obj, Out), GapFill(Config.GapFill), PadTo(Config.PadTo) {}374};375376// A base class for writing ascii hex formats such as srec and ihex.377class ASCIIHexWriter : public Writer {378public:379ASCIIHexWriter(Object &Obj, raw_ostream &OS, StringRef OutputFile)380: Writer(Obj, OS), OutputFileName(OutputFile) {}381Error finalize() override;382383protected:384StringRef OutputFileName;385size_t TotalSize = 0;386std::vector<const SectionBase *> Sections;387388Error checkSection(const SectionBase &S) const;389virtual Expected<size_t>390getTotalSize(WritableMemoryBuffer &EmptyBuffer) const = 0;391};392393class IHexWriter : public ASCIIHexWriter {394public:395Error write() override;396IHexWriter(Object &Obj, raw_ostream &Out, StringRef OutputFile)397: ASCIIHexWriter(Obj, Out, OutputFile) {}398399private:400uint64_t writeEntryPointRecord(uint8_t *Buf);401uint64_t writeEndOfFileRecord(uint8_t *Buf);402Expected<size_t>403getTotalSize(WritableMemoryBuffer &EmptyBuffer) const override;404};405406class SRECWriter : public ASCIIHexWriter {407public:408SRECWriter(Object &Obj, raw_ostream &OS, StringRef OutputFile)409: ASCIIHexWriter(Obj, OS, OutputFile) {}410Error write() override;411412private:413size_t writeHeader(uint8_t *Buf);414size_t writeTerminator(uint8_t *Buf, uint8_t Type);415Expected<size_t>416getTotalSize(WritableMemoryBuffer &EmptyBuffer) const override;417};418419using SRecLineData = SmallVector<char, 64>;420struct SRecord {421uint8_t Type;422uint32_t Address;423ArrayRef<uint8_t> Data;424SRecLineData toString() const;425uint8_t getCount() const;426// Get address size in characters.427uint8_t getAddressSize() const;428uint8_t getChecksum() const;429size_t getSize() const;430static SRecord getHeader(StringRef FileName);431static uint8_t getType(uint32_t Address);432433enum Type : uint8_t {434// Vendor specific text comment.435S0 = 0,436// Data that starts at a 16 bit address.437S1 = 1,438// Data that starts at a 24 bit address.439S2 = 2,440// Data that starts at a 32 bit address.441S3 = 3,442// Reserved.443S4 = 4,444// 16 bit count of S1/S2/S3 records (optional).445S5 = 5,446// 32 bit count of S1/S2/S3 records (optional).447S6 = 6,448// Terminates a series of S3 records.449S7 = 7,450// Terminates a series of S2 records.451S8 = 8,452// Terminates a series of S1 records.453S9 = 9454};455};456457class SRECSectionWriterBase : public BinarySectionWriter {458public:459explicit SRECSectionWriterBase(WritableMemoryBuffer &Buf,460uint64_t StartOffset)461: BinarySectionWriter(Buf), Offset(StartOffset), HeaderSize(StartOffset) {462}463464using BinarySectionWriter::visit;465466void writeRecords(uint32_t Entry);467uint64_t getBufferOffset() const { return Offset; }468Error visit(const Section &S) override;469Error visit(const OwnedDataSection &S) override;470Error visit(const StringTableSection &S) override;471Error visit(const DynamicRelocationSection &S) override;472uint8_t getType() const { return Type; };473474protected:475// Offset in the output buffer.476uint64_t Offset;477// Sections start after the header.478uint64_t HeaderSize;479// Type of records to write.480uint8_t Type = SRecord::S1;481std::vector<SRecord> Records;482483void writeSection(const SectionBase &S, ArrayRef<uint8_t> Data);484virtual void writeRecord(SRecord &Record, uint64_t Off) = 0;485};486487// An SRECSectionWriterBase that visits sections but does not write anything.488// This class is only used to calculate the size of the output file.489class SRECSizeCalculator : public SRECSectionWriterBase {490public:491SRECSizeCalculator(WritableMemoryBuffer &EmptyBuffer, uint64_t Offset)492: SRECSectionWriterBase(EmptyBuffer, Offset) {}493494protected:495void writeRecord(SRecord &Record, uint64_t Off) override {}496};497498class SRECSectionWriter : public SRECSectionWriterBase {499public:500SRECSectionWriter(WritableMemoryBuffer &Buf, uint64_t Offset)501: SRECSectionWriterBase(Buf, Offset) {}502Error visit(const StringTableSection &Sec) override;503504protected:505void writeRecord(SRecord &Record, uint64_t Off) override;506};507508class SectionBase {509public:510std::string Name;511Segment *ParentSegment = nullptr;512uint64_t HeaderOffset = 0;513uint32_t Index = 0;514515uint32_t OriginalIndex = 0;516uint64_t OriginalFlags = 0;517uint64_t OriginalType = ELF::SHT_NULL;518uint64_t OriginalOffset = std::numeric_limits<uint64_t>::max();519520uint64_t Addr = 0;521uint64_t Align = 1;522uint32_t EntrySize = 0;523uint64_t Flags = 0;524uint64_t Info = 0;525uint64_t Link = ELF::SHN_UNDEF;526uint64_t NameIndex = 0;527uint64_t Offset = 0;528uint64_t Size = 0;529uint64_t Type = ELF::SHT_NULL;530ArrayRef<uint8_t> OriginalData;531bool HasSymbol = false;532533SectionBase() = default;534SectionBase(const SectionBase &) = default;535536virtual ~SectionBase() = default;537538virtual Error initialize(SectionTableRef SecTable);539virtual void finalize();540// Remove references to these sections. The list of sections must be sorted.541virtual Error542removeSectionReferences(bool AllowBrokenLinks,543function_ref<bool(const SectionBase *)> ToRemove);544virtual Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);545virtual Error accept(SectionVisitor &Visitor) const = 0;546virtual Error accept(MutableSectionVisitor &Visitor) = 0;547virtual void markSymbols();548virtual void549replaceSectionReferences(const DenseMap<SectionBase *, SectionBase *> &);550virtual bool hasContents() const { return false; }551// Notify the section that it is subject to removal.552virtual void onRemove();553554virtual void restoreSymTabLink(SymbolTableSection &) {}555};556557class Segment {558private:559struct SectionCompare {560bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const {561// Some sections might have the same address if one of them is empty. To562// fix this we can use the lexicographic ordering on ->Addr and the563// original index.564if (Lhs->OriginalOffset == Rhs->OriginalOffset)565return Lhs->OriginalIndex < Rhs->OriginalIndex;566return Lhs->OriginalOffset < Rhs->OriginalOffset;567}568};569570public:571uint32_t Type = 0;572uint32_t Flags = 0;573uint64_t Offset = 0;574uint64_t VAddr = 0;575uint64_t PAddr = 0;576uint64_t FileSize = 0;577uint64_t MemSize = 0;578uint64_t Align = 0;579580uint32_t Index = 0;581uint64_t OriginalOffset = 0;582Segment *ParentSegment = nullptr;583ArrayRef<uint8_t> Contents;584std::set<const SectionBase *, SectionCompare> Sections;585586explicit Segment(ArrayRef<uint8_t> Data) : Contents(Data) {}587Segment() = default;588589const SectionBase *firstSection() const {590if (!Sections.empty())591return *Sections.begin();592return nullptr;593}594595void removeSection(const SectionBase *Sec) { Sections.erase(Sec); }596void addSection(const SectionBase *Sec) { Sections.insert(Sec); }597598ArrayRef<uint8_t> getContents() const { return Contents; }599};600601class Section : public SectionBase {602MAKE_SEC_WRITER_FRIEND603604ArrayRef<uint8_t> Contents;605SectionBase *LinkSection = nullptr;606bool HasSymTabLink = false;607608public:609explicit Section(ArrayRef<uint8_t> Data) : Contents(Data) {}610611Error accept(SectionVisitor &Visitor) const override;612Error accept(MutableSectionVisitor &Visitor) override;613Error removeSectionReferences(614bool AllowBrokenLinks,615function_ref<bool(const SectionBase *)> ToRemove) override;616Error initialize(SectionTableRef SecTable) override;617void finalize() override;618bool hasContents() const override {619return Type != ELF::SHT_NOBITS && Type != ELF::SHT_NULL;620}621void restoreSymTabLink(SymbolTableSection &SymTab) override;622};623624class OwnedDataSection : public SectionBase {625MAKE_SEC_WRITER_FRIEND626627std::vector<uint8_t> Data;628629public:630OwnedDataSection(StringRef SecName, ArrayRef<uint8_t> Data)631: Data(std::begin(Data), std::end(Data)) {632Name = SecName.str();633Type = OriginalType = ELF::SHT_PROGBITS;634Size = Data.size();635OriginalOffset = std::numeric_limits<uint64_t>::max();636}637638OwnedDataSection(const Twine &SecName, uint64_t SecAddr, uint64_t SecFlags,639uint64_t SecOff) {640Name = SecName.str();641Type = OriginalType = ELF::SHT_PROGBITS;642Addr = SecAddr;643Flags = OriginalFlags = SecFlags;644OriginalOffset = SecOff;645}646647OwnedDataSection(SectionBase &S, ArrayRef<uint8_t> Data)648: SectionBase(S), Data(std::begin(Data), std::end(Data)) {649Size = Data.size();650}651652void appendHexData(StringRef HexData);653Error accept(SectionVisitor &Sec) const override;654Error accept(MutableSectionVisitor &Visitor) override;655bool hasContents() const override { return true; }656};657658class CompressedSection : public SectionBase {659MAKE_SEC_WRITER_FRIEND660661uint32_t ChType = 0;662DebugCompressionType CompressionType;663uint64_t DecompressedSize;664uint64_t DecompressedAlign;665SmallVector<uint8_t, 128> CompressedData;666667public:668CompressedSection(const SectionBase &Sec,669DebugCompressionType CompressionType, bool Is64Bits);670CompressedSection(ArrayRef<uint8_t> CompressedData, uint32_t ChType,671uint64_t DecompressedSize, uint64_t DecompressedAlign);672673uint64_t getDecompressedSize() const { return DecompressedSize; }674uint64_t getDecompressedAlign() const { return DecompressedAlign; }675uint64_t getChType() const { return ChType; }676677Error accept(SectionVisitor &Visitor) const override;678Error accept(MutableSectionVisitor &Visitor) override;679680static bool classof(const SectionBase *S) {681return S->OriginalFlags & ELF::SHF_COMPRESSED;682}683};684685class DecompressedSection : public SectionBase {686MAKE_SEC_WRITER_FRIEND687688public:689uint32_t ChType;690explicit DecompressedSection(const CompressedSection &Sec)691: SectionBase(Sec), ChType(Sec.getChType()) {692Size = Sec.getDecompressedSize();693Align = Sec.getDecompressedAlign();694Flags = OriginalFlags = (Flags & ~ELF::SHF_COMPRESSED);695}696697Error accept(SectionVisitor &Visitor) const override;698Error accept(MutableSectionVisitor &Visitor) override;699};700701// There are two types of string tables that can exist, dynamic and not dynamic.702// In the dynamic case the string table is allocated. Changing a dynamic string703// table would mean altering virtual addresses and thus the memory image. So704// dynamic string tables should not have an interface to modify them or705// reconstruct them. This type lets us reconstruct a string table. To avoid706// this class being used for dynamic string tables (which has happened) the707// classof method checks that the particular instance is not allocated. This708// then agrees with the makeSection method used to construct most sections.709class StringTableSection : public SectionBase {710MAKE_SEC_WRITER_FRIEND711712StringTableBuilder StrTabBuilder;713714public:715StringTableSection() : StrTabBuilder(StringTableBuilder::ELF) {716Type = OriginalType = ELF::SHT_STRTAB;717}718719void addString(StringRef Name);720uint32_t findIndex(StringRef Name) const;721void prepareForLayout();722Error accept(SectionVisitor &Visitor) const override;723Error accept(MutableSectionVisitor &Visitor) override;724725static bool classof(const SectionBase *S) {726if (S->OriginalFlags & ELF::SHF_ALLOC)727return false;728return S->OriginalType == ELF::SHT_STRTAB;729}730};731732// Symbols have a st_shndx field that normally stores an index but occasionally733// stores a different special value. This enum keeps track of what the st_shndx734// field means. Most of the values are just copies of the special SHN_* values.735// SYMBOL_SIMPLE_INDEX means that the st_shndx is just an index of a section.736enum SymbolShndxType {737SYMBOL_SIMPLE_INDEX = 0,738SYMBOL_ABS = ELF::SHN_ABS,739SYMBOL_COMMON = ELF::SHN_COMMON,740SYMBOL_LOPROC = ELF::SHN_LOPROC,741SYMBOL_AMDGPU_LDS = ELF::SHN_AMDGPU_LDS,742SYMBOL_HEXAGON_SCOMMON = ELF::SHN_HEXAGON_SCOMMON,743SYMBOL_HEXAGON_SCOMMON_2 = ELF::SHN_HEXAGON_SCOMMON_2,744SYMBOL_HEXAGON_SCOMMON_4 = ELF::SHN_HEXAGON_SCOMMON_4,745SYMBOL_HEXAGON_SCOMMON_8 = ELF::SHN_HEXAGON_SCOMMON_8,746SYMBOL_MIPS_ACOMMON = ELF::SHN_MIPS_ACOMMON,747SYMBOL_MIPS_TEXT = ELF::SHN_MIPS_TEXT,748SYMBOL_MIPS_DATA = ELF::SHN_MIPS_DATA,749SYMBOL_MIPS_SCOMMON = ELF::SHN_MIPS_SCOMMON,750SYMBOL_MIPS_SUNDEFINED = ELF::SHN_MIPS_SUNDEFINED,751SYMBOL_HIPROC = ELF::SHN_HIPROC,752SYMBOL_LOOS = ELF::SHN_LOOS,753SYMBOL_HIOS = ELF::SHN_HIOS,754SYMBOL_XINDEX = ELF::SHN_XINDEX,755};756757struct Symbol {758uint8_t Binding;759SectionBase *DefinedIn = nullptr;760SymbolShndxType ShndxType;761uint32_t Index;762std::string Name;763uint32_t NameIndex;764uint64_t Size;765uint8_t Type;766uint64_t Value;767uint8_t Visibility;768bool Referenced = false;769770uint16_t getShndx() const;771bool isCommon() const;772};773774class SectionIndexSection : public SectionBase {775MAKE_SEC_WRITER_FRIEND776777private:778std::vector<uint32_t> Indexes;779SymbolTableSection *Symbols = nullptr;780781public:782virtual ~SectionIndexSection() {}783void addIndex(uint32_t Index) {784assert(Size > 0);785Indexes.push_back(Index);786}787788void reserve(size_t NumSymbols) {789Indexes.reserve(NumSymbols);790Size = NumSymbols * 4;791}792void setSymTab(SymbolTableSection *SymTab) { Symbols = SymTab; }793Error initialize(SectionTableRef SecTable) override;794void finalize() override;795Error accept(SectionVisitor &Visitor) const override;796Error accept(MutableSectionVisitor &Visitor) override;797798SectionIndexSection() {799Name = ".symtab_shndx";800Align = 4;801EntrySize = 4;802Type = OriginalType = ELF::SHT_SYMTAB_SHNDX;803}804};805806class SymbolTableSection : public SectionBase {807MAKE_SEC_WRITER_FRIEND808809void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; }810void assignIndices();811812protected:813std::vector<std::unique_ptr<Symbol>> Symbols;814StringTableSection *SymbolNames = nullptr;815SectionIndexSection *SectionIndexTable = nullptr;816bool IndicesChanged = false;817818using SymPtr = std::unique_ptr<Symbol>;819820public:821SymbolTableSection() { Type = OriginalType = ELF::SHT_SYMTAB; }822823void addSymbol(Twine Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn,824uint64_t Value, uint8_t Visibility, uint16_t Shndx,825uint64_t SymbolSize);826void prepareForLayout();827// An 'empty' symbol table still contains a null symbol.828bool empty() const { return Symbols.size() == 1; }829bool indicesChanged() const { return IndicesChanged; }830void setShndxTable(SectionIndexSection *ShndxTable) {831SectionIndexTable = ShndxTable;832}833const SectionIndexSection *getShndxTable() const { return SectionIndexTable; }834void fillShndxTable();835const SectionBase *getStrTab() const { return SymbolNames; }836Expected<const Symbol *> getSymbolByIndex(uint32_t Index) const;837Expected<Symbol *> getSymbolByIndex(uint32_t Index);838void updateSymbols(function_ref<void(Symbol &)> Callable);839840Error removeSectionReferences(841bool AllowBrokenLinks,842function_ref<bool(const SectionBase *)> ToRemove) override;843Error initialize(SectionTableRef SecTable) override;844void finalize() override;845Error accept(SectionVisitor &Visitor) const override;846Error accept(MutableSectionVisitor &Visitor) override;847Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;848void replaceSectionReferences(849const DenseMap<SectionBase *, SectionBase *> &FromTo) override;850851static bool classof(const SectionBase *S) {852return S->OriginalType == ELF::SHT_SYMTAB;853}854};855856struct Relocation {857Symbol *RelocSymbol = nullptr;858uint64_t Offset;859uint64_t Addend;860uint32_t Type;861};862863// All relocation sections denote relocations to apply to another section.864// However, some relocation sections use a dynamic symbol table and others use865// a regular symbol table. Because the types of the two symbol tables differ in866// our system (because they should behave differently) we can't uniformly867// represent all relocations with the same base class if we expose an interface868// that mentions the symbol table type. So we split the two base types into two869// different classes, one which handles the section the relocation is applied to870// and another which handles the symbol table type. The symbol table type is871// taken as a type parameter to the class (see RelocSectionWithSymtabBase).872class RelocationSectionBase : public SectionBase {873protected:874SectionBase *SecToApplyRel = nullptr;875876public:877const SectionBase *getSection() const { return SecToApplyRel; }878void setSection(SectionBase *Sec) { SecToApplyRel = Sec; }879880StringRef getNamePrefix() const;881882static bool classof(const SectionBase *S) {883return is_contained({ELF::SHT_REL, ELF::SHT_RELA, ELF::SHT_CREL},884S->OriginalType);885}886};887888// Takes the symbol table type to use as a parameter so that we can deduplicate889// that code between the two symbol table types.890template <class SymTabType>891class RelocSectionWithSymtabBase : public RelocationSectionBase {892void setSymTab(SymTabType *SymTab) { Symbols = SymTab; }893894protected:895RelocSectionWithSymtabBase() = default;896897SymTabType *Symbols = nullptr;898899public:900Error initialize(SectionTableRef SecTable) override;901void finalize() override;902};903904class RelocationSection905: public RelocSectionWithSymtabBase<SymbolTableSection> {906MAKE_SEC_WRITER_FRIEND907908std::vector<Relocation> Relocations;909const Object &Obj;910911public:912RelocationSection(const Object &O) : Obj(O) {}913void addRelocation(const Relocation &Rel) { Relocations.push_back(Rel); }914Error accept(SectionVisitor &Visitor) const override;915Error accept(MutableSectionVisitor &Visitor) override;916Error removeSectionReferences(917bool AllowBrokenLinks,918function_ref<bool(const SectionBase *)> ToRemove) override;919Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;920void markSymbols() override;921void replaceSectionReferences(922const DenseMap<SectionBase *, SectionBase *> &FromTo) override;923const Object &getObject() const { return Obj; }924925static bool classof(const SectionBase *S) {926if (S->OriginalFlags & ELF::SHF_ALLOC)927return false;928return RelocationSectionBase::classof(S);929}930};931932// TODO: The way stripping and groups interact is complicated933// and still needs to be worked on.934935class GroupSection : public SectionBase {936MAKE_SEC_WRITER_FRIEND937const SymbolTableSection *SymTab = nullptr;938Symbol *Sym = nullptr;939ELF::Elf32_Word FlagWord;940SmallVector<SectionBase *, 3> GroupMembers;941942public:943template <class T>944using ConstRange = iterator_range<945pointee_iterator<typename llvm::SmallVector<T *, 3>::const_iterator>>;946// TODO: Contents is present in several classes of the hierarchy.947// This needs to be refactored to avoid duplication.948ArrayRef<uint8_t> Contents;949950explicit GroupSection(ArrayRef<uint8_t> Data) : Contents(Data) {}951952void setSymTab(const SymbolTableSection *SymTabSec) { SymTab = SymTabSec; }953void setSymbol(Symbol *S) { Sym = S; }954void setFlagWord(ELF::Elf32_Word W) { FlagWord = W; }955void addMember(SectionBase *Sec) { GroupMembers.push_back(Sec); }956957Error accept(SectionVisitor &) const override;958Error accept(MutableSectionVisitor &Visitor) override;959void finalize() override;960Error removeSectionReferences(961bool AllowBrokenLinks,962function_ref<bool(const SectionBase *)> ToRemove) override;963Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;964void markSymbols() override;965void replaceSectionReferences(966const DenseMap<SectionBase *, SectionBase *> &FromTo) override;967void onRemove() override;968969ConstRange<SectionBase> members() const {970return make_pointee_range(GroupMembers);971}972973static bool classof(const SectionBase *S) {974return S->OriginalType == ELF::SHT_GROUP;975}976};977978class DynamicSymbolTableSection : public Section {979public:980explicit DynamicSymbolTableSection(ArrayRef<uint8_t> Data) : Section(Data) {}981982static bool classof(const SectionBase *S) {983return S->OriginalType == ELF::SHT_DYNSYM;984}985};986987class DynamicSection : public Section {988public:989explicit DynamicSection(ArrayRef<uint8_t> Data) : Section(Data) {}990991static bool classof(const SectionBase *S) {992return S->OriginalType == ELF::SHT_DYNAMIC;993}994};995996class DynamicRelocationSection997: public RelocSectionWithSymtabBase<DynamicSymbolTableSection> {998MAKE_SEC_WRITER_FRIEND9991000private:1001ArrayRef<uint8_t> Contents;10021003public:1004explicit DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}10051006Error accept(SectionVisitor &) const override;1007Error accept(MutableSectionVisitor &Visitor) override;1008Error removeSectionReferences(1009bool AllowBrokenLinks,1010function_ref<bool(const SectionBase *)> ToRemove) override;10111012static bool classof(const SectionBase *S) {1013if (!(S->OriginalFlags & ELF::SHF_ALLOC))1014return false;1015return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;1016}1017};10181019class GnuDebugLinkSection : public SectionBase {1020MAKE_SEC_WRITER_FRIEND10211022private:1023StringRef FileName;1024uint32_t CRC32;10251026void init(StringRef File);10271028public:1029// If we add this section from an external source we can use this ctor.1030explicit GnuDebugLinkSection(StringRef File, uint32_t PrecomputedCRC);1031Error accept(SectionVisitor &Visitor) const override;1032Error accept(MutableSectionVisitor &Visitor) override;1033};10341035class Reader {1036public:1037virtual ~Reader();1038virtual Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const = 0;1039};10401041using object::Binary;1042using object::ELFFile;1043using object::ELFObjectFile;1044using object::OwningBinary;10451046class BasicELFBuilder {1047protected:1048std::unique_ptr<Object> Obj;10491050void initFileHeader();1051void initHeaderSegment();1052StringTableSection *addStrTab();1053SymbolTableSection *addSymTab(StringTableSection *StrTab);1054Error initSections();10551056public:1057BasicELFBuilder() : Obj(std::make_unique<Object>()) {}1058};10591060class BinaryELFBuilder : public BasicELFBuilder {1061MemoryBuffer *MemBuf;1062uint8_t NewSymbolVisibility;1063void addData(SymbolTableSection *SymTab);10641065public:1066BinaryELFBuilder(MemoryBuffer *MB, uint8_t NewSymbolVisibility)1067: MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {}10681069Expected<std::unique_ptr<Object>> build();1070};10711072class IHexELFBuilder : public BasicELFBuilder {1073const std::vector<IHexRecord> &Records;10741075void addDataSections();10761077public:1078IHexELFBuilder(const std::vector<IHexRecord> &Records) : Records(Records) {}10791080Expected<std::unique_ptr<Object>> build();1081};10821083template <class ELFT> class ELFBuilder {1084private:1085using Elf_Addr = typename ELFT::Addr;1086using Elf_Shdr = typename ELFT::Shdr;1087using Elf_Word = typename ELFT::Word;10881089const ELFFile<ELFT> &ElfFile;1090Object &Obj;1091size_t EhdrOffset = 0;1092std::optional<StringRef> ExtractPartition;10931094void setParentSegment(Segment &Child);1095Error readProgramHeaders(const ELFFile<ELFT> &HeadersFile);1096Error initGroupSection(GroupSection *GroupSec);1097Error initSymbolTable(SymbolTableSection *SymTab);1098Error readSectionHeaders();1099Error readSections(bool EnsureSymtab);1100Error findEhdrOffset();1101Expected<SectionBase &> makeSection(const Elf_Shdr &Shdr);11021103public:1104ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,1105std::optional<StringRef> ExtractPartition);11061107Error build(bool EnsureSymtab);1108};11091110class BinaryReader : public Reader {1111MemoryBuffer *MemBuf;1112uint8_t NewSymbolVisibility;11131114public:1115BinaryReader(MemoryBuffer *MB, const uint8_t NewSymbolVisibility)1116: MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {}1117Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;1118};11191120class IHexReader : public Reader {1121MemoryBuffer *MemBuf;11221123Expected<std::vector<IHexRecord>> parse() const;1124Error parseError(size_t LineNo, Error E) const {1125return LineNo == -1U1126? createFileError(MemBuf->getBufferIdentifier(), std::move(E))1127: createFileError(MemBuf->getBufferIdentifier(), LineNo,1128std::move(E));1129}1130template <typename... Ts>1131Error parseError(size_t LineNo, char const *Fmt, const Ts &...Vals) const {1132Error E = createStringError(errc::invalid_argument, Fmt, Vals...);1133return parseError(LineNo, std::move(E));1134}11351136public:1137IHexReader(MemoryBuffer *MB) : MemBuf(MB) {}11381139Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;1140};11411142class ELFReader : public Reader {1143Binary *Bin;1144std::optional<StringRef> ExtractPartition;11451146public:1147Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;1148explicit ELFReader(Binary *B, std::optional<StringRef> ExtractPartition)1149: Bin(B), ExtractPartition(ExtractPartition) {}1150};11511152class Object {1153private:1154using SecPtr = std::unique_ptr<SectionBase>;1155using SegPtr = std::unique_ptr<Segment>;11561157std::vector<SecPtr> Sections;1158std::vector<SegPtr> Segments;1159std::vector<SecPtr> RemovedSections;1160DenseMap<SectionBase *, std::vector<uint8_t>> UpdatedSections;11611162static bool sectionIsAlloc(const SectionBase &Sec) {1163return Sec.Flags & ELF::SHF_ALLOC;1164};11651166public:1167template <class T>1168using ConstRange = iterator_range<pointee_iterator<1169typename std::vector<std::unique_ptr<T>>::const_iterator>>;11701171// It is often the case that the ELF header and the program header table are1172// not present in any segment. This could be a problem during file layout,1173// because other segments may get assigned an offset where either of the1174// two should reside, which will effectively corrupt the resulting binary.1175// Other than that we use these segments to track program header offsets1176// when they may not follow the ELF header.1177Segment ElfHdrSegment;1178Segment ProgramHdrSegment;11791180bool Is64Bits;1181uint8_t OSABI;1182uint8_t ABIVersion;1183uint64_t Entry;1184uint64_t SHOff;1185uint32_t Type;1186uint32_t Machine;1187uint32_t Version;1188uint32_t Flags;11891190bool HadShdrs = true;1191bool MustBeRelocatable = false;1192StringTableSection *SectionNames = nullptr;1193SymbolTableSection *SymbolTable = nullptr;1194SectionIndexSection *SectionIndexTable = nullptr;11951196bool IsMips64EL = false;11971198SectionTableRef sections() const { return SectionTableRef(Sections); }1199iterator_range<1200filter_iterator<pointee_iterator<std::vector<SecPtr>::const_iterator>,1201decltype(§ionIsAlloc)>>1202allocSections() const {1203return make_filter_range(make_pointee_range(Sections), sectionIsAlloc);1204}12051206const auto &getUpdatedSections() const { return UpdatedSections; }1207Error updateSection(StringRef Name, ArrayRef<uint8_t> Data);12081209SectionBase *findSection(StringRef Name) {1210auto SecIt =1211find_if(Sections, [&](const SecPtr &Sec) { return Sec->Name == Name; });1212return SecIt == Sections.end() ? nullptr : SecIt->get();1213}1214SectionTableRef removedSections() { return SectionTableRef(RemovedSections); }12151216ConstRange<Segment> segments() const { return make_pointee_range(Segments); }12171218Error removeSections(bool AllowBrokenLinks,1219std::function<bool(const SectionBase &)> ToRemove);1220Error compressOrDecompressSections(const CommonConfig &Config);1221Error replaceSections(const DenseMap<SectionBase *, SectionBase *> &FromTo);1222Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);1223template <class T, class... Ts> T &addSection(Ts &&...Args) {1224auto Sec = std::make_unique<T>(std::forward<Ts>(Args)...);1225auto Ptr = Sec.get();1226MustBeRelocatable |= isa<RelocationSection>(*Ptr);1227Sections.emplace_back(std::move(Sec));1228Ptr->Index = Sections.size();1229return *Ptr;1230}1231Error addNewSymbolTable();1232Segment &addSegment(ArrayRef<uint8_t> Data) {1233Segments.emplace_back(std::make_unique<Segment>(Data));1234return *Segments.back();1235}1236bool isRelocatable() const {1237return (Type != ELF::ET_DYN && Type != ELF::ET_EXEC) || MustBeRelocatable;1238}1239};12401241} // end namespace elf1242} // end namespace objcopy1243} // end namespace llvm12441245#endif // LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H124612471248