Skip to content

Commit

Permalink
[ELF][ARM] Refine check for when undefined weak needs a Thunk
Browse files Browse the repository at this point in the history
When an undefined weak reference has a PLT entry we must generate a range
extension thunk for any B or BL that can't reach the PLT entry.

This change explicitly looks for whether a PLT entry exists rather than
assuming that weak references never need PLT entries unless Config->Shared
is in operation. This covers the case where we are linking an executable
with dynamic linking, hence a PLT entry will be needed for undefined weak
references. This case comes up in real programs over 32 Mb in size as there
is a B to a weak reference __gmon__start__ in the Arm crti.o for glibc.

Differential Revision: https://reviews.llvm.org/D40248

llvm-svn: 319020
  • Loading branch information
smithp35 committed Nov 27, 2017
1 parent 4b47648 commit 2809926
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 4 deletions.
7 changes: 3 additions & 4 deletions lld/ELF/Arch/ARM.cpp
Expand Up @@ -229,10 +229,9 @@ void ARM::addPltSymbols(InputSectionBase *ISD, uint64_t Off) const {

bool ARM::needsThunk(RelExpr Expr, RelType Type, const InputFile *File,
uint64_t BranchAddr, const Symbol &S) const {
// If S is an undefined weak symbol in an executable we don't need a Thunk.
// In a DSO calls to undefined symbols, including weak ones get PLT entries
// which may need a thunk.
if (S.isUndefWeak() && !Config->Shared)
// 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;
// A state change from ARM to Thumb and vice versa must go through an
// interworking thunk if the relocation type is not R_ARM_CALL or
Expand Down
35 changes: 35 additions & 0 deletions lld/test/ELF/arm-branch-undef-weak-plt-thunk.s
@@ -0,0 +1,35 @@
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-shared.s -o %t
// RUN: ld.lld %t --shared -o %t.so
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2
// RUN: ld.lld %t2 %t.so -o %t3
// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi -start-address=69632 -stop-address=69664 %t3 | FileCheck %s
// REQUIRES: arm

// When we are dynamic linking, undefined weak references have a PLT entry so
// we must create a thunk for the branch to the PLT entry.

.text
.globl bar2
.weak undefined_weak_we_expect_a_plt_entry_for
_start:
.globl _start
.type _start, %function
b undefined_weak_we_expect_a_plt_entry_for
bl bar2
// Create 32 Mb gap between the call to the weak reference and the PLT so that
// the b and bl need a range-extension thunk.
.section .text.1, "ax", %progbits
.space 32 * 1024 * 1024

// CHECK: Disassembly of section .text:
// CHECK-NEXT: _start:
// CHECK-NEXT: 11000: 00 00 00 ea b #0 <__ARMv7ABSLongThunk_undefined_weak_we_expect_a_plt_entry_for>
// CHECK-NEXT: 11004: 02 00 00 eb bl #8 <__ARMv7ABSLongThunk_bar2>
// CHECK: __ARMv7ABSLongThunk_undefined_weak_we_expect_a_plt_entry_for:
// CHECK-NEXT: 11008: 34 c0 01 e3 movw r12, #4148
// CHECK-NEXT: 1100c: 01 c2 40 e3 movt r12, #513
// CHECK-NEXT: 11010: 1c ff 2f e1 bx r12
// CHECK: __ARMv7ABSLongThunk_bar2:
// CHECK-NEXT: 11014: 44 c0 01 e3 movw r12, #4164
// CHECK-NEXT: 11018: 01 c2 40 e3 movt r12, #513
// CHECK-NEXT: 1101c: 1c ff 2f e1 bx r12

0 comments on commit 2809926

Please sign in to comment.