[ELF] Retain .rela.dyn for PPC64 PI long-branch thunks (#212078)
PPC64PILongBranchThunk adds a relative relocation, which runs after removeUnusedSyntheticSections. With no other dynamic relocation .rela.dyn is incorrectly removed. Extract the .rela.auth.dyn condition (#96496, #195649) to `mayGrowLate` and add a .branch_lt check.
This commit is contained in:
parent
6dfd733723
commit
bd9aa3ca57
4 changed files with 46 additions and 21 deletions
|
|
@ -770,6 +770,10 @@ struct Ctx : CommonLinkerContext {
|
|||
unsigned scriptSymOrderCounter = 1;
|
||||
llvm::DenseMap<const Symbol *, unsigned> scriptSymOrder;
|
||||
|
||||
// Used to assert removeUnusedSyntheticSections-removed sections cannot become
|
||||
// needed again.
|
||||
SmallVector<SyntheticSection *, 0> removedSyntheticSections;
|
||||
|
||||
// The set of TOC entries (.toc + addend) for which we should not apply
|
||||
// toc-indirect to toc-relative relaxation. const Symbol * refers to the
|
||||
// STT_SECTION symbol associated to the .toc input section.
|
||||
|
|
|
|||
|
|
@ -1747,6 +1747,17 @@ template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() {
|
|||
is->trim();
|
||||
}
|
||||
|
||||
// Sections that finalizeAddressDependentContent may add to.
|
||||
static bool mayGrowLate(Ctx &ctx, SyntheticSection *sec) {
|
||||
if (sec != ctx.in.relaDyn.get())
|
||||
return false;
|
||||
// Relocations may move here from .relr.auth.dyn.
|
||||
if (ctx.in.relrAuthDyn && ctx.in.relrAuthDyn->isNeeded())
|
||||
return true;
|
||||
// PPC64PILongBranchThunk adds a relative relocation for its .branch_lt entry.
|
||||
return ctx.in.ppc64LongBranchTarget && ctx.arg.picThunk;
|
||||
}
|
||||
|
||||
// In order to allow users to manipulate linker-synthesized sections,
|
||||
// we had to add synthetic sections to the input section list early,
|
||||
// even before we make decisions whether they are needed. This allows
|
||||
|
|
@ -1758,7 +1769,8 @@ template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() {
|
|||
//
|
||||
// To deal with the above problem, this function is called after
|
||||
// scanRelocations is called to remove synthetic sections that turn
|
||||
// out to be empty.
|
||||
// out to be empty. It runs before finalizeAddressDependentContent, which may
|
||||
// add to a section mayGrowLate reports.
|
||||
static void removeUnusedSyntheticSections(Ctx &ctx) {
|
||||
// All input synthetic sections that can be empty are placed after
|
||||
// all regular ones. Reverse iterate to find the first synthetic section
|
||||
|
|
@ -1773,17 +1785,13 @@ static void removeUnusedSyntheticSections(Ctx &ctx) {
|
|||
auto end =
|
||||
std::remove_if(start, ctx.inputSections.end(), [&](InputSectionBase *s) {
|
||||
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 (ctx.arg.emachine == EM_AARCH64 && ctx.arg.relrPackDynRelocs &&
|
||||
sec == ctx.in.relaDyn.get() && ctx.in.relrAuthDyn &&
|
||||
ctx.in.relrAuthDyn->isNeeded())
|
||||
if ((sec->getParent() && sec->isNeeded()) || mayGrowLate(ctx, sec))
|
||||
return false;
|
||||
unused.insert(sec);
|
||||
// LinkerScript::discard clears the parent. Losing later additions to
|
||||
// such a section is intended.
|
||||
if (sec->getParent())
|
||||
ctx.removedSyntheticSections.push_back(sec);
|
||||
return true;
|
||||
});
|
||||
ctx.inputSections.erase(end, ctx.inputSections.end());
|
||||
|
|
@ -2117,6 +2125,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
|||
// values. They also might change after adding the thunks.
|
||||
finalizeAddressDependentContent();
|
||||
|
||||
// A section dropped as unneeded must have stayed unneeded.
|
||||
assert(llvm::none_of(ctx.removedSyntheticSections,
|
||||
[](SyntheticSection *sec) { return sec->isNeeded(); }));
|
||||
|
||||
// All information needed for OutputSection part of Map file is available.
|
||||
if (errCount(ctx))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -11,11 +11,20 @@
|
|||
|
||||
# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
|
||||
# RUN: ld.lld -pie -T %t.lds %t.o -o %t
|
||||
# RUN: llvm-readelf -r %t | FileCheck --check-prefix=SEC %s
|
||||
# RUN: llvm-readelf -r %t | FileCheck --check-prefix=SEC-PI -DOFF0=a0b0 -DOFF1=a0b8 %s
|
||||
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
|
||||
|
||||
## --pic-veneer selects PI long-branch thunks in a non-PIC link.
|
||||
# RUN: ld.lld --pic-veneer -T %t.lds %t.o -o %t
|
||||
# RUN: llvm-readelf -r %t | FileCheck --check-prefix=SEC-PI -DOFF0=a010 -DOFF1=a018 %s
|
||||
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
|
||||
|
||||
# SEC: There are no relocations in this file.
|
||||
|
||||
# SEC-PI: Relocation section '.rela.dyn' {{.*}} contains 2 entries:
|
||||
# SEC-PI: {{0+}}[[OFF0]] {{[0-9a-f]+}} R_PPC64_RELATIVE a004
|
||||
# SEC-PI-NEXT: {{0+}}[[OFF1]] {{[0-9a-f]+}} R_PPC64_RELATIVE a010
|
||||
|
||||
# CHECK-LABEL: <_start>:
|
||||
# CHECK-NEXT: 2000: bt 2, 0x2040
|
||||
# CHECK-NEXT: bt+ 2, 0x2040
|
||||
|
|
|
|||
|
|
@ -28,16 +28,16 @@
|
|||
# RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYMBOL-GLOBAL
|
||||
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
|
||||
|
||||
# SYMBOL: 2: 0000000010010000 0 NOTYPE LOCAL DEFAULT 5 callee1_stother0_default
|
||||
# SYMBOL-NEXT: 3: 0000000010010004 0 NOTYPE LOCAL DEFAULT [<other: 0x20>] 5 caller1
|
||||
# SYMBOL-NEXT: 4: 0000000010020000 0 NOTYPE LOCAL DEFAULT 6 func_local
|
||||
# SYMBOL-NEXT: 5: 0000000010020004 0 NOTYPE LOCAL DEFAULT [<other: 0x20>] 6 callee2_stother1_default
|
||||
# SYMBOL-NEXT: 6: 000000001002000c 0 NOTYPE LOCAL DEFAULT [<other: 0x20>] 6 caller2
|
||||
# SYMBOL-NEXT: 7: 0000000010030000 0 NOTYPE LOCAL DEFAULT [<other: 0x20>] 7 caller3
|
||||
# SYMBOL-NEXT: 8: 0000000010040000 0 NOTYPE LOCAL DEFAULT [<other: 0x20>] 8 caller4
|
||||
# SYMBOL-NEXT: 9: 0000000010040008 0 NOTYPE LOCAL DEFAULT 9 func_extern
|
||||
# SYMBOL-NEXT: 10: 000000001004000c 0 NOTYPE LOCAL HIDDEN 9 callee3_stother0_hidden
|
||||
# SYMBOL-NEXT: 11: 0000000010040010 0 NOTYPE LOCAL HIDDEN [<other: 0x22>] 9 callee4_stother1_hidden
|
||||
# SYMBOL: 2: 0000000010010000 0 NOTYPE LOCAL DEFAULT 6 callee1_stother0_default
|
||||
# SYMBOL-NEXT: 3: 0000000010010004 0 NOTYPE LOCAL DEFAULT [<other: 0x20>] 6 caller1
|
||||
# SYMBOL-NEXT: 4: 0000000010020000 0 NOTYPE LOCAL DEFAULT 7 func_local
|
||||
# SYMBOL-NEXT: 5: 0000000010020004 0 NOTYPE LOCAL DEFAULT [<other: 0x20>] 7 callee2_stother1_default
|
||||
# SYMBOL-NEXT: 6: 000000001002000c 0 NOTYPE LOCAL DEFAULT [<other: 0x20>] 7 caller2
|
||||
# SYMBOL-NEXT: 7: 0000000010030000 0 NOTYPE LOCAL DEFAULT [<other: 0x20>] 8 caller3
|
||||
# SYMBOL-NEXT: 8: 0000000010040000 0 NOTYPE LOCAL DEFAULT [<other: 0x20>] 9 caller4
|
||||
# SYMBOL-NEXT: 9: 0000000010040008 0 NOTYPE LOCAL DEFAULT 10 func_extern
|
||||
# SYMBOL-NEXT: 10: 000000001004000c 0 NOTYPE LOCAL HIDDEN 10 callee3_stother0_hidden
|
||||
# SYMBOL-NEXT: 11: 0000000010040010 0 NOTYPE LOCAL HIDDEN [<other: 0x22>] 10 callee4_stother1_hidden
|
||||
|
||||
# SYMBOL-GLOBAL: 2: 0000000010010004 0 NOTYPE LOCAL DEFAULT [<other: 0x20>] 1 caller1
|
||||
# SYMBOL-GLOBAL-NEXT: 3: 0000000010020000 0 NOTYPE LOCAL DEFAULT 2 func_local
|
||||
|
|
|
|||
Loading…
Reference in a new issue