summaryrefslogtreecommitdiff
path: root/lld/ELF/SyntheticSections.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/SyntheticSections.cpp')
-rw-r--r--lld/ELF/SyntheticSections.cpp138
1 files changed, 75 insertions, 63 deletions
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index f125e3f0a51a..986c1308cbaf 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -83,8 +83,10 @@ static ArrayRef<uint8_t> getVersion() {
// by "readelf --string-dump .comment <file>".
// The returned object is a mergeable string section.
MergeInputSection *elf::createCommentSection() {
- return make<MergeInputSection>(SHF_MERGE | SHF_STRINGS, SHT_PROGBITS, 1,
- getVersion(), ".comment");
+ auto *sec = make<MergeInputSection>(SHF_MERGE | SHF_STRINGS, SHT_PROGBITS, 1,
+ getVersion(), ".comment");
+ sec->splitIntoPieces();
+ return sec;
}
// .MIPS.abiflags section.
@@ -100,7 +102,7 @@ template <class ELFT> void MipsAbiFlagsSection<ELFT>::writeTo(uint8_t *buf) {
}
template <class ELFT>
-MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {
+std::unique_ptr<MipsAbiFlagsSection<ELFT>> MipsAbiFlagsSection<ELFT>::create() {
Elf_Mips_ABIFlags flags = {};
bool create = false;
@@ -142,7 +144,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {
};
if (create)
- return make<MipsAbiFlagsSection<ELFT>>(flags);
+ return std::make_unique<MipsAbiFlagsSection<ELFT>>(flags);
return nullptr;
}
@@ -165,7 +167,7 @@ template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *buf) {
}
template <class ELFT>
-MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() {
+std::unique_ptr<MipsOptionsSection<ELFT>> MipsOptionsSection<ELFT>::create() {
// N64 ABI only.
if (!ELFT::Is64Bits)
return nullptr;
@@ -204,7 +206,7 @@ MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() {
}
};
- return make<MipsOptionsSection<ELFT>>(reginfo);
+ return std::make_unique<MipsOptionsSection<ELFT>>(reginfo);
}
// MIPS .reginfo section.
@@ -222,7 +224,7 @@ template <class ELFT> void MipsReginfoSection<ELFT>::writeTo(uint8_t *buf) {
}
template <class ELFT>
-MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() {
+std::unique_ptr<MipsReginfoSection<ELFT>> MipsReginfoSection<ELFT>::create() {
// Section should be alive for O32 and N32 ABIs only.
if (ELFT::Is64Bits)
return nullptr;
@@ -249,7 +251,7 @@ MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() {
sec->getFile<ELFT>()->mipsGp0 = r->ri_gp_value;
};
- return make<MipsReginfoSection<ELFT>>(reginfo);
+ return std::make_unique<MipsReginfoSection<ELFT>>(reginfo);
}
InputSection *elf::createInterpSection() {
@@ -1228,7 +1230,8 @@ StringTableSection::StringTableSection(StringRef name, bool dynamic)
: SyntheticSection(dynamic ? (uint64_t)SHF_ALLOC : 0, SHT_STRTAB, 1, name),
dynamic(dynamic) {
// ELF string tables start with a NUL byte.
- addString("");
+ strings.push_back("");
+ size = 1;
}
// Adds a string to the string table. If `hashIt` is true we hash and check for
@@ -1241,6 +1244,8 @@ unsigned StringTableSection::addString(StringRef s, bool hashIt) {
if (!r.second)
return r.first->second;
}
+ if (s.empty())
+ return 0;
unsigned ret = this->size;
this->size = this->size + s.size() + 1;
strings.push_back(s);
@@ -1589,9 +1594,11 @@ uint32_t DynamicReloc::getSymIndex(SymbolTableBaseSection *symTab) const {
RelocationBaseSection::RelocationBaseSection(StringRef name, uint32_t type,
int32_t dynamicTag,
- int32_t sizeDynamicTag)
+ int32_t sizeDynamicTag,
+ bool combreloc)
: SyntheticSection(SHF_ALLOC, type, config->wordsize, name),
- dynamicTag(dynamicTag), sizeDynamicTag(sizeDynamicTag) {}
+ dynamicTag(dynamicTag), sizeDynamicTag(sizeDynamicTag),
+ combreloc(combreloc) {}
void RelocationBaseSection::addSymbolReloc(RelType dynType,
InputSectionBase &isec,
@@ -1640,10 +1647,13 @@ void RelocationBaseSection::addReloc(DynamicReloc::Kind kind, RelType dynType,
addReloc({dynType, &inputSec, offsetInSec, kind, sym, addend, expr});
}
-void RelocationBaseSection::addReloc(const DynamicReloc &reloc) {
- if (reloc.type == target->relativeRel)
- ++numRelativeRelocs;
- relocs.push_back(reloc);
+void RelocationBaseSection::partitionRels() {
+ if (!combreloc)
+ return;
+ const RelType relativeRel = target->relativeRel;
+ numRelativeRelocs =
+ llvm::partition(relocs, [=](auto &r) { return r.type == relativeRel; }) -
+ relocs.begin();
}
void RelocationBaseSection::finalizeContents() {
@@ -1667,20 +1677,6 @@ void RelocationBaseSection::finalizeContents() {
}
}
-RelrBaseSection::RelrBaseSection()
- : SyntheticSection(SHF_ALLOC,
- config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR,
- config->wordsize, ".relr.dyn") {}
-
-template <class ELFT>
-static void encodeDynamicReloc(typename ELFT::Rela *p,
- const DynamicReloc &rel) {
- p->r_offset = rel.r_offset;
- p->setSymbolAndType(rel.r_sym, rel.type, config->isMips64EL);
- if (config->isRela)
- p->r_addend = rel.addend;
-}
-
void DynamicReloc::computeRaw(SymbolTableBaseSection *symtab) {
r_offset = getOffset();
r_sym = getSymIndex(symtab);
@@ -1688,27 +1684,15 @@ void DynamicReloc::computeRaw(SymbolTableBaseSection *symtab) {
kind = AddendOnly; // Catch errors
}
-template <class ELFT>
-RelocationSection<ELFT>::RelocationSection(StringRef name, bool sort)
- : RelocationBaseSection(name, config->isRela ? SHT_RELA : SHT_REL,
- config->isRela ? DT_RELA : DT_REL,
- config->isRela ? DT_RELASZ : DT_RELSZ),
- sort(sort) {
- this->entsize = config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
-}
-
-template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) {
+void RelocationBaseSection::computeRels() {
SymbolTableBaseSection *symTab = getPartition().dynSymTab.get();
-
parallelForEach(relocs,
[symTab](DynamicReloc &rel) { rel.computeRaw(symTab); });
// Sort by (!IsRelative,SymIndex,r_offset). DT_REL[A]COUNT requires us to
// place R_*_RELATIVE first. SymIndex is to improve locality, while r_offset
// is to make results easier to read.
- if (sort) {
- const RelType relativeRel = target->relativeRel;
- auto nonRelative =
- llvm::partition(relocs, [=](auto &r) { return r.type == relativeRel; });
+ if (combreloc) {
+ auto nonRelative = relocs.begin() + numRelativeRelocs;
parallelSort(relocs.begin(), nonRelative,
[&](auto &a, auto &b) { return a.r_offset < b.r_offset; });
// Non-relative relocations are few, so don't bother with parallelSort.
@@ -1716,20 +1700,41 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) {
return std::tie(a.r_sym, a.r_offset) < std::tie(b.r_sym, b.r_offset);
});
}
+}
+template <class ELFT>
+RelocationSection<ELFT>::RelocationSection(StringRef name, bool combreloc)
+ : RelocationBaseSection(name, config->isRela ? SHT_RELA : SHT_REL,
+ config->isRela ? DT_RELA : DT_REL,
+ config->isRela ? DT_RELASZ : DT_RELSZ, combreloc) {
+ this->entsize = config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
+}
+
+template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) {
+ computeRels();
for (const DynamicReloc &rel : relocs) {
- encodeDynamicReloc<ELFT>(reinterpret_cast<Elf_Rela *>(buf), rel);
+ auto *p = reinterpret_cast<Elf_Rela *>(buf);
+ p->r_offset = rel.r_offset;
+ p->setSymbolAndType(rel.r_sym, rel.type, config->isMips64EL);
+ if (config->isRela)
+ p->r_addend = rel.addend;
buf += config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
}
}
+RelrBaseSection::RelrBaseSection()
+ : SyntheticSection(SHF_ALLOC,
+ config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR,
+ config->wordsize, ".relr.dyn") {}
+
template <class ELFT>
AndroidPackedRelocationSection<ELFT>::AndroidPackedRelocationSection(
StringRef name)
: RelocationBaseSection(
name, config->isRela ? SHT_ANDROID_RELA : SHT_ANDROID_REL,
config->isRela ? DT_ANDROID_RELA : DT_ANDROID_REL,
- config->isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ) {
+ config->isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ,
+ /*combreloc=*/false) {
this->entsize = 1;
}
@@ -2153,7 +2158,7 @@ void SymbolTableBaseSection::addSymbol(Symbol *b) {
// Adding a local symbol to a .dynsym is a bug.
assert(this->type != SHT_DYNSYM || !b->isLocal());
- bool hashIt = b->isLocal();
+ bool hashIt = b->isLocal() && config->optimize >= 2;
symbols.push_back({b, strTabSec.addString(b->getName(), hashIt)});
}
@@ -2765,13 +2770,13 @@ readAddressAreas(DWARFContext &dwarf, InputSection *sec) {
}
template <class ELFT>
-static std::vector<GdbIndexSection::NameAttrEntry>
+static SmallVector<GdbIndexSection::NameAttrEntry, 0>
readPubNamesAndTypes(const LLDDwarfObj<ELFT> &obj,
const SmallVectorImpl<GdbIndexSection::CuEntry> &cus) {
const LLDDWARFSection &pubNames = obj.getGnuPubnamesSection();
const LLDDWARFSection &pubTypes = obj.getGnuPubtypesSection();
- std::vector<GdbIndexSection::NameAttrEntry> ret;
+ SmallVector<GdbIndexSection::NameAttrEntry, 0> ret;
for (const LLDDWARFSection *pub : {&pubNames, &pubTypes}) {
DWARFDataExtractor data(obj, *pub, config->isLE, config->wordsize);
DWARFDebugPubTable table;
@@ -2798,9 +2803,9 @@ readPubNamesAndTypes(const LLDDwarfObj<ELFT> &obj,
// Create a list of symbols from a given list of symbol names and types
// by uniquifying them by name.
-static std::vector<GdbIndexSection::GdbSymbol>
-createSymbols(ArrayRef<std::vector<GdbIndexSection::NameAttrEntry>> nameAttrs,
- const std::vector<GdbIndexSection::GdbChunk> &chunks) {
+static SmallVector<GdbIndexSection::GdbSymbol, 0> createSymbols(
+ ArrayRef<SmallVector<GdbIndexSection::NameAttrEntry, 0>> nameAttrs,
+ const SmallVector<GdbIndexSection::GdbChunk, 0> &chunks) {
using GdbSymbol = GdbIndexSection::GdbSymbol;
using NameAttrEntry = GdbIndexSection::NameAttrEntry;
@@ -2827,7 +2832,7 @@ createSymbols(ArrayRef<std::vector<GdbIndexSection::NameAttrEntry>> nameAttrs,
size_t shift = 32 - countTrailingZeros(numShards);
// Instantiate GdbSymbols while uniqufying them by name.
- auto symbols = std::make_unique<std::vector<GdbSymbol>[]>(numShards);
+ auto symbols = std::make_unique<SmallVector<GdbSymbol, 0>[]>(numShards);
parallelForEachN(0, concurrency, [&](size_t threadId) {
uint32_t i = 0;
@@ -2857,9 +2862,9 @@ createSymbols(ArrayRef<std::vector<GdbIndexSection::NameAttrEntry>> nameAttrs,
// The return type is a flattened vector, so we'll copy each vector
// contents to Ret.
- std::vector<GdbSymbol> ret;
+ SmallVector<GdbSymbol, 0> ret;
ret.reserve(numSymbols);
- for (std::vector<GdbSymbol> &vec :
+ for (SmallVector<GdbSymbol, 0> &vec :
makeMutableArrayRef(symbols.get(), numShards))
for (GdbSymbol &sym : vec)
ret.push_back(std::move(sym));
@@ -2906,8 +2911,8 @@ template <class ELFT> GdbIndexSection *GdbIndexSection::create() {
return !s->isLive();
});
- std::vector<GdbChunk> chunks(files.size());
- std::vector<std::vector<NameAttrEntry>> nameAttrs(files.size());
+ SmallVector<GdbChunk, 0> chunks(files.size());
+ SmallVector<SmallVector<NameAttrEntry, 0>, 0> nameAttrs(files.size());
parallelForEachN(0, files.size(), [&](size_t i) {
// To keep memory usage low, we don't want to keep cached DWARFContext, so
@@ -3328,11 +3333,15 @@ template <class ELFT> void elf::splitSections() {
llvm::TimeTraceScope timeScope("Split sections");
// splitIntoPieces needs to be called on each MergeInputSection
// before calling finalizeContents().
- parallelForEach(inputSections, [](InputSectionBase *sec) {
- if (auto *s = dyn_cast<MergeInputSection>(sec))
- s->splitIntoPieces();
- else if (auto *eh = dyn_cast<EhInputSection>(sec))
- eh->split<ELFT>();
+ parallelForEach(objectFiles, [](ELFFileBase *file) {
+ for (InputSectionBase *sec : file->getSections()) {
+ if (!sec)
+ continue;
+ if (auto *s = dyn_cast<MergeInputSection>(sec))
+ s->splitIntoPieces();
+ else if (auto *eh = dyn_cast<EhInputSection>(sec))
+ eh->split<ELFT>();
+ }
});
}
@@ -3476,7 +3485,7 @@ void ARMExidxSyntheticSection::finalizeContents() {
sentinel = executableSections.back();
// Optionally merge adjacent duplicate entries.
if (config->mergeArmExidx) {
- std::vector<InputSection *> selectedSections;
+ SmallVector<InputSection *, 0> selectedSections;
selectedSections.reserve(executableSections.size());
selectedSections.push_back(executableSections[0]);
size_t prev = 0;
@@ -3813,7 +3822,10 @@ void InStruct::reset() {
gotPlt.reset();
igotPlt.reset();
ppc64LongBranchTarget.reset();
+ mipsAbiFlags.reset();
mipsGot.reset();
+ mipsOptions.reset();
+ mipsReginfo.reset();
mipsRldMap.reset();
partEnd.reset();
partIndex.reset();