aboutsummaryrefslogtreecommitdiffstats
path: root/ELF/SyntheticSections.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ELF/SyntheticSections.cpp')
-rw-r--r--ELF/SyntheticSections.cpp485
1 files changed, 271 insertions, 214 deletions
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index f6d0f190d84d..ff35bb7bd10c 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -45,13 +45,12 @@ using namespace llvm::ELF;
using namespace llvm::object;
using namespace llvm::support;
-using namespace lld;
-using namespace lld::elf;
-
using llvm::support::endian::read32le;
using llvm::support::endian::write32le;
using llvm::support::endian::write64le;
+namespace lld {
+namespace elf {
constexpr size_t MergeNoTailSection::numShards;
static uint64_t readUint(uint8_t *buf) {
@@ -82,7 +81,7 @@ static ArrayRef<uint8_t> getVersion() {
// With this feature, you can identify LLD-generated binaries easily
// by "readelf --string-dump .comment <file>".
// The returned object is a mergeable string section.
-MergeInputSection *elf::createCommentSection() {
+MergeInputSection *createCommentSection() {
return make<MergeInputSection>(SHF_MERGE | SHF_STRINGS, SHT_PROGBITS, 1,
getVersion(), ".comment");
}
@@ -138,7 +137,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {
flags.ases |= s->ases;
flags.flags1 |= s->flags1;
flags.flags2 |= s->flags2;
- flags.fp_abi = elf::getMipsFpAbiFlag(flags.fp_abi, s->fp_abi, filename);
+ flags.fp_abi = getMipsFpAbiFlag(flags.fp_abi, s->fp_abi, filename);
};
if (create)
@@ -252,19 +251,17 @@ MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() {
return make<MipsReginfoSection<ELFT>>(reginfo);
}
-InputSection *elf::createInterpSection() {
+InputSection *createInterpSection() {
// StringSaver guarantees that the returned string ends with '\0'.
StringRef s = saver.save(config->dynamicLinker);
ArrayRef<uint8_t> contents = {(const uint8_t *)s.data(), s.size() + 1};
- auto *sec = make<InputSection>(nullptr, SHF_ALLOC, SHT_PROGBITS, 1, contents,
- ".interp");
- sec->markLive();
- return sec;
+ return make<InputSection>(nullptr, SHF_ALLOC, SHT_PROGBITS, 1, contents,
+ ".interp");
}
-Defined *elf::addSyntheticLocal(StringRef name, uint8_t type, uint64_t value,
- uint64_t size, InputSectionBase &section) {
+Defined *addSyntheticLocal(StringRef name, uint8_t type, uint64_t value,
+ uint64_t size, InputSectionBase &section) {
auto *s = make<Defined>(section.file, name, STB_LOCAL, STV_DEFAULT, type,
value, size, &section);
if (in.symTab)
@@ -402,7 +399,7 @@ bool EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef<RelTy> rels) {
// a list of FDEs. This function searches an existing CIE or create a new
// one and associates FDEs to the CIE.
template <class ELFT, class RelTy>
-void EhFrameSection::addSectionAux(EhInputSection *sec, ArrayRef<RelTy> rels) {
+void EhFrameSection::addRecords(EhInputSection *sec, ArrayRef<RelTy> rels) {
offsetToCie.clear();
for (EhSectionPiece &piece : sec->pieces) {
// The empty record is the end marker.
@@ -428,8 +425,17 @@ void EhFrameSection::addSectionAux(EhInputSection *sec, ArrayRef<RelTy> rels) {
}
}
-template <class ELFT> void EhFrameSection::addSection(InputSectionBase *c) {
- auto *sec = cast<EhInputSection>(c);
+template <class ELFT>
+void EhFrameSection::addSectionAux(EhInputSection *sec) {
+ if (!sec->isLive())
+ return;
+ if (sec->areRelocsRela)
+ addRecords<ELFT>(sec, sec->template relas<ELFT>());
+ else
+ addRecords<ELFT>(sec, sec->template rels<ELFT>());
+}
+
+void EhFrameSection::addSection(EhInputSection *sec) {
sec->parent = this;
alignment = std::max(alignment, sec->alignment);
@@ -437,14 +443,6 @@ template <class ELFT> void EhFrameSection::addSection(InputSectionBase *c) {
for (auto *ds : sec->dependentSections)
dependentSections.push_back(ds);
-
- if (sec->pieces.empty())
- return;
-
- if (sec->areRelocsRela)
- addSectionAux<ELFT>(sec, sec->template relas<ELFT>());
- else
- addSectionAux<ELFT>(sec, sec->template rels<ELFT>());
}
static void writeCieFde(uint8_t *buf, ArrayRef<uint8_t> d) {
@@ -461,6 +459,28 @@ static void writeCieFde(uint8_t *buf, ArrayRef<uint8_t> d) {
void EhFrameSection::finalizeContents() {
assert(!this->size); // Not finalized.
+
+ switch (config->ekind) {
+ case ELFNoneKind:
+ llvm_unreachable("invalid ekind");
+ case ELF32LEKind:
+ for (EhInputSection *sec : sections)
+ addSectionAux<ELF32LE>(sec);
+ break;
+ case ELF32BEKind:
+ for (EhInputSection *sec : sections)
+ addSectionAux<ELF32BE>(sec);
+ break;
+ case ELF64LEKind:
+ for (EhInputSection *sec : sections)
+ addSectionAux<ELF64LE>(sec);
+ break;
+ case ELF64BEKind:
+ for (EhInputSection *sec : sections)
+ addSectionAux<ELF64BE>(sec);
+ break;
+ }
+
size_t off = 0;
for (CieRecord *rec : cieRecords) {
rec->cie->outputOff = off;
@@ -1162,10 +1182,12 @@ void StringTableSection::writeTo(uint8_t *buf) {
}
}
-// Returns the number of version definition entries. Because the first entry
-// is for the version definition itself, it is the number of versioned symbols
-// plus one. Note that we don't support multiple versions yet.
-static unsigned getVerDefNum() { return config->versionDefinitions.size() + 1; }
+// Returns the number of entries in .gnu.version_d: the number of
+// non-VER_NDX_LOCAL-non-VER_NDX_GLOBAL definitions, plus 1.
+// Note that we don't support vd_cnt > 1 yet.
+static unsigned getVerDefNum() {
+ return namedVersionDefs().size() + 1;
+}
template <class ELFT>
DynamicSection<ELFT>::DynamicSection()
@@ -1218,6 +1240,25 @@ void DynamicSection<ELFT>::addSym(int32_t tag, Symbol *sym) {
entries.push_back({tag, [=] { return sym->getVA(); }});
}
+// The output section .rela.dyn may include these synthetic sections:
+//
+// - part.relaDyn
+// - in.relaIplt: this is included if in.relaIplt is named .rela.dyn
+// - in.relaPlt: this is included if a linker script places .rela.plt inside
+// .rela.dyn
+//
+// DT_RELASZ is the total size of the included sections.
+static std::function<uint64_t()> addRelaSz(RelocationBaseSection *relaDyn) {
+ return [=]() {
+ size_t size = relaDyn->getSize();
+ if (in.relaIplt->getParent() == relaDyn->getParent())
+ size += in.relaIplt->getSize();
+ if (in.relaPlt->getParent() == relaDyn->getParent())
+ size += in.relaPlt->getSize();
+ return size;
+ };
+}
+
// A Linker script may assign the RELA relocation sections to the same
// output section. When this occurs we cannot just use the OutputSection
// Size. Moreover the [DT_JMPREL, DT_JMPREL + DT_PLTRELSZ) is permitted to
@@ -1232,7 +1273,7 @@ static uint64_t addPltRelSz() {
// Add remaining entries to complete .dynamic contents.
template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
- elf::Partition &part = getPartition();
+ Partition &part = getPartition();
bool isMain = part.name.empty();
for (StringRef s : config->filterList)
@@ -1306,9 +1347,11 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
if (OutputSection *sec = part.dynStrTab->getParent())
this->link = sec->sectionIndex;
- if (part.relaDyn->isNeeded()) {
+ if (part.relaDyn->isNeeded() ||
+ (in.relaIplt->isNeeded() &&
+ part.relaDyn->getParent() == in.relaIplt->getParent())) {
addInSec(part.relaDyn->dynamicTag, part.relaDyn);
- addSize(part.relaDyn->sizeDynamicTag, part.relaDyn->getParent());
+ entries.push_back({part.relaDyn->sizeDynamicTag, addRelaSz(part.relaDyn)});
bool isRela = config->isRela;
addInt(isRela ? DT_RELAENT : DT_RELENT,
@@ -1679,6 +1722,56 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
relativeGroups.emplace_back(std::move(group));
}
+ // For non-relative relocations, we would like to:
+ // 1. Have relocations with the same symbol offset to be consecutive, so
+ // that the runtime linker can speed-up symbol lookup by implementing an
+ // 1-entry cache.
+ // 2. Group relocations by r_info to reduce the size of the relocation
+ // section.
+ // Since the symbol offset is the high bits in r_info, sorting by r_info
+ // allows us to do both.
+ //
+ // For Rela, we also want to sort by r_addend when r_info is the same. This
+ // enables us to group by r_addend as well.
+ llvm::stable_sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) {
+ if (a.r_info != b.r_info)
+ return a.r_info < b.r_info;
+ if (config->isRela)
+ return a.r_addend < b.r_addend;
+ return false;
+ });
+
+ // Group relocations with the same r_info. Note that each group emits a group
+ // header and that may make the relocation section larger. It is hard to
+ // estimate the size of a group header as the encoded size of that varies
+ // based on r_info. However, we can approximate this trade-off by the number
+ // of values encoded. Each group header contains 3 values, and each relocation
+ // in a group encodes one less value, as compared to when it is not grouped.
+ // Therefore, we only group relocations if there are 3 or more of them with
+ // the same r_info.
+ //
+ // For Rela, the addend for most non-relative relocations is zero, and thus we
+ // can usually get a smaller relocation section if we group relocations with 0
+ // addend as well.
+ std::vector<Elf_Rela> ungroupedNonRelatives;
+ std::vector<std::vector<Elf_Rela>> nonRelativeGroups;
+ for (auto i = nonRelatives.begin(), e = nonRelatives.end(); i != e;) {
+ auto j = i + 1;
+ while (j != e && i->r_info == j->r_info &&
+ (!config->isRela || i->r_addend == j->r_addend))
+ ++j;
+ if (j - i < 3 || (config->isRela && i->r_addend != 0))
+ ungroupedNonRelatives.insert(ungroupedNonRelatives.end(), i, j);
+ else
+ nonRelativeGroups.emplace_back(i, j);
+ i = j;
+ }
+
+ // Sort ungrouped relocations by offset to minimize the encoded length.
+ llvm::sort(ungroupedNonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) {
+ return a.r_offset < b.r_offset;
+ });
+
unsigned hasAddendIfRela =
config->isRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG : 0;
@@ -1733,14 +1826,23 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
}
}
- // Finally the non-relative relocations.
- llvm::sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) {
- return a.r_offset < b.r_offset;
- });
- if (!nonRelatives.empty()) {
- add(nonRelatives.size());
+ // Grouped non-relatives.
+ for (ArrayRef<Elf_Rela> g : nonRelativeGroups) {
+ add(g.size());
+ add(RELOCATION_GROUPED_BY_INFO_FLAG);
+ add(g[0].r_info);
+ for (const Elf_Rela &r : g) {
+ add(r.r_offset - offset);
+ offset = r.r_offset;
+ }
+ addend = 0;
+ }
+
+ // Finally the ungrouped non-relative relocations.
+ if (!ungroupedNonRelatives.empty()) {
+ add(ungroupedNonRelatives.size());
add(hasAddendIfRela);
- for (Elf_Rela &r : nonRelatives) {
+ for (Elf_Rela &r : ungroupedNonRelatives) {
add(r.r_offset - offset);
offset = r.r_offset;
add(r.r_info);
@@ -1852,6 +1954,14 @@ template <class ELFT> bool RelrSection<ELFT>::updateAllocSize() {
}
}
+ // Don't allow the section to shrink; otherwise the size of the section can
+ // oscillate infinitely. Trailing 1s do not decode to more relocations.
+ if (relrRelocs.size() < oldSize) {
+ log(".relr.dyn needs " + Twine(oldSize - relrRelocs.size()) +
+ " padding word(s)");
+ relrRelocs.resize(oldSize, Elf_Relr(1));
+ }
+
return relrRelocs.size() != oldSize;
}
@@ -2452,6 +2562,10 @@ readAddressAreas(DWARFContext &dwarf, InputSection *sec) {
uint32_t cuIdx = 0;
for (std::unique_ptr<DWARFUnit> &cu : dwarf.compile_units()) {
+ if (Error e = cu->tryExtractDIEsIfNeeded(false)) {
+ error(toString(sec) + ": " + toString(std::move(e)));
+ return {};
+ }
Expected<DWARFAddressRangesVector> ranges = cu->collectAddressRanges();
if (!ranges) {
error(toString(sec) + ": " + toString(ranges.takeError()));
@@ -2481,9 +2595,9 @@ readAddressAreas(DWARFContext &dwarf, InputSection *sec) {
template <class ELFT>
static std::vector<GdbIndexSection::NameAttrEntry>
readPubNamesAndTypes(const LLDDwarfObj<ELFT> &obj,
- const std::vector<GdbIndexSection::CuEntry> &cUs) {
- const DWARFSection &pubNames = obj.getGnuPubNamesSection();
- const DWARFSection &pubTypes = obj.getGnuPubTypesSection();
+ const std::vector<GdbIndexSection::CuEntry> &cus) {
+ const DWARFSection &pubNames = obj.getGnuPubnamesSection();
+ const DWARFSection &pubTypes = obj.getGnuPubtypesSection();
std::vector<GdbIndexSection::NameAttrEntry> ret;
for (const DWARFSection *pub : {&pubNames, &pubTypes}) {
@@ -2493,12 +2607,11 @@ readPubNamesAndTypes(const LLDDwarfObj<ELFT> &obj,
// don't know how many compilation units precede this object to compute
// cuIndex, we compute (kind << 24 | cuIndexInThisObject) instead, and add
// the number of preceding compilation units later.
- uint32_t i =
- lower_bound(cUs, set.Offset,
- [](GdbIndexSection::CuEntry cu, uint32_t offset) {
- return cu.cuOffset < offset;
- }) -
- cUs.begin();
+ uint32_t i = llvm::partition_point(cus,
+ [&](GdbIndexSection::CuEntry cu) {
+ return cu.cuOffset < set.Offset;
+ }) -
+ cus.begin();
for (const DWARFDebugPubTable::Entry &ent : set.Entries)
ret.push_back({{ent.Name, computeGdbHash(ent.Name)},
(ent.Descriptor.toBits() << 24) | i});
@@ -2603,7 +2716,7 @@ template <class ELFT> GdbIndexSection *GdbIndexSection::create() {
parallelForEachN(0, sections.size(), [&](size_t i) {
ObjFile<ELFT> *file = sections[i]->getFile<ELFT>();
- DWARFContext dwarf(make_unique<LLDDwarfObj<ELFT>>(file));
+ DWARFContext dwarf(std::make_unique<LLDDwarfObj<ELFT>>(file));
chunks[i].sec = sections[i];
chunks[i].compilationUnits = readCuList(dwarf);
@@ -2750,7 +2863,7 @@ StringRef VersionDefinitionSection::getFileDefName() {
void VersionDefinitionSection::finalizeContents() {
fileDefNameOff = getPartition().dynStrTab->addString(getFileDefName());
- for (VersionDefinition &v : config->versionDefinitions)
+ for (const VersionDefinition &v : namedVersionDefs())
verDefNameOffs.push_back(getPartition().dynStrTab->addString(v.name));
if (OutputSection *sec = getPartition().dynStrTab->getParent())
@@ -2784,7 +2897,7 @@ void VersionDefinitionSection::writeTo(uint8_t *buf) {
writeOne(buf, 1, getFileDefName(), fileDefNameOff);
auto nameOffIt = verDefNameOffs.begin();
- for (VersionDefinition &v : config->versionDefinitions) {
+ for (const VersionDefinition &v : namedVersionDefs()) {
buf += EntrySize;
writeOne(buf, v.id, v.name, *nameOffIt++);
}
@@ -2826,7 +2939,7 @@ bool VersionTableSection::isNeeded() const {
return getPartition().verDef || getPartition().verNeed->isNeeded();
}
-void elf::addVerneed(Symbol *ss) {
+void addVerneed(Symbol *ss) {
auto &file = cast<SharedFile>(*ss->file);
if (ss->verdefIndex == VER_NDX_GLOBAL) {
ss->versionId = VER_NDX_GLOBAL;
@@ -3009,17 +3122,16 @@ void MergeNoTailSection::finalizeContents() {
});
}
-static MergeSyntheticSection *createMergeSynthetic(StringRef name,
- uint32_t type,
- uint64_t flags,
- uint32_t alignment) {
+MergeSyntheticSection *createMergeSynthetic(StringRef name, uint32_t type,
+ uint64_t flags,
+ uint32_t alignment) {
bool shouldTailMerge = (flags & SHF_STRINGS) && config->optimize >= 2;
if (shouldTailMerge)
return make<MergeTailSection>(name, type, flags, alignment);
return make<MergeNoTailSection>(name, type, flags, alignment);
}
-template <class ELFT> void elf::splitSections() {
+template <class ELFT> void splitSections() {
// splitIntoPieces needs to be called on each MergeInputSection
// before calling finalizeContents().
parallelForEach(inputSections, [](InputSectionBase *sec) {
@@ -3030,63 +3142,6 @@ template <class ELFT> void elf::splitSections() {
});
}
-// This function scans over the inputsections to create mergeable
-// synthetic sections.
-//
-// It removes MergeInputSections from the input section array and adds
-// new synthetic sections at the location of the first input section
-// that it replaces. It then finalizes each synthetic section in order
-// to compute an output offset for each piece of each input section.
-void elf::mergeSections() {
- std::vector<MergeSyntheticSection *> mergeSections;
- for (InputSectionBase *&s : inputSections) {
- MergeInputSection *ms = dyn_cast<MergeInputSection>(s);
- if (!ms)
- continue;
-
- // We do not want to handle sections that are not alive, so just remove
- // them instead of trying to merge.
- if (!ms->isLive()) {
- s = nullptr;
- continue;
- }
-
- StringRef outsecName = getOutputSectionName(ms);
-
- auto i = llvm::find_if(mergeSections, [=](MergeSyntheticSection *sec) {
- // While we could create a single synthetic section for two different
- // values of Entsize, it is better to take Entsize into consideration.
- //
- // With a single synthetic section no two pieces with different Entsize
- // could be equal, so we may as well have two sections.
- //
- // Using Entsize in here also allows us to propagate it to the synthetic
- // section.
- //
- // SHF_STRINGS section with different alignments should not be merged.
- return sec->name == outsecName && sec->flags == ms->flags &&
- sec->entsize == ms->entsize &&
- (sec->alignment == ms->alignment || !(sec->flags & SHF_STRINGS));
- });
- if (i == mergeSections.end()) {
- MergeSyntheticSection *syn =
- createMergeSynthetic(outsecName, ms->type, ms->flags, ms->alignment);
- mergeSections.push_back(syn);
- i = std::prev(mergeSections.end());
- s = syn;
- syn->entsize = ms->entsize;
- } else {
- s = nullptr;
- }
- (*i)->addSection(ms);
- }
- for (auto *ms : mergeSections)
- ms->finalizeContents();
-
- std::vector<InputSectionBase *> &v = inputSections;
- v.erase(std::remove(v.begin(), v.end(), nullptr), v.end());
-}
-
MipsRldMapSection::MipsRldMapSection()
: SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize,
".rld_map") {}
@@ -3102,17 +3157,23 @@ static InputSection *findExidxSection(InputSection *isec) {
return nullptr;
}
+static bool isValidExidxSectionDep(InputSection *isec) {
+ return (isec->flags & SHF_ALLOC) && (isec->flags & SHF_EXECINSTR) &&
+ isec->getSize() > 0;
+}
+
bool ARMExidxSyntheticSection::addSection(InputSection *isec) {
if (isec->type == SHT_ARM_EXIDX) {
- exidxSections.push_back(isec);
- return true;
+ if (InputSection* dep = isec->getLinkOrderDep())
+ if (isValidExidxSectionDep(dep)) {
+ exidxSections.push_back(isec);
+ return true;
+ }
+ return false;
}
- if ((isec->flags & SHF_ALLOC) && (isec->flags & SHF_EXECINSTR) &&
- isec->getSize() > 0) {
+ if (isValidExidxSectionDep(isec)) {
executableSections.push_back(isec);
- if (empty && findExidxSection(isec))
- empty = false;
return false;
}
@@ -3177,11 +3238,20 @@ static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) {
// The .ARM.exidx table must be sorted in ascending order of the address of the
// functions the table describes. Optionally duplicate adjacent table entries
-// can be removed. At the end of the function the ExecutableSections must be
+// can be removed. At the end of the function the executableSections must be
// sorted in ascending order of address, Sentinel is set to the InputSection
// with the highest address and any InputSections that have mergeable
// .ARM.exidx table entries are removed from it.
void ARMExidxSyntheticSection::finalizeContents() {
+ // The executableSections and exidxSections that we use to derive the final
+ // contents of this SyntheticSection are populated before
+ // processSectionCommands() and ICF. A /DISCARD/ entry in SECTIONS command or
+ // ICF may remove executable InputSections and their dependent .ARM.exidx
+ // section that we recorded earlier.
+ auto isDiscarded = [](const InputSection *isec) { return !isec->isLive(); };
+ llvm::erase_if(executableSections, isDiscarded);
+ llvm::erase_if(exidxSections, isDiscarded);
+
// Sort the executable sections that may or may not have associated
// .ARM.exidx sections by order of ascending address. This requires the
// relative positions of InputSections to be known.
@@ -3270,6 +3340,12 @@ void ARMExidxSyntheticSection::writeTo(uint8_t *buf) {
assert(size == offset + 8);
}
+bool ARMExidxSyntheticSection::isNeeded() const {
+ return llvm::find_if(exidxSections, [](InputSection *isec) {
+ return isec->isLive();
+ }) != exidxSections.end();
+}
+
bool ARMExidxSyntheticSection::classof(const SectionBase *d) {
return d->kind() == InputSectionBase::Synthetic && d->type == SHT_ARM_EXIDX;
}
@@ -3389,23 +3465,6 @@ bool PPC64LongBranchTargetSection::isNeeded() const {
return !finalized || !entries.empty();
}
-RISCVSdataSection::RISCVSdataSection()
- : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, 1, ".sdata") {}
-
-bool RISCVSdataSection::isNeeded() const {
- if (!ElfSym::riscvGlobalPointer)
- return false;
-
- // __global_pointer$ is defined relative to .sdata . If the section does not
- // exist, create a dummy one.
- for (BaseCommand *base : getParent()->sectionCommands)
- if (auto *isd = dyn_cast<InputSectionDescription>(base))
- for (InputSection *isec : isd->sections)
- if (isec != this)
- return false;
- return true;
-}
-
static uint8_t getAbiVersion() {
// MIPS non-PIC executable gets ABI version 1.
if (config->emachine == EM_MIPS) {
@@ -3426,7 +3485,7 @@ static uint8_t getAbiVersion() {
return 0;
}
-template <typename ELFT> void elf::writeEhdr(uint8_t *buf, Partition &part) {
+template <typename ELFT> void writeEhdr(uint8_t *buf, Partition &part) {
// For executable segments, the trap instructions are written before writing
// the header. Setting Elf header bytes to zero ensures that any unused bytes
// in header are zero-cleared, instead of having trap instructions.
@@ -3452,7 +3511,7 @@ template <typename ELFT> void elf::writeEhdr(uint8_t *buf, Partition &part) {
}
}
-template <typename ELFT> void elf::writePhdrs(uint8_t *buf, Partition &part) {
+template <typename ELFT> void writePhdrs(uint8_t *buf, Partition &part) {
// Write the program header table.
auto *hBuf = reinterpret_cast<typename ELFT::Phdr *>(buf);
for (PhdrEntry *p : part.phdrs) {
@@ -3527,92 +3586,90 @@ void PartitionIndexSection::writeTo(uint8_t *buf) {
}
}
-InStruct elf::in;
+InStruct in;
-std::vector<Partition> elf::partitions;
-Partition *elf::mainPart;
+std::vector<Partition> partitions;
+Partition *mainPart;
template GdbIndexSection *GdbIndexSection::create<ELF32LE>();
template GdbIndexSection *GdbIndexSection::create<ELF32BE>();
template GdbIndexSection *GdbIndexSection::create<ELF64LE>();
template GdbIndexSection *GdbIndexSection::create<ELF64BE>();
-template void elf::splitSections<ELF32LE>();
-template void elf::splitSections<ELF32BE>();
-template void elf::splitSections<ELF64LE>();
-template void elf::splitSections<ELF64BE>();
-
-template void EhFrameSection::addSection<ELF32LE>(InputSectionBase *);
-template void EhFrameSection::addSection<ELF32BE>(InputSectionBase *);
-template void EhFrameSection::addSection<ELF64LE>(InputSectionBase *);
-template void EhFrameSection::addSection<ELF64BE>(InputSectionBase *);
+template void splitSections<ELF32LE>();
+template void splitSections<ELF32BE>();
+template void splitSections<ELF64LE>();
+template void splitSections<ELF64BE>();
template void PltSection::addEntry<ELF32LE>(Symbol &Sym);
template void PltSection::addEntry<ELF32BE>(Symbol &Sym);
template void PltSection::addEntry<ELF64LE>(Symbol &Sym);
template void PltSection::addEntry<ELF64BE>(Symbol &Sym);
-template class elf::MipsAbiFlagsSection<ELF32LE>;
-template class elf::MipsAbiFlagsSection<ELF32BE>;
-template class elf::MipsAbiFlagsSection<ELF64LE>;
-template class elf::MipsAbiFlagsSection<ELF64BE>;
-
-template class elf::MipsOptionsSection<ELF32LE>;
-template class elf::MipsOptionsSection<ELF32BE>;
-template class elf::MipsOptionsSection<ELF64LE>;
-template class elf::MipsOptionsSection<ELF64BE>;
-
-template class elf::MipsReginfoSection<ELF32LE>;
-template class elf::MipsReginfoSection<ELF32BE>;
-template class elf::MipsReginfoSection<ELF64LE>;
-template class elf::MipsReginfoSection<ELF64BE>;
-
-template class elf::DynamicSection<ELF32LE>;
-template class elf::DynamicSection<ELF32BE>;
-template class elf::DynamicSection<ELF64LE>;
-template class elf::DynamicSection<ELF64BE>;
-
-template class elf::RelocationSection<ELF32LE>;
-template class elf::RelocationSection<ELF32BE>;
-template class elf::RelocationSection<ELF64LE>;
-template class elf::RelocationSection<ELF64BE>;
-
-template class elf::AndroidPackedRelocationSection<ELF32LE>;
-template class elf::AndroidPackedRelocationSection<ELF32BE>;
-template class elf::AndroidPackedRelocationSection<ELF64LE>;
-template class elf::AndroidPackedRelocationSection<ELF64BE>;
-
-template class elf::RelrSection<ELF32LE>;
-template class elf::RelrSection<ELF32BE>;
-template class elf::RelrSection<ELF64LE>;
-template class elf::RelrSection<ELF64BE>;
-
-template class elf::SymbolTableSection<ELF32LE>;
-template class elf::SymbolTableSection<ELF32BE>;
-template class elf::SymbolTableSection<ELF64LE>;
-template class elf::SymbolTableSection<ELF64BE>;
-
-template class elf::VersionNeedSection<ELF32LE>;
-template class elf::VersionNeedSection<ELF32BE>;
-template class elf::VersionNeedSection<ELF64LE>;
-template class elf::VersionNeedSection<ELF64BE>;
-
-template void elf::writeEhdr<ELF32LE>(uint8_t *Buf, Partition &Part);
-template void elf::writeEhdr<ELF32BE>(uint8_t *Buf, Partition &Part);
-template void elf::writeEhdr<ELF64LE>(uint8_t *Buf, Partition &Part);
-template void elf::writeEhdr<ELF64BE>(uint8_t *Buf, Partition &Part);
-
-template void elf::writePhdrs<ELF32LE>(uint8_t *Buf, Partition &Part);
-template void elf::writePhdrs<ELF32BE>(uint8_t *Buf, Partition &Part);
-template void elf::writePhdrs<ELF64LE>(uint8_t *Buf, Partition &Part);
-template void elf::writePhdrs<ELF64BE>(uint8_t *Buf, Partition &Part);
-
-template class elf::PartitionElfHeaderSection<ELF32LE>;
-template class elf::PartitionElfHeaderSection<ELF32BE>;
-template class elf::PartitionElfHeaderSection<ELF64LE>;
-template class elf::PartitionElfHeaderSection<ELF64BE>;
-
-template class elf::PartitionProgramHeadersSection<ELF32LE>;
-template class elf::PartitionProgramHeadersSection<ELF32BE>;
-template class elf::PartitionProgramHeadersSection<ELF64LE>;
-template class elf::PartitionProgramHeadersSection<ELF64BE>;
+template class MipsAbiFlagsSection<ELF32LE>;
+template class MipsAbiFlagsSection<ELF32BE>;
+template class MipsAbiFlagsSection<ELF64LE>;
+template class MipsAbiFlagsSection<ELF64BE>;
+
+template class MipsOptionsSection<ELF32LE>;
+template class MipsOptionsSection<ELF32BE>;
+template class MipsOptionsSection<ELF64LE>;
+template class MipsOptionsSection<ELF64BE>;
+
+template class MipsReginfoSection<ELF32LE>;
+template class MipsReginfoSection<ELF32BE>;
+template class MipsReginfoSection<ELF64LE>;
+template class MipsReginfoSection<ELF64BE>;
+
+template class DynamicSection<ELF32LE>;
+template class DynamicSection<ELF32BE>;
+template class DynamicSection<ELF64LE>;
+template class DynamicSection<ELF64BE>;
+
+template class RelocationSection<ELF32LE>;
+template class RelocationSection<ELF32BE>;
+template class RelocationSection<ELF64LE>;
+template class RelocationSection<ELF64BE>;
+
+template class AndroidPackedRelocationSection<ELF32LE>;
+template class AndroidPackedRelocationSection<ELF32BE>;
+template class AndroidPackedRelocationSection<ELF64LE>;
+template class AndroidPackedRelocationSection<ELF64BE>;
+
+template class RelrSection<ELF32LE>;
+template class RelrSection<ELF32BE>;
+template class RelrSection<ELF64LE>;
+template class RelrSection<ELF64BE>;
+
+template class SymbolTableSection<ELF32LE>;
+template class SymbolTableSection<ELF32BE>;
+template class SymbolTableSection<ELF64LE>;
+template class SymbolTableSection<ELF64BE>;
+
+template class VersionNeedSection<ELF32LE>;
+template class VersionNeedSection<ELF32BE>;
+template class VersionNeedSection<ELF64LE>;
+template class VersionNeedSection<ELF64BE>;
+
+template void writeEhdr<ELF32LE>(uint8_t *Buf, Partition &Part);
+template void writeEhdr<ELF32BE>(uint8_t *Buf, Partition &Part);
+template void writeEhdr<ELF64LE>(uint8_t *Buf, Partition &Part);
+template void writeEhdr<ELF64BE>(uint8_t *Buf, Partition &Part);
+
+template void writePhdrs<ELF32LE>(uint8_t *Buf, Partition &Part);
+template void writePhdrs<ELF32BE>(uint8_t *Buf, Partition &Part);
+template void writePhdrs<ELF64LE>(uint8_t *Buf, Partition &Part);
+template void writePhdrs<ELF64BE>(uint8_t *Buf, Partition &Part);
+
+template class PartitionElfHeaderSection<ELF32LE>;
+template class PartitionElfHeaderSection<ELF32BE>;
+template class PartitionElfHeaderSection<ELF64LE>;
+template class PartitionElfHeaderSection<ELF64BE>;
+
+template class PartitionProgramHeadersSection<ELF32LE>;
+template class PartitionProgramHeadersSection<ELF32BE>;
+template class PartitionProgramHeadersSection<ELF64LE>;
+template class PartitionProgramHeadersSection<ELF64BE>;
+
+} // namespace elf
+} // namespace lld