aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/Writer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/Writer.cpp')
-rw-r--r--lld/ELF/Writer.cpp35
1 files changed, 35 insertions, 0 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index e8a7b19..fe2e190 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1454,9 +1454,32 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
in.mipsGot->updateAllocSize();
for (Partition &part : partitions) {
+ // The R_AARCH64_AUTH_RELATIVE has a smaller addend field as bits [63:32]
+ // encode the signing schema. We've put relocations in .relr.auth.dyn
+ // during RelocationScanner::processAux, but the target VA for some of
+ // them might be wider than 32 bits. We can only know the final VA at this
+ // point, so move relocations with large values from .relr.auth.dyn to
+ // .rela.dyn. See also AArch64::relocate.
+ if (part.relrAuthDyn) {
+ auto it = llvm::remove_if(
+ part.relrAuthDyn->relocs, [&part](const RelativeReloc &elem) {
+ const Relocation &reloc = elem.inputSec->relocs()[elem.relocIdx];
+ if (isInt<32>(reloc.sym->getVA(reloc.addend)))
+ return false;
+ part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, elem.inputSec,
+ reloc.offset,
+ DynamicReloc::AddendOnlyWithTargetVA,
+ *reloc.sym, reloc.addend, R_ABS});
+ return true;
+ });
+ changed |= (it != part.relrAuthDyn->relocs.end());
+ part.relrAuthDyn->relocs.erase(it, part.relrAuthDyn->relocs.end());
+ }
changed |= part.relaDyn->updateAllocSize();
if (part.relrDyn)
changed |= part.relrDyn->updateAllocSize();
+ if (part.relrAuthDyn)
+ changed |= part.relrAuthDyn->updateAllocSize();
if (part.memtagGlobalDescriptors)
changed |= part.memtagGlobalDescriptors->updateAllocSize();
}
@@ -1614,6 +1637,14 @@ static void removeUnusedSyntheticSections() {
auto *sec = cast<SyntheticSection>(s);
if (sec->getParent() && sec->isNeeded())
return false;
+ // .relr.auth.dyn relocations may be moved to .rela.dyn in
+ // finalizeAddressDependentContent, making .rela.dyn no longer empty.
+ // Conservatively keep .rela.dyn. .relr.auth.dyn can be made empty, but
+ // we would fail to remove it here.
+ if (config->emachine == EM_AARCH64 && config->relrPackDynRelocs)
+ if (auto *relSec = dyn_cast<RelocationBaseSection>(sec))
+ if (relSec == mainPart->relaDyn.get())
+ return false;
unused.insert(sec);
return true;
});
@@ -1926,6 +1957,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
part.relrDyn->mergeRels();
finalizeSynthetic(part.relrDyn.get());
}
+ if (part.relrAuthDyn) {
+ part.relrAuthDyn->mergeRels();
+ finalizeSynthetic(part.relrAuthDyn.get());
+ }
finalizeSynthetic(part.dynSymTab.get());
finalizeSynthetic(part.gnuHashTab.get());