Skip to content

Commit 8548348

Browse files
committed
Deterministically allocate GOT/PLT slots
Slots are now created during relocation scanning deterministically in input order, matching lld. The scan is now serial. Slot creation within it was already serialized on a mutex, so parallelism only decided which input reached the lock first. .rela.dyn and .rela.plt are created once alongside .got/.plt rather than per input file. ifunc loops now iterate .plt instead of a DenseMap, which is not deterministic even under a single-threaded link. Signed-off-by: quic-areg <aregmi@qti.qualcomm.com>
1 parent aedb2c9 commit 8548348

22 files changed

Lines changed: 185 additions & 104 deletions

File tree

include/eld/Input/ELFObjectFile.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ class ELFObjectFile : public ELFFileBase {
4848
void setDynamicSections(ELFSection &GOT, ELFSection &GOTPLT, ELFSection &PLT,
4949
ELFSection &RelDyn, ELFSection &RelPLT);
5050

51-
void setDynamicRelocSections(ELFSection &RelDyn, ELFSection &RelPLT);
52-
5351
ELFSection *getRelaDyn() const { return RelaDyn; }
5452
ELFSection *getRelaPLT() const { return RelaPLT; }
5553

include/eld/Target/GNULDBackend.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,6 +1297,8 @@ class GNULDBackend {
12971297
ELFSection *GOTSection = nullptr;
12981298
ELFSection *GOTPLTSection = nullptr;
12991299
ELFSection *PLTSection = nullptr;
1300+
ELFSection *RelDynSection = nullptr;
1301+
ELFSection *RelPLTSection = nullptr;
13001302
LDSymbol *m_pGOTSymbol = nullptr;
13011303
llvm::DenseMap<const Relocation *, Relocation *> m_RelativeRelocMap;
13021304

lib/Core/Linker.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,6 @@ bool Linker::link() {
169169
return false;
170170
}
171171

172-
// Init per-file synthetic dynamic sections.
173-
if (LinkerConfig::Object != ThisConfig->codeGenType()) {
174-
for (auto &Input : ThisModule->getObjectList())
175-
if (ELFObjectFile *ELFObj = llvm::dyn_cast<ELFObjectFile>(Input))
176-
Backend->initDynamicSections(*ELFObj);
177-
}
178-
179172
if (ThisModule->getPrinter()->isVerbose())
180173
ThisConfig->raise(Diag::merging_input_sections);
181174
{

lib/Input/ELFObjectFile.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,6 @@ void ELFObjectFile::setDynamicSections(ELFSection &PGOT, ELFSection &PGOTPLT,
4444
RelaPLT->setExcludedFromGC();
4545
}
4646

47-
void ELFObjectFile::setDynamicRelocSections(ELFSection &PRelDyn,
48-
ELFSection &PRelPLT) {
49-
RelaDyn = &PRelDyn;
50-
RelaPLT = &PRelPLT;
51-
RelaDyn->setExcludedFromGC();
52-
RelaPLT->setExcludedFromGC();
53-
}
54-
5547
void ELFObjectFile::createDWARFContext(bool Is32) {
5648
if (DebugSections.empty())
5749
return;

lib/Object/ObjectLinker.cpp

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,54 +2203,21 @@ bool ObjectLinker::scanRelocations(bool IsPartialLink) {
22032203

22042204
getTargetBackend().provideSymbols();
22052205

2206+
// Slots are allocated as relocations are scanned in input order.
22062207
std::vector<std::unique_ptr<Relocator::CopyRelocs>> AllCopyRelocs;
2207-
if (ThisConfig.options().numThreads() <= 1 ||
2208-
!ThisConfig.isScanRelocationsMultiThreaded()) {
2209-
if (ThisModule->getPrinter()->traceThreads())
2210-
ThisConfig.raise(Diag::threads_disabled) << "ScanRelocations";
2211-
for (auto &Input : ThisModule->getObjectList()) {
2212-
auto CopyRelocs = std::make_unique<Relocator::CopyRelocs>();
2213-
scanRelocationsHelper(Input, IsPartialLink, PluginVect, *CopyRelocs);
2214-
AllCopyRelocs.push_back(std::move(CopyRelocs));
2215-
}
2216-
} else {
2217-
if (ThisModule->getPrinter()->traceThreads())
2218-
ThisConfig.raise(Diag::threads_enabled)
2219-
<< "ScanRelocations" << ThisConfig.options().numThreads();
2220-
llvm::ThreadPoolInterface *Pool = ThisModule->getThreadPool();
2221-
for (auto &Input : ThisModule->getObjectList()) {
2222-
auto CopyRelocs = std::make_unique<Relocator::CopyRelocs>();
2223-
auto &CopyRelocsRef = *CopyRelocs; // must dereference in the main thread
2224-
Pool->async([&] {
2225-
scanRelocationsHelper(Input, IsPartialLink, PluginVect, CopyRelocsRef);
2226-
});
2227-
AllCopyRelocs.push_back(std::move(CopyRelocs));
2228-
}
2229-
Pool->wait();
2208+
if (ThisModule->getPrinter()->traceThreads())
2209+
ThisConfig.raise(Diag::threads_disabled) << "ScanRelocations";
2210+
for (auto &Input : ThisModule->getObjectList()) {
2211+
auto CopyRelocs = std::make_unique<Relocator::CopyRelocs>();
2212+
scanRelocationsHelper(Input, IsPartialLink, PluginVect, *CopyRelocs);
2213+
AllCopyRelocs.push_back(std::move(CopyRelocs));
22302214
}
22312215
// assume there is only one copy relocation type per target
22322216
Relocation::Type CopyRelocType = getTargetBackend().getCopyRelType();
22332217
for (const auto &RelocVec : AllCopyRelocs)
22342218
for (auto &Reloc : *RelocVec)
22352219
createCopyRelocation(*Reloc, CopyRelocType);
22362220

2237-
// Merge per-file relocations
2238-
if (!IsPartialLink) {
2239-
ELFObjectFile *RelocInput =
2240-
getTargetBackend().getDynamicSectionHeadersInputFile();
2241-
auto MergeRelocs = [](ELFSection &To, ELFSection &From) {
2242-
To.appendRelocations(From.getRelocations());
2243-
};
2244-
for (auto &Input : ThisModule->getObjectList())
2245-
if (ELFObjectFile *Obj = llvm::dyn_cast<ELFObjectFile>(Input))
2246-
if (Obj != RelocInput) {
2247-
if (const auto &S = Obj->getRelaDyn())
2248-
MergeRelocs(*RelocInput->getRelaDyn(), *S);
2249-
if (const auto &S = Obj->getRelaPLT())
2250-
MergeRelocs(*RelocInput->getRelaPLT(), *S);
2251-
}
2252-
}
2253-
22542221
// If there is a undefined symbol, fail the link. No point fixing the
22552222
// relocations. This is overridden by --noinhibit-exec.
22562223
if (!ThisConfig.getDiagEngine()->diagnose()) {

lib/Target/AArch64/AArch64LDBackend.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -523,8 +523,15 @@ bool AArch64LDBackend::finalizeScanRelocations() {
523523
if (!Obj)
524524
return true;
525525

526-
for (auto &[symInfo, plt] : m_PLTMap) {
527-
if (!symInfo->isIFunc() || !symInfo->hasIFuncDirectRef() ||
526+
if (!getPLT())
527+
return true;
528+
529+
for (Fragment *F : getPLT()->getFragmentList()) {
530+
auto *plt = llvm::dyn_cast<AArch64PLT>(F);
531+
if (!plt)
532+
continue;
533+
ResolveInfo *symInfo = plt->symInfo();
534+
if (!symInfo || !symInfo->isIFunc() || !symInfo->hasIFuncDirectRef() ||
528535
!symInfo->hasIFuncNeedsGOT())
529536
continue;
530537

@@ -745,7 +752,7 @@ AArch64PLT *AArch64LDBackend::createPLT(ELFObjectFile *Obj, ResolveInfo *R,
745752
*m_Module.getIRBuilder(), createGOT(GOT::GOTPLTN, Obj, R, isIRelative),
746753
getPLT(), R);
747754
// init the corresponding rel entry in .rela.plt
748-
Relocation &rela_entry = *Obj->getRelaPLT()->createOneReloc();
755+
Relocation &rela_entry = *getRelaPLT()->createOneReloc();
749756
rela_entry.setType(isIRelative ? llvm::ELF::R_AARCH64_IRELATIVE
750757
: llvm::ELF::R_AARCH64_JUMP_SLOT);
751758
rela_entry.setTargetRef(make<FragmentRef>(*P->getGOT(), 0));

lib/Target/AArch64/AArch64Relocator.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ Relocation *helper_DynRel_init(ELFObjectFile *Obj, Relocation *R,
5656
Relocation *rela_entry = nullptr;
5757

5858
if (pType == R_AARCH64_TLSDESC)
59-
rela_entry = Obj->getRelaPLT()->createOneReloc();
59+
rela_entry = B.getRelaPLT()->createOneReloc();
6060
else
61-
rela_entry = Obj->getRelaDyn()->createOneReloc();
61+
rela_entry = B.getRelaDyn()->createOneReloc();
6262

6363
rela_entry->setType(pType);
6464
rela_entry->setTargetRef(make<FragmentRef>(*F, pOffset));

lib/Target/ARM/ARMLDBackend.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -637,8 +637,15 @@ bool ARMGNULDBackend::finalizeScanRelocations() {
637637
// holds the address of PLT[ifunc]. GOT references then resolve to this slot
638638
// rather than the GOTPLT slot, so that the GOT-loaded pointer equals the
639639
// direct-reference pointer (pointer equality).
640-
for (auto &[symInfo, plt] : m_PLTMap) {
641-
if (!symInfo->isIFunc() || !symInfo->hasIFuncDirectRef() ||
640+
if (!getPLT())
641+
return true;
642+
643+
for (Fragment *F : getPLT()->getFragmentList()) {
644+
auto *plt = llvm::dyn_cast<ARMPLT>(F);
645+
if (!plt)
646+
continue;
647+
ResolveInfo *symInfo = plt->symInfo();
648+
if (!symInfo || !symInfo->isIFunc() || !symInfo->hasIFuncDirectRef() ||
642649
!symInfo->hasIFuncNeedsGOT())
643650
continue;
644651
ARMGOT *G = createGOT(GOT::Regular, nullptr, symInfo);
@@ -1121,7 +1128,7 @@ ARMPLT *ARMGNULDBackend::createPLT(ELFObjectFile *Obj, ResolveInfo *R,
11211128
*m_Module.getIRBuilder(),
11221129
createGOT(GOT::GOTPLTN, Obj, R, hasNow || isIRelative), getPLT(), R);
11231130
// init the corresponding rel entry in .rel.plt
1124-
Relocation *rel_entry = Obj->getRelaPLT()->createOneReloc();
1131+
Relocation *rel_entry = getRelaPLT()->createOneReloc();
11251132
rel_entry->setType(isIRelative ? llvm::ELF::R_ARM_IRELATIVE
11261133
: llvm::ELF::R_ARM_JUMP_SLOT);
11271134
rel_entry->setTargetRef(make<FragmentRef>(*P->getGOT(), 0));

lib/Target/ARM/ARMRelocator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static Relocation *helper_DynRel_init(ELFObjectFile *Obj, Relocation *R,
6868
ResolveInfo *pSym, Fragment *F,
6969
uint32_t pOffset, Relocator::Type pType,
7070
ARMGNULDBackend &B) {
71-
Relocation *rel_entry = Obj->getRelaDyn()->createOneReloc();
71+
Relocation *rel_entry = B.getRelaDyn()->createOneReloc();
7272
rel_entry->setType(pType);
7373
rel_entry->setTargetRef(make<FragmentRef>(*F, pOffset));
7474
rel_entry->setSymInfo(pSym);

lib/Target/GNULDBackend.cpp

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,21 +1717,19 @@ ELFSection *GNULDBackend::getPLT() const { return PLTSection; }
17171717

17181718
void GNULDBackend::initDynamicSections(ELFObjectFile &InputFile,
17191719
const DynamicSectionLayout &Layout) {
1720+
if (GOTSection)
1721+
return;
1722+
17201723
bool IsRela = Layout.RelType == llvm::ELF::SHT_RELA;
1721-
ELFSection &RelDyn = *m_Module.createInternalSection(
1724+
RelDynSection = m_Module.createInternalSection(
17221725
InputFile, LDFileFormat::DynamicRelocation,
17231726
IsRela ? ".rela.dyn" : ".rel.dyn", Layout.RelType, llvm::ELF::SHF_ALLOC,
17241727
Layout.RelAlign);
1725-
ELFSection &RelPLT = *m_Module.createInternalSection(
1728+
RelPLTSection = m_Module.createInternalSection(
17261729
InputFile, LDFileFormat::DynamicRelocation,
17271730
IsRela ? ".rela.plt" : ".rel.plt", Layout.RelType, llvm::ELF::SHF_ALLOC,
17281731
Layout.RelAlign);
17291732

1730-
if (GOTSection) {
1731-
InputFile.setDynamicRelocSections(RelDyn, RelPLT);
1732-
return;
1733-
}
1734-
17351733
auto Create = [&](std::string Name, uint32_t Flags, uint32_t Align) {
17361734
return m_Module.createInternalSection(InputFile, LDFileFormat::Internal,
17371735
Name, llvm::ELF::SHT_PROGBITS, Flags,
@@ -1744,17 +1742,13 @@ void GNULDBackend::initDynamicSections(ELFObjectFile &InputFile,
17441742
Layout.GOTPLTAlign);
17451743
PLTSection = Create(".plt", llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
17461744
Layout.PLTAlign);
1747-
InputFile.setDynamicSections(*GOTSection, *GOTPLTSection, *PLTSection, RelDyn,
1748-
RelPLT);
1745+
InputFile.setDynamicSections(*GOTSection, *GOTPLTSection, *PLTSection,
1746+
*RelDynSection, *RelPLTSection);
17491747
}
17501748

1751-
ELFSection *GNULDBackend::getRelaDyn() const {
1752-
return m_DynamicSectionHeadersInputFile->getRelaDyn();
1753-
}
1749+
ELFSection *GNULDBackend::getRelaDyn() const { return RelDynSection; }
17541750

1755-
ELFSection *GNULDBackend::getRelaPLT() const {
1756-
return m_DynamicSectionHeadersInputFile->getRelaPLT();
1757-
}
1751+
ELFSection *GNULDBackend::getRelaPLT() const { return RelPLTSection; }
17581752

17591753
void GNULDBackend::reportErrorIfGOTIsDiscarded(ResolveInfo *R) const {
17601754
ELFSection *GOT = getGOT();

0 commit comments

Comments
 (0)