[LLD][ELF][AArch64] Do not use thunk for undefined weak symbol.

In AArch64 a branch to an undefined weak symbol that does not have a PLT
entry should resolve to the next instruction. The thunk generation code
can prevent this from happening as a range extension thunk can be generated
if the branch is sufficiently far away from 0, the value of an undefined
weak symbol.

The fix is taken from the Arm implementation of needsThunk(), we prevent a
thunk from being generated to an undefined weak symbol.

fixes pr44451

Differential Revision: https://reviews.llvm.org/D72267
This commit is contained in:
Peter Smith 2020-01-06 14:16:05 +00:00
parent d364815351
commit 051c4d5b7b
3 changed files with 33 additions and 28 deletions

View File

@ -234,6 +234,10 @@ void AArch64::writePlt(uint8_t *buf, const Symbol &sym,
bool AArch64::needsThunk(RelExpr expr, RelType type, const InputFile *file,
uint64_t branchAddr, const Symbol &s,
int64_t a) const {
// If s is an undefined weak symbol and does not have a PLT entry then it
// will be resolved as a branch to the next instruction.
if (s.isUndefWeak() && !s.isInPlt())
return false;
// ELF for the ARM 64-bit architecture, section Call and Jump relocations
// only permits range extension thunks for R_AARCH64_CALL26 and
// R_AARCH64_JUMP26 relocation types.

View File

@ -1,12 +1,13 @@
// REQUIRES: aarch64
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o
// RUN: ld.lld %t.o -o %t
// RUN: ld.lld --image-base=0x10000000 %t.o -o %t
// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
// Check that the ARM 64-bit ABI rules for undefined weak symbols are applied.
// Branch instructions are resolved to the next instruction. Undefined
// Symbols in relative are resolved to the place so S - P + A = A.
// We place the image-base at 0x10000000 to test that a range extensions thunk
// is not generated.
.weak target
.text
@ -24,27 +25,26 @@ _start:
adr x0, target
// R_AARCH64_ADR_PREL_PG_HI21
adrp x0, target
// R_AARCH64_LD_PREL_LO19
ldr x8, target
// R_AARCH64_PREL32
.word target - .
// R_AARCH64_PREL64
.xword target - .
// R_AARCH64_PREL16
.hword target - .
// R_AARCH64_LD_PREL_LO19
ldr x8, target
// CHECK: Disassembly of section .text:
// CHECK-EMPTY:
// 2162688 = 0x210000
// CHECK: 210120: b #4
// CHECK-NEXT: 210124: bl #4
// CHECK-NEXT: 210128: b.eq #4
// CHECK-NEXT: 21012c: cbz x1, #4
// CHECK-NEXT: 210130: adr x0, #0
// CHECK-NEXT: 210134: adrp x0, #0
// CHECK: 210138: 00 00 00 00 .word 0x00000000
// CHECK-NEXT: 21013c: 00 00 00 00 .word 0x00000000
// CHECK-NEXT: 210140: 00 00 00 00 .word 0x00000000
// CHECK-NEXT: 210144: 00 00 .short 0x0000
// CHECK: $x.2:
// CHECK-NEXT: 210146: ldr x8, #0
// CHECK-NEXT: 0000000010010120 _start:
// CHECK-NEXT: 10010120: b #4
// CHECK-NEXT: 10010124: bl #4
// CHECK-NEXT: 10010128: b.eq #4
// CHECK-NEXT: 1001012c: cbz x1, #4
// CHECK-NEXT: 10010130: adr x0, #0
// CHECK-NEXT: 10010134: adrp x0, #0
// CHECK-NEXT: 10010138: ldr x8, #0
// CHECK: 1001013c: 00 00 00 00 .word 0x00000000
// CHECK-NEXT: 10010140: 00 00 00 00 .word 0x00000000
// CHECK-NEXT: 10010144: 00 00 00 00 .word 0x00000000
// CHECK-NEXT: 10010148: 00 00 .short 0x0000

View File

@ -1,11 +1,13 @@
// REQUIRES: arm
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
// RUN: ld.lld %t -o %t2
// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t2 | FileCheck %s
// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
// RUN: ld.lld --image-base=0x10000000 %t -o %t2
// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi --no-show-raw-insn -d %t2 | FileCheck %s
// Check that the ARM ABI rules for undefined weak symbols are applied.
// Branch instructions are resolved to the next instruction. Undefined
// Symbols in relative are resolved to the place so S - P + A = A.
// We place the image-base at 0x10000000 to test that a range extensions thunk
// is not generated.
.syntax unified
@ -29,11 +31,10 @@ _start:
// CHECK: Disassembly of section .text:
// CHECK-EMPTY:
// CHECK: 110b4: {{.*}} b #-4 <_start+0x4>
// CHECK-NEXT: 110b8: {{.*}} bl #-4 <_start+0x8>
// blx is transformed into bl so we don't change state
// CHECK-NEXT: 110bc: {{.*}} bl #-4 <_start+0xc>
// CHECK-NEXT: 110c0: {{.*}} movt r0, #0
// CHECK-NEXT: 110c4: {{.*}} movw r0, #0
// CHECK: 110c8: {{.*}} .word 0x00000000
// CHECK-NEXT: 100010b4 _start:
// CHECK-NEXT: 100010b4: b #-4
// CHECK-NEXT: 100010b8: bl #-4
// CHECK-NEXT: 100010bc: bl #-4
// CHECK-NEXT: 100010c0: movt r0, #0
// CHECK-NEXT: 100010c4: movw r0, #0
// CHECK: 100010c8: 00 00 00 00 .word 0x00000000