#ifndef LLD_ELF_SYNTHETIC_SECTIONS_H
#define LLD_ELF_SYNTHETIC_SECTIONS_H
#include "Config.h"
#include "DWARF.h"
#include "InputSection.h"
#include "Symbols.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/Threading.h"
namespace lld::elf {
class Defined;
struct PhdrEntry;
class SymbolTableBaseSection;
struct CieRecord {
EhSectionPiece *cie = nullptr;
SmallVector<EhSectionPiece *, 0> fdes;
};
class EhFrameSection final : public SyntheticSection {
public:
EhFrameSection();
void writeTo(uint8_t *buf) override;
void finalizeContents() override;
bool isNeeded() const override { return !sections.empty(); }
size_t getSize() const override { return size; }
static bool classof(const SectionBase *d) {
return SyntheticSection::classof(d) && d->name == ".eh_frame";
}
SmallVector<EhInputSection *, 0> sections;
size_t numFdes = 0;
struct FdeData {
uint32_t pcRel;
uint32_t fdeVARel;
};
SmallVector<FdeData, 0> getFdeData() const;
ArrayRef<CieRecord *> getCieRecords() const { return cieRecords; }
template <class ELFT>
void iterateFDEWithLSDA(llvm::function_ref<void(InputSection &)> fn);
private:
llvm::DenseMap<size_t, CieRecord *> offsetToCie;
uint64_t size = 0;
template <class ELFT, class RelTy>
void addRecords(EhInputSection *s, llvm::ArrayRef<RelTy> rels);
template <class ELFT> void addSectionAux(EhInputSection *s);
template <class ELFT, class RelTy>
void iterateFDEWithLSDAAux(EhInputSection &sec, ArrayRef<RelTy> rels,
llvm::DenseSet<size_t> &ciesWithLSDA,
llvm::function_ref<void(InputSection &)> fn);
template <class ELFT, class RelTy>
CieRecord *addCie(EhSectionPiece &piece, ArrayRef<RelTy> rels);
template <class ELFT, class RelTy>
Defined *isFdeLive(EhSectionPiece &piece, ArrayRef<RelTy> rels);
uint64_t getFdePc(uint8_t *buf, size_t off, uint8_t enc) const;
SmallVector<CieRecord *, 0> cieRecords;
llvm::DenseMap<std::pair<ArrayRef<uint8_t>, Symbol *>, CieRecord *> cieMap;
};
class GotSection final : public SyntheticSection {
public:
GotSection();
size_t getSize() const override { return size; }
void finalizeContents() override;
bool isNeeded() const override;
void writeTo(uint8_t *buf) override;
void addConstant(const Relocation &r);
void addEntry(const Symbol &sym);
bool addTlsDescEntry(const Symbol &sym);
bool addDynTlsEntry(const Symbol &sym);
bool addTlsIndex();
uint32_t getTlsDescOffset(const Symbol &sym) const;
uint64_t getTlsDescAddr(const Symbol &sym) const;
uint64_t getGlobalDynAddr(const Symbol &b) const;
uint64_t getGlobalDynOffset(const Symbol &b) const;
uint64_t getTlsIndexVA() { return this->getVA() + tlsIndexOff; }
uint32_t getTlsIndexOff() const { return tlsIndexOff; }
std::atomic<bool> hasGotOffRel = false;
protected:
size_t numEntries = 0;
uint32_t tlsIndexOff = -1;
uint64_t size = 0;
};
class GnuStackSection : public SyntheticSection {
public:
GnuStackSection()
: SyntheticSection(0, llvm::ELF::SHT_PROGBITS, 1, ".note.GNU-stack") {}
void writeTo(uint8_t *buf) override {}
size_t getSize() const override { return 0; }
};
class GnuPropertySection final : public SyntheticSection {
public:
GnuPropertySection();
void writeTo(uint8_t *buf) override;
size_t getSize() const override;
};
class BuildIdSection : public SyntheticSection {
static const unsigned headerSize = 16;
public:
const size_t hashSize;
BuildIdSection();
void writeTo(uint8_t *buf) override;
size_t getSize() const override { return headerSize + hashSize; }
void writeBuildId(llvm::ArrayRef<uint8_t> buf);
private:
uint8_t *hashBuf;
};
class BssSection final : public SyntheticSection {
public:
BssSection(StringRef name, uint64_t size, uint32_t addralign);
void writeTo(uint8_t *) override {}
bool isNeeded() const override { return size != 0; }
size_t getSize() const override { return size; }
static bool classof(const SectionBase *s) { return s->bss; }
uint64_t size;
};
class MipsGotSection final : public SyntheticSection {
public:
MipsGotSection();
void writeTo(uint8_t *buf) override;
size_t getSize() const override { return size; }
bool updateAllocSize() override;
void finalizeContents() override;
bool isNeeded() const override;
void build();
void addEntry(InputFile &file, Symbol &sym, int64_t addend, RelExpr expr);
void addDynTlsEntry(InputFile &file, Symbol &sym);
void addTlsIndex(InputFile &file);
uint64_t getPageEntryOffset(const InputFile *f, const Symbol &s,
int64_t addend) const;
uint64_t getSymEntryOffset(const InputFile *f, const Symbol &s,
int64_t addend) const;
uint64_t getGlobalDynOffset(const InputFile *f, const Symbol &s) const;
uint64_t getTlsIndexOffset(const InputFile *f) const;
const Symbol *getFirstGlobalEntry() const;
unsigned getLocalEntriesNum() const;
uint64_t getGp(const InputFile *f = nullptr) const;
private:
static const unsigned headerEntriesNum = 2;
uint64_t size = 0;
using GotEntry = std::pair<Symbol *, int64_t>;
struct FileGot {
InputFile *file = nullptr;
size_t startIndex = 0;
struct PageBlock {
size_t firstIndex;
size_t count;
PageBlock() : firstIndex(0), count(0) {}
};
llvm::SmallMapVector<const OutputSection *, PageBlock, 16> pagesMap;
llvm::MapVector<GotEntry, size_t> local16;
llvm::MapVector<GotEntry, size_t> local32;
llvm::MapVector<Symbol *, size_t> global;
llvm::MapVector<Symbol *, size_t> relocs;
llvm::MapVector<Symbol *, size_t> tls;
llvm::MapVector<Symbol *, size_t> dynTlsSymbols;
size_t getEntriesNum() const;
size_t getPageEntriesNum() const;
size_t getIndexedEntriesNum() const;
};
std::vector<FileGot> gots;
FileGot &getGot(InputFile &f);
bool tryMergeGots(FileGot & dst, FileGot & src, bool isPrimary);
};
class GotPltSection final : public SyntheticSection {
public:
GotPltSection();
void addEntry(Symbol &sym);
size_t getSize() const override;
void writeTo(uint8_t *buf) override;
bool isNeeded() const override;
std::atomic<bool> hasGotPltOffRel = false;
private:
SmallVector<const Symbol *, 0> entries;
};
class IgotPltSection final : public SyntheticSection {
public:
IgotPltSection();
void addEntry(Symbol &sym);
size_t getSize() const override;
void writeTo(uint8_t *buf) override;
bool isNeeded() const override { return !entries.empty(); }
private:
SmallVector<const Symbol *, 0> entries;
};
class StringTableSection final : public SyntheticSection {
public:
StringTableSection(StringRef name, bool dynamic);
unsigned addString(StringRef s, bool hashIt = true);
void writeTo(uint8_t *buf) override;
size_t getSize() const override { return size; }
bool isDynamic() const { return dynamic; }
private:
const bool dynamic;
uint64_t size = 0;
llvm::DenseMap<llvm::CachedHashStringRef, unsigned> stringMap;
SmallVector<StringRef, 0> strings;
};
class DynamicReloc {
public:
enum Kind {
AddendOnly,
AddendOnlyWithTargetVA,
AgainstSymbol,
AgainstSymbolWithTargetVA,
MipsMultiGotPage,
};
DynamicReloc(RelType type, const InputSectionBase *inputSec,
uint64_t offsetInSec, Kind kind, Symbol &sym, int64_t addend,
RelExpr expr)
: sym(&sym), inputSec(inputSec), offsetInSec(offsetInSec), type(type),
addend(addend), kind(kind), expr(expr) {}
DynamicReloc(RelType type, const InputSectionBase *inputSec,
uint64_t offsetInSec, int64_t addend = 0)
: sym(nullptr), inputSec(inputSec), offsetInSec(offsetInSec), type(type),
addend(addend), kind(AddendOnly), expr(R_ADDEND) {}
DynamicReloc(RelType type, const InputSectionBase *inputSec,
uint64_t offsetInSec, const OutputSection *outputSec,
int64_t addend)
: sym(nullptr), outputSec(outputSec), inputSec(inputSec),
offsetInSec(offsetInSec), type(type), addend(addend),
kind(MipsMultiGotPage), expr(R_ADDEND) {}
uint64_t getOffset() const;
uint32_t getSymIndex(SymbolTableBaseSection *symTab) const;
bool needsDynSymIndex() const {
return kind == AgainstSymbol || kind == AgainstSymbolWithTargetVA;
}
int64_t computeAddend() const;
void computeRaw(SymbolTableBaseSection *symtab);
Symbol *sym;
const OutputSection *outputSec = nullptr;
const InputSectionBase *inputSec;
uint64_t offsetInSec;
uint64_t r_offset;
RelType type;
uint32_t r_sym;
int64_t addend;
private:
Kind kind;
RelExpr expr;
};
template <class ELFT> class DynamicSection final : public SyntheticSection {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
public:
DynamicSection();
void finalizeContents() override;
void writeTo(uint8_t *buf) override;
size_t getSize() const override { return size; }
private:
std::vector<std::pair<int32_t, uint64_t>> computeContents();
uint64_t size = 0;
};
class RelocationBaseSection : public SyntheticSection {
public:
RelocationBaseSection(StringRef name, uint32_t type, int32_t dynamicTag,
int32_t sizeDynamicTag, bool combreloc,
unsigned concurrency);
template <bool shard = false> void addReloc(const DynamicReloc &reloc) {
relocs.push_back(reloc);
}
void addSymbolReloc(RelType dynType, InputSectionBase &isec,
uint64_t offsetInSec, Symbol &sym, int64_t addend = 0,
std::optional<RelType> addendRelType = {});
template <bool shard = false>
void addRelativeReloc(RelType dynType, InputSectionBase &isec,
uint64_t offsetInSec, Symbol &sym, int64_t addend,
RelType addendRelType, RelExpr expr) {
assert(expr != R_ADDEND && "expected non-addend relocation expression");
addReloc<shard>(DynamicReloc::AddendOnlyWithTargetVA, dynType, isec,
offsetInSec, sym, addend, expr, addendRelType);
}
void addAddendOnlyRelocIfNonPreemptible(RelType dynType, GotSection &sec,
uint64_t offsetInSec, Symbol &sym,
RelType addendRelType);
template <bool shard = false>
void addReloc(DynamicReloc::Kind kind, RelType dynType, InputSectionBase &sec,
uint64_t offsetInSec, Symbol &sym, int64_t addend, RelExpr expr,
RelType addendRelType) {
if (config->writeAddends && (expr != R_ADDEND || addend != 0))
sec.addReloc({expr, addendRelType, offsetInSec, addend, &sym});
addReloc<shard>({dynType, &sec, offsetInSec, kind, sym, addend, expr});
}
bool isNeeded() const override {
return !relocs.empty() ||
llvm::any_of(relocsVec, [](auto &v) { return !v.empty(); });
}
size_t getSize() const override { return relocs.size() * this->entsize; }
size_t getRelativeRelocCount() const { return numRelativeRelocs; }
void mergeRels();
void partitionRels();
void finalizeContents() override;
static bool classof(const SectionBase *d) {
return SyntheticSection::classof(d) &&
(d->type == llvm::ELF::SHT_RELA || d->type == llvm::ELF::SHT_REL ||
d->type == llvm::ELF::SHT_RELR ||
(d->type == llvm::ELF::SHT_AARCH64_AUTH_RELR &&
config->emachine == llvm::ELF::EM_AARCH64));
}
int32_t dynamicTag, sizeDynamicTag;
SmallVector<DynamicReloc, 0> relocs;
protected:
void computeRels();
SmallVector<SmallVector<DynamicReloc, 0>, 0> relocsVec;
size_t numRelativeRelocs = 0;
bool combreloc;
};
template <>
inline void RelocationBaseSection::addReloc<true>(const DynamicReloc &reloc) {
relocsVec[llvm::parallel::getThreadIndex()].push_back(reloc);
}
template <class ELFT>
class RelocationSection final : public RelocationBaseSection {
using Elf_Rel = typename ELFT::Rel;
using Elf_Rela = typename ELFT::Rela;
public:
RelocationSection(StringRef name, bool combreloc, unsigned concurrency);
void writeTo(uint8_t *buf) override;
};
template <class ELFT>
class AndroidPackedRelocationSection final : public RelocationBaseSection {
using Elf_Rel = typename ELFT::Rel;
using Elf_Rela = typename ELFT::Rela;
public:
AndroidPackedRelocationSection(StringRef name, unsigned concurrency);
bool updateAllocSize() override;
size_t getSize() const override { return relocData.size(); }
void writeTo(uint8_t *buf) override {
memcpy(buf, relocData.data(), relocData.size());
}
private:
SmallVector<char, 0> relocData;
};
struct RelativeReloc {
uint64_t getOffset() const {
return inputSec->getVA(inputSec->relocs()[relocIdx].offset);
}
const InputSectionBase *inputSec;
size_t relocIdx;
};
class RelrBaseSection : public SyntheticSection {
public:
RelrBaseSection(unsigned concurrency, bool isAArch64Auth = false);
void mergeRels();
bool isNeeded() const override {
return !relocs.empty() ||
llvm::any_of(relocsVec, [](auto &v) { return !v.empty(); });
}
SmallVector<RelativeReloc, 0> relocs;
SmallVector<SmallVector<RelativeReloc, 0>, 0> relocsVec;
};
template <class ELFT> class RelrSection final : public RelrBaseSection {
using Elf_Relr = typename ELFT::Relr;
public:
RelrSection(unsigned concurrency, bool isAArch64Auth = false);
bool updateAllocSize() override;
size_t getSize() const override { return relrRelocs.size() * this->entsize; }
void writeTo(uint8_t *buf) override {
memcpy(buf, relrRelocs.data(), getSize());
}
private:
SmallVector<Elf_Relr, 0> relrRelocs;
};
struct SymbolTableEntry {
Symbol *sym;
size_t strTabOffset;
};
class SymbolTableBaseSection : public SyntheticSection {
public:
SymbolTableBaseSection(StringTableSection &strTabSec);
void finalizeContents() override;
size_t getSize() const override { return getNumSymbols() * entsize; }
void addSymbol(Symbol *sym);
unsigned getNumSymbols() const { return symbols.size() + 1; }
size_t getSymbolIndex(const Symbol &sym);
ArrayRef<SymbolTableEntry> getSymbols() const { return symbols; }
protected:
void sortSymTabSymbols();
SmallVector<SymbolTableEntry, 0> symbols;
StringTableSection &strTabSec;
llvm::once_flag onceFlag;
llvm::DenseMap<Symbol *, size_t> symbolIndexMap;
llvm::DenseMap<OutputSection *, size_t> sectionIndexMap;
};
template <class ELFT>
class SymbolTableSection final : public SymbolTableBaseSection {
using Elf_Sym = typename ELFT::Sym;
public:
SymbolTableSection(StringTableSection &strTabSec);
void writeTo(uint8_t *buf) override;
};
class SymtabShndxSection final : public SyntheticSection {
public:
SymtabShndxSection();
void writeTo(uint8_t *buf) override;
size_t getSize() const override;
bool isNeeded() const override;
void finalizeContents() override;
};
class GnuHashTableSection final : public SyntheticSection {
public:
GnuHashTableSection();
void finalizeContents() override;
void writeTo(uint8_t *buf) override;
size_t getSize() const override { return size; }
void addSymbols(llvm::SmallVectorImpl<SymbolTableEntry> &symbols);
private:
enum { Shift2 = 26 };
struct Entry {
Symbol *sym;
size_t strTabOffset;
uint32_t hash;
uint32_t bucketIdx;
};
SmallVector<Entry, 0> symbols;
size_t maskWords;
size_t nBuckets = 0;
size_t size = 0;
};
class HashTableSection final : public SyntheticSection {
public:
HashTableSection();
void finalizeContents() override;
void writeTo(uint8_t *buf) override;
size_t getSize() const override { return size; }
private:
size_t size = 0;
};
class PltSection : public SyntheticSection {
public:
PltSection();
void writeTo(uint8_t *buf) override;
size_t getSize() const override;
bool isNeeded() const override;
void addSymbols();
void addEntry(Symbol &sym);
size_t getNumEntries() const { return entries.size(); }
size_t headerSize;
SmallVector<const Symbol *, 0> entries;
};
class IpltSection final : public SyntheticSection {
SmallVector<const Symbol *, 0> entries;
public:
IpltSection();
void writeTo(uint8_t *buf) override;
size_t getSize() const override;
bool isNeeded() const override { return !entries.empty(); }
void addSymbols();
void addEntry(Symbol &sym);
};
class PPC32GlinkSection : public PltSection {
public:
PPC32GlinkSection();
void writeTo(uint8_t *buf) override;
size_t getSize() const override;
SmallVector<const Symbol *, 0> canonical_plts;
static constexpr size_t footerSize = 64;
};
class IBTPltSection : public SyntheticSection {
public:
IBTPltSection();
void writeTo(uint8_t *Buf) override;
bool isNeeded() const override;
size_t getSize() const override;
};
class RelroPaddingSection final : public SyntheticSection {
public:
RelroPaddingSection();
size_t getSize() const override { return 0; }
void writeTo(uint8_t *buf) override {}
};
class DebugNamesBaseSection : public SyntheticSection {
public:
struct Abbrev : llvm::FoldingSetNode {
uint32_t code;
uint32_t tag;
SmallVector<llvm::DWARFDebugNames::AttributeEncoding, 2> attributes;
void Profile(llvm::FoldingSetNodeID &id) const;
};
struct AttrValue {
uint32_t attrValue;
uint8_t attrSize;
};
struct IndexEntry {
uint32_t abbrevCode;
uint32_t poolOffset;
union {
uint64_t parentOffset = 0;
IndexEntry *parentEntry;
};
SmallVector<AttrValue, 3> attrValues;
};
struct NameEntry {
const char *name;
uint32_t hashValue;
uint32_t stringOffset;
uint32_t entryOffset;
uint32_t chunkIdx;
SmallVector<IndexEntry *, 0> indexEntries;
llvm::iterator_range<
llvm::pointee_iterator<typename SmallVector<IndexEntry *, 0>::iterator>>
entries() {
return llvm::make_pointee_range(indexEntries);
}
};
struct NameData {
llvm::DWARFDebugNames::Header hdr;
llvm::DenseMap<uint32_t, uint32_t> abbrevCodeMap;
SmallVector<NameEntry, 0> nameEntries;
};
struct InputChunk {
uint32_t baseCuIdx;
LLDDWARFSection section;
SmallVector<NameData, 0> nameData;
std::optional<llvm::DWARFDebugNames> llvmDebugNames;
};
struct OutputChunk {
InputSection *infoSec;
SmallVector<uint32_t, 0> compUnits;
};
DebugNamesBaseSection();
size_t getSize() const override { return size; }
bool isNeeded() const override { return numChunks > 0; }
protected:
void init(llvm::function_ref<void(InputFile *, InputChunk &, OutputChunk &)>);
static void
parseDebugNames(InputChunk &inputChunk, OutputChunk &chunk,
llvm::DWARFDataExtractor &namesExtractor,
llvm::DataExtractor &strExtractor,
llvm::function_ref<SmallVector<uint32_t, 0>(
uint32_t numCUs, const llvm::DWARFDebugNames::Header &hdr,
const llvm::DWARFDebugNames::DWARFDebugNamesOffsets &)>
readOffsets);
void computeHdrAndAbbrevTable(MutableArrayRef<InputChunk> inputChunks);
std::pair<uint32_t, uint32_t>
computeEntryPool(MutableArrayRef<InputChunk> inputChunks);
SmallVector<InputSection *, 0> inputSections;
llvm::DWARFDebugNames::Header hdr;
size_t numChunks;
std::unique_ptr<OutputChunk[]> chunks;
llvm::SpecificBumpPtrAllocator<Abbrev> abbrevAlloc;
SmallVector<Abbrev *, 0> abbrevTable;
SmallVector<char, 0> abbrevTableBuf;
ArrayRef<OutputChunk> getChunks() const {
return ArrayRef(chunks.get(), numChunks);
}
static constexpr size_t numShards = 32;
SmallVector<NameEntry, 0> nameVecs[numShards];
};
template <class ELFT>
class DebugNamesSection final : public DebugNamesBaseSection {
public:
DebugNamesSection();
void finalizeContents() override;
void writeTo(uint8_t *buf) override;
template <class RelTy>
void getNameRelocs(const InputFile &file,
llvm::DenseMap<uint32_t, uint32_t> &relocs,
Relocs<RelTy> rels);
private:
static void readOffsets(InputChunk &inputChunk, OutputChunk &chunk,
llvm::DWARFDataExtractor &namesExtractor,
llvm::DataExtractor &strExtractor);
};
class GdbIndexSection final : public SyntheticSection {
public:
struct AddressEntry {
InputSection *section;
uint64_t lowAddress;
uint64_t highAddress;
uint32_t cuIndex;
};
struct CuEntry {
uint64_t cuOffset;
uint64_t cuLength;
};
struct NameAttrEntry {
llvm::CachedHashStringRef name;
uint32_t cuIndexAndAttrs;
};
struct GdbChunk {
InputSection *sec;
SmallVector<AddressEntry, 0> addressAreas;
SmallVector<CuEntry, 0> compilationUnits;
};
struct GdbSymbol {
llvm::CachedHashStringRef name;
SmallVector<uint32_t, 0> cuVector;
uint32_t nameOff;
uint32_t cuVectorOff;
};
GdbIndexSection();
template <typename ELFT> static std::unique_ptr<GdbIndexSection> create();
void writeTo(uint8_t *buf) override;
size_t getSize() const override { return size; }
bool isNeeded() const override;
private:
struct GdbIndexHeader {
llvm::support::ulittle32_t version;
llvm::support::ulittle32_t cuListOff;
llvm::support::ulittle32_t cuTypesOff;
llvm::support::ulittle32_t addressAreaOff;
llvm::support::ulittle32_t symtabOff;
llvm::support::ulittle32_t constantPoolOff;
};
size_t computeSymtabSize() const;
SmallVector<GdbChunk, 0> chunks;
SmallVector<GdbSymbol, 0> symbols;
size_t size;
};
class EhFrameHeader final : public SyntheticSection {
public:
EhFrameHeader();
void write();
void writeTo(uint8_t *buf) override;
size_t getSize() const override;
bool isNeeded() const override;
};
class VersionDefinitionSection final : public SyntheticSection {
public:
VersionDefinitionSection();
void finalizeContents() override;
size_t getSize() const override;
void writeTo(uint8_t *buf) override;
private:
enum { EntrySize = 28 };
void writeOne(uint8_t *buf, uint32_t index, StringRef name, size_t nameOff);
StringRef getFileDefName();
unsigned fileDefNameOff;
SmallVector<unsigned, 0> verDefNameOffs;
};
class VersionTableSection final : public SyntheticSection {
public:
VersionTableSection();
void finalizeContents() override;
size_t getSize() const override;
void writeTo(uint8_t *buf) override;
bool isNeeded() const override;
};
template <class ELFT>
class VersionNeedSection final : public SyntheticSection {
using Elf_Verneed = typename ELFT::Verneed;
using Elf_Vernaux = typename ELFT::Vernaux;
struct Vernaux {
uint64_t hash;
uint32_t verneedIndex;
uint64_t nameStrTab;
};
struct Verneed {
uint64_t nameStrTab;
std::vector<Vernaux> vernauxs;
};
SmallVector<Verneed, 0> verneeds;
public:
VersionNeedSection();
void finalizeContents() override;
void writeTo(uint8_t *buf) override;
size_t getSize() const override;
bool isNeeded() const override;
};
class MergeSyntheticSection : public SyntheticSection {
public:
void addSection(MergeInputSection *ms);
SmallVector<MergeInputSection *, 0> sections;
protected:
MergeSyntheticSection(StringRef name, uint32_t type, uint64_t flags,
uint32_t addralign)
: SyntheticSection(flags, type, addralign, name) {}
};
class MergeTailSection final : public MergeSyntheticSection {
public:
MergeTailSection(StringRef name, uint32_t type, uint64_t flags,
uint32_t addralign);
size_t getSize() const override;
void writeTo(uint8_t *buf) override;
void finalizeContents() override;
private:
llvm::StringTableBuilder builder;
};
class MergeNoTailSection final : public MergeSyntheticSection {
public:
MergeNoTailSection(StringRef name, uint32_t type, uint64_t flags,
uint32_t addralign)
: MergeSyntheticSection(name, type, flags, addralign) {}
size_t getSize() const override { return size; }
void writeTo(uint8_t *buf) override;
void finalizeContents() override;
private:
size_t getShardId(uint32_t hash) {
assert((hash >> 31) == 0);
return hash >> (31 - llvm::countr_zero(numShards));
}
size_t size;
constexpr static size_t numShards = 32;
SmallVector<llvm::StringTableBuilder, 0> shards;
size_t shardOffsets[numShards];
};
template <class ELFT>
class MipsAbiFlagsSection final : public SyntheticSection {
using Elf_Mips_ABIFlags = llvm::object::Elf_Mips_ABIFlags<ELFT>;
public:
static std::unique_ptr<MipsAbiFlagsSection> create();
MipsAbiFlagsSection(Elf_Mips_ABIFlags flags);
size_t getSize() const override { return sizeof(Elf_Mips_ABIFlags); }
void writeTo(uint8_t *buf) override;
private:
Elf_Mips_ABIFlags flags;
};
template <class ELFT> class MipsOptionsSection final : public SyntheticSection {
using Elf_Mips_Options = llvm::object::Elf_Mips_Options<ELFT>;
using Elf_Mips_RegInfo = llvm::object::Elf_Mips_RegInfo<ELFT>;
public:
static std::unique_ptr<MipsOptionsSection<ELFT>> create();
MipsOptionsSection(Elf_Mips_RegInfo reginfo);
void writeTo(uint8_t *buf) override;
size_t getSize() const override {
return sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo);
}
private:
Elf_Mips_RegInfo reginfo;
};
template <class ELFT> class MipsReginfoSection final : public SyntheticSection {
using Elf_Mips_RegInfo = llvm::object::Elf_Mips_RegInfo<ELFT>;
public:
static std::unique_ptr<MipsReginfoSection> create();
MipsReginfoSection(Elf_Mips_RegInfo reginfo);
size_t getSize() const override { return sizeof(Elf_Mips_RegInfo); }
void writeTo(uint8_t *buf) override;
private:
Elf_Mips_RegInfo reginfo;
};
class MipsRldMapSection final : public SyntheticSection {
public:
MipsRldMapSection();
size_t getSize() const override { return config->wordsize; }
void writeTo(uint8_t *buf) override {}
};
class ARMExidxSyntheticSection : public SyntheticSection {
public:
ARMExidxSyntheticSection();
bool addSection(InputSection *isec);
size_t getSize() const override { return size; }
void writeTo(uint8_t *buf) override;
bool isNeeded() const override;
void finalizeContents() override;
InputSection *getLinkOrderDep() const;
static bool classof(const SectionBase *sec) {
return sec->kind() == InputSectionBase::Synthetic &&
sec->type == llvm::ELF::SHT_ARM_EXIDX;
}
SmallVector<InputSection *, 0> exidxSections;
private:
size_t size = 0;
SmallVector<InputSection *, 0> executableSections;
SmallVector<InputSection *, 0> originalExecutableSections;
InputSection *sentinel = nullptr;
};
class ThunkSection final : public SyntheticSection {
public:
ThunkSection(OutputSection *os, uint64_t off);
void addThunk(Thunk *t);
size_t getSize() const override;
void writeTo(uint8_t *buf) override;
InputSection *getTargetInputSection() const;
bool assignOffsets();
bool roundUpSizeForErrata = false;
private:
SmallVector<Thunk *, 0> thunks;
size_t size = 0;
};
const char ACLESESYM_PREFIX[] = "__acle_se_";
const int ACLESESYM_SIZE = 8;
class ArmCmseSGVeneer;
class ArmCmseSGSection final : public SyntheticSection {
public:
ArmCmseSGSection();
bool isNeeded() const override { return !entries.empty(); }
size_t getSize() const override;
void writeTo(uint8_t *buf) override;
void addSGVeneer(Symbol *sym, Symbol *ext_sym);
void addMappingSymbol();
void finalizeContents() override;
void exportEntries(SymbolTableBaseSection *symTab);
uint64_t impLibMaxAddr = 0;
private:
SmallVector<std::pair<Symbol *, Symbol *>, 0> entries;
SmallVector<ArmCmseSGVeneer *, 0> sgVeneers;
uint64_t newEntries = 0;
};
class PPC32Got2Section final : public SyntheticSection {
public:
PPC32Got2Section();
size_t getSize() const override { return 0; }
bool isNeeded() const override;
void finalizeContents() override;
void writeTo(uint8_t *buf) override {}
};
class PPC64LongBranchTargetSection final : public SyntheticSection {
public:
PPC64LongBranchTargetSection();
uint64_t getEntryVA(const Symbol *sym, int64_t addend);
std::optional<uint32_t> addEntry(const Symbol *sym, int64_t addend);
size_t getSize() const override;
void writeTo(uint8_t *buf) override;
bool isNeeded() const override;
void finalizeContents() override { finalized = true; }
private:
SmallVector<std::pair<const Symbol *, int64_t>, 0> entries;
llvm::DenseMap<std::pair<const Symbol *, int64_t>, uint32_t> entry_index;
bool finalized = false;
};
template <typename ELFT>
class PartitionElfHeaderSection final : public SyntheticSection {
public:
PartitionElfHeaderSection();
size_t getSize() const override;
void writeTo(uint8_t *buf) override;
};
template <typename ELFT>
class PartitionProgramHeadersSection final : public SyntheticSection {
public:
PartitionProgramHeadersSection();
size_t getSize() const override;
void writeTo(uint8_t *buf) override;
};
class PartitionIndexSection final : public SyntheticSection {
public:
PartitionIndexSection();
size_t getSize() const override;
void finalizeContents() override;
void writeTo(uint8_t *buf) override;
};
class MemtagAndroidNote final : public SyntheticSection {
public:
MemtagAndroidNote()
: SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE,
4, ".note.android.memtag") {}
void writeTo(uint8_t *buf) override;
size_t getSize() const override;
};
class PackageMetadataNote final : public SyntheticSection {
public:
PackageMetadataNote()
: SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE,
4, ".note.package") {}
void writeTo(uint8_t *buf) override;
size_t getSize() const override;
};
class MemtagGlobalDescriptors final : public SyntheticSection {
public:
MemtagGlobalDescriptors()
: SyntheticSection(llvm::ELF::SHF_ALLOC,
llvm::ELF::SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC,
4, ".memtag.globals.dynamic") {}
void writeTo(uint8_t *buf) override;
size_t getSize() const override;
bool updateAllocSize() override;
void addSymbol(const Symbol &sym) {
symbols.push_back(&sym);
}
bool isNeeded() const override {
return !symbols.empty();
}
private:
SmallVector<const Symbol *, 0> symbols;
};
template <class ELFT> void createSyntheticSections();
InputSection *createInterpSection();
MergeInputSection *createCommentSection();
template <class ELFT> void splitSections();
void combineEhSections();
bool hasMemtag();
bool canHaveMemtagGlobals();
template <typename ELFT> void writeEhdr(uint8_t *buf, Partition &part);
template <typename ELFT> void writePhdrs(uint8_t *buf, Partition &part);
Defined *addSyntheticLocal(StringRef name, uint8_t type, uint64_t value,
uint64_t size, InputSectionBase §ion);
void addVerneed(Symbol *ss);
struct Partition {
StringRef name;
uint64_t nameStrTab;
std::unique_ptr<SyntheticSection> elfHeader;
std::unique_ptr<SyntheticSection> programHeaders;
SmallVector<PhdrEntry *, 0> phdrs;
std::unique_ptr<ARMExidxSyntheticSection> armExidx;
std::unique_ptr<BuildIdSection> buildId;
std::unique_ptr<SyntheticSection> dynamic;
std::unique_ptr<StringTableSection> dynStrTab;
std::unique_ptr<SymbolTableBaseSection> dynSymTab;
std::unique_ptr<EhFrameHeader> ehFrameHdr;
std::unique_ptr<EhFrameSection> ehFrame;
std::unique_ptr<GnuHashTableSection> gnuHashTab;
std::unique_ptr<HashTableSection> hashTab;
std::unique_ptr<MemtagAndroidNote> memtagAndroidNote;
std::unique_ptr<MemtagGlobalDescriptors> memtagGlobalDescriptors;
std::unique_ptr<PackageMetadataNote> packageMetadataNote;
std::unique_ptr<RelocationBaseSection> relaDyn;
std::unique_ptr<RelrBaseSection> relrDyn;
std::unique_ptr<RelrBaseSection> relrAuthDyn;
std::unique_ptr<VersionDefinitionSection> verDef;
std::unique_ptr<SyntheticSection> verNeed;
std::unique_ptr<VersionTableSection> verSym;
unsigned getNumber() const { return this - &partitions[0] + 1; }
};
LLVM_LIBRARY_VISIBILITY extern Partition *mainPart;
inline Partition &SectionBase::getPartition() const {
assert(isLive());
return partitions[partition - 1];
}
struct InStruct {
std::unique_ptr<InputSection> attributes;
std::unique_ptr<SyntheticSection> riscvAttributes;
std::unique_ptr<BssSection> bss;
std::unique_ptr<BssSection> bssRelRo;
std::unique_ptr<GotSection> got;
std::unique_ptr<GotPltSection> gotPlt;
std::unique_ptr<IgotPltSection> igotPlt;
std::unique_ptr<RelroPaddingSection> relroPadding;
std::unique_ptr<SyntheticSection> armCmseSGSection;
std::unique_ptr<PPC64LongBranchTargetSection> ppc64LongBranchTarget;
std::unique_ptr<SyntheticSection> mipsAbiFlags;
std::unique_ptr<MipsGotSection> mipsGot;
std::unique_ptr<SyntheticSection> mipsOptions;
std::unique_ptr<SyntheticSection> mipsReginfo;
std::unique_ptr<MipsRldMapSection> mipsRldMap;
std::unique_ptr<SyntheticSection> partEnd;
std::unique_ptr<SyntheticSection> partIndex;
std::unique_ptr<PltSection> plt;
std::unique_ptr<IpltSection> iplt;
std::unique_ptr<PPC32Got2Section> ppc32Got2;
std::unique_ptr<IBTPltSection> ibtPlt;
std::unique_ptr<RelocationBaseSection> relaPlt;
std::unique_ptr<SyntheticSection> debugNames;
std::unique_ptr<GdbIndexSection> gdbIndex;
std::unique_ptr<StringTableSection> shStrTab;
std::unique_ptr<StringTableSection> strTab;
std::unique_ptr<SymbolTableBaseSection> symTab;
std::unique_ptr<SymtabShndxSection> symTabShndx;
void reset();
};
LLVM_LIBRARY_VISIBILITY extern InStruct in;
}
#endif