From 53b59fdc52bf6c8bf15ce7c146d2cebe338f34a7 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 15 Feb 2022 12:57:27 -0800 Subject: [PATCH] [ELF][PPC64] Fix assertion failure for branches to hidden undefined weak for -no-pie Reported by Stefan Pintilie in D119773. For a branch to a hidden undefined weak symbol, there is an `assert(sym->getVA());` failure in PPC64LongBranchTargetSection::writeTo for a -no-pie link. The root cause is that we unnecessarily create the thunk for the -no-pie link. Fix this by changing the condition to just `s.isUndefined()`. See the inline comment. Rename ppc64-weak-undef-call.s to ppc64-undefined-weak.s to be consistent with other architectures. Reviewed By: sfertile, stefanp Differential Revision: https://reviews.llvm.org/D119787 --- lld/ELF/Arch/PPC64.cpp | 7 ++--- lld/test/ELF/ppc64-undefined-weak.s | 40 +++++++++++++++++++++++++++++ lld/test/ELF/ppc64-undefined.s | 11 ++++++++ lld/test/ELF/ppc64-weak-undef-call-shared.s | 21 --------------- lld/test/ELF/ppc64-weak-undef-call.s | 29 --------------------- 5 files changed, 55 insertions(+), 53 deletions(-) create mode 100644 lld/test/ELF/ppc64-undefined-weak.s create mode 100644 lld/test/ELF/ppc64-undefined.s delete mode 100644 lld/test/ELF/ppc64-weak-undef-call-shared.s delete mode 100644 lld/test/ELF/ppc64-weak-undef-call.s diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index 38fbc72..16893bf 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -1380,9 +1380,10 @@ bool PPC64::needsThunk(RelExpr expr, RelType type, const InputFile *file, if (type == R_PPC64_REL24_NOTOC && (s.stOther >> 5) > 1) return true; - // If a symbol is a weak undefined and we are compiling an executable - // it doesn't need a range-extending thunk since it can't be called. - if (s.isUndefWeak() && !config->shared) + // An undefined weak symbol not in a PLT does not need a thunk. If it is + // hidden, its binding has been converted to local, so we just check + // isUndefined() here. A undefined non-weak symbol has been errored. + if (s.isUndefined()) return false; // If the offset exceeds the range of the branch type then it will need diff --git a/lld/test/ELF/ppc64-undefined-weak.s b/lld/test/ELF/ppc64-undefined-weak.s new file mode 100644 index 0000000..7b1be5e --- /dev/null +++ b/lld/test/ELF/ppc64-undefined-weak.s @@ -0,0 +1,40 @@ +# REQUIRES: ppc + +# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PDE +# RUN: ld.lld -pie %t.o -o %t +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PIC +# RUN: ld.lld -shared %t.o -o %t.so +# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s --check-prefix=PIC + +# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PDE + +## Branches to an undefined weak symbol need a thunk iff a dynamic relocation is +## produced. undefweak2 is hidden and does not need a dynamic relocation, so we +## suppress the thunk. undefweak1 needs a thunk iff -pie or -shared. + +# PDE-LABEL: <_start>: +# PDE-NEXT: bl {{.*}} <_start> +# PDE-NEXT: nop +# PDE-NEXT: bl {{.*}} <_start+0x8> +# PDE-NEXT: nop + +# PIC-LABEL: <_start>: +# PIC-NEXT: bl {{.*}} <__plt_undefweak1> +# PIC-NEXT: ld 2, 24(1) +# PIC-NEXT: bl {{.*}} <_start+0x8> +# PIC-NEXT: nop + +.text +.global _start +_start: + bl undefweak1 + nop + bl undefweak2 + nop + +.weak undefweak1, undefweak2 +.hidden undefweak2 diff --git a/lld/test/ELF/ppc64-undefined.s b/lld/test/ELF/ppc64-undefined.s new file mode 100644 index 0000000..c9c2a75 --- /dev/null +++ b/lld/test/ELF/ppc64-undefined.s @@ -0,0 +1,11 @@ +# REQUIRES: ppc + +# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o +# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR + +# ERR: error: undefined symbol: undef + +.global _start +_start: + bl undef + nop diff --git a/lld/test/ELF/ppc64-weak-undef-call-shared.s b/lld/test/ELF/ppc64-weak-undef-call-shared.s deleted file mode 100644 index 244f72f..0000000 --- a/lld/test/ELF/ppc64-weak-undef-call-shared.s +++ /dev/null @@ -1,21 +0,0 @@ -# REQUIRES: ppc - -# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o -# RUN: ld.lld -shared %t.o -o %t.so -# RUN: llvm-readobj --symbols -r --dyn-syms %t.so | FileCheck %s - -# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o -# RUN: ld.lld -shared %t.o -o %t.so -# RUN: llvm-readobj --symbols -r --dyn-syms %t.so | FileCheck %s - -.section ".toc","aw" -.quad weakfunc -// CHECK-NOT: R_PPC64_RELATIVE - -.text -.Lfoo: - bl weakfunc - nop -// CHECK-NOT: R_PPC64_REL24 - -.weak weakfunc diff --git a/lld/test/ELF/ppc64-weak-undef-call.s b/lld/test/ELF/ppc64-weak-undef-call.s deleted file mode 100644 index 1f68693..0000000 --- a/lld/test/ELF/ppc64-weak-undef-call.s +++ /dev/null @@ -1,29 +0,0 @@ -# REQUIRES: ppc - -# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t -# RUN: ld.lld %t -o %t2 -# RUN: llvm-objdump -d --no-show-raw-insn %t2 | FileCheck %s - -# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t -# RUN: ld.lld %t -o %t2 -# RUN: llvm-objdump -d --no-show-raw-insn %t2 | FileCheck %s - -# CHECK: Disassembly of section .text: -# CHECK-EMPTY: - -.text -.global _start -_start: - bl weakfunc - nop - blr - -.weak weakfunc - -# It does not really matter how we fixup the bl, if at all, because it needs to -# be unreachable. But, we should link successfully. We should not, however, -# generate a .plt entry (this would be wasted space). For now, we do nothing -# (leaving the zero relative offset present in the input). -# CHECK: 10010158: bl 0x10010158 -# CHECK: 1001015c: nop -# CHECK: 10010160: blr -- 2.7.4