Skip to content

Commit 588b95a

Browse files
MaskRaytstellar
authored andcommitted
[ELF][AArch64] Fix unneeded thunk for branches to hidden undefined weak
Similar to D119787 for PPC64. A hidden undefined weak may change its binding to local before some `isUndefinedWeak` code, so some `isUndefinedWeak` code needs to be changed to `isUndefined`. The undefined non-weak case has been errored, so just using `isUndefined` is fine. The Linux kernel recently has a usage that a branch from 0xffff800008491ee0 references a hidden undefined weak symbol `vfio_group_set_kvm`. It relies on the behavior that a branch to undefined weak resolving to the next instruction, otherwise it'd see spurious relocation out of range errors. Fixes ClangBuiltLinux/linux#1624 Differential Revision: https://reviews.llvm.org/D123750 (cherry picked from commit 02eab52)
1 parent e70d79f commit 588b95a

File tree

3 files changed

+16
-4
lines changed

3 files changed

+16
-4
lines changed

lld/ELF/Arch/AArch64.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,11 @@ void AArch64::writePlt(uint8_t *buf, const Symbol &sym,
256256
bool AArch64::needsThunk(RelExpr expr, RelType type, const InputFile *file,
257257
uint64_t branchAddr, const Symbol &s,
258258
int64_t a) const {
259-
// If s is an undefined weak symbol and does not have a PLT entry then it
260-
// will be resolved as a branch to the next instruction.
261-
if (s.isUndefWeak() && !s.isInPlt())
259+
// If s is an undefined weak symbol and does not have a PLT entry then it will
260+
// be resolved as a branch to the next instruction. If it is hidden, its
261+
// binding has been converted to local, so we just check isUndefined() here. A
262+
// undefined non-weak symbol will have been errored.
263+
if (s.isUndefined() && !s.isInPlt())
262264
return false;
263265
// ELF for the ARM 64-bit architecture, section Call and Jump relocations
264266
// only permits range extension thunks for R_AARCH64_CALL26 and

lld/ELF/InputSection.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,11 +733,13 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
733733
if (expr == R_ARM_PCA)
734734
// Some PC relative ARM (Thumb) relocations align down the place.
735735
p = p & 0xfffffffc;
736-
if (sym.isUndefWeak()) {
736+
if (sym.isUndefined()) {
737737
// On ARM and AArch64 a branch to an undefined weak resolves to the next
738738
// instruction, otherwise the place. On RISCV, resolve an undefined weak
739739
// to the same instruction to cause an infinite loop (making the user
740740
// aware of the issue) while ensuring no overflow.
741+
// Note: if the symbol is hidden, its binding has been converted to local,
742+
// so we just check isUndefined() here.
741743
if (config->emachine == EM_ARM)
742744
dest = getARMUndefinedRelativeWeakVA(type, a, p);
743745
else if (config->emachine == EM_AARCH64)

lld/test/ELF/aarch64-undefined-weak.s

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
// is not generated.
1111
.weak target
1212

13+
.weak undefweak2
14+
.hidden undefweak2
15+
1316
.text
1417
.global _start
1518
_start:
@@ -36,6 +39,9 @@ _start:
3639
// R_AARCH64_PLT32
3740
.word target@PLT - .
3841

42+
bl_undefweak2:
43+
bl undefweak2
44+
3945
// CHECK: Disassembly of section .text:
4046
// CHECK-EMPTY:
4147
// CHECK-NEXT: 0000000010010120 <_start>:
@@ -51,3 +57,5 @@ _start:
5157
// CHECK-NEXT: 10010144: 00 00 00 00 .word 0x00000000
5258
// CHECK-NEXT: 10010148: 00 00 00 00 .word 0x00000000
5359
// CHECK-NEXT: 1001014c: 00 00 .short 0x0000
60+
// CHECK-LABEL: <bl_undefweak2>:
61+
// CHECK-NEXT: bl {{.*}} <bl_undefweak2+0x4>

0 commit comments

Comments
 (0)