Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[LLD][ELF][ARM] Do not insert interworking thunks for non STT_FUNC sy…
…mbols ELF for the ARM architecture requires linkers to provide interworking for symbols that are of type STT_FUNC. Interworking for other symbols must be encoded directly in the object file. LLD was always providing interworking, regardless of the symbol type, this breaks some programs that have branches from Thumb state targeting STT_NOTYPE symbols that have bit 0 clear, but they are in fact internal labels in a Thumb function. LLD treats these symbols as ARM and inserts a transition to Arm. This fixes the problem for in range branches, R_ARM_JUMP24, R_ARM_THM_JUMP24 and R_ARM_THM_JUMP19. This is expected to be the vast majority of problem cases as branching to an internal label close to the function. There is at least one follow up patch required. - R_ARM_CALL and R_ARM_THM_CALL may do interworking via BL/BLX substitution. In theory range-extension thunks can be altered to not change state when the symbol type is not STT_FUNC. I will need to check with ld.bfd to see if this is the case in practice. Fixes (part of) ClangBuiltLinux/linux#773 Differential Revision: https://reviews.llvm.org/D73474 (cherry picked from commit 4f38ab2)
- Loading branch information
Showing
4 changed files
with
130 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// REQUIRES: arm | ||
// RUN: llvm-mc --triple=armv7a-linux-gnueabihf -arm-add-build-attributes -filetype=obj -o %t.o %s | ||
// RUN: ld.lld %t.o -o %t | ||
// RUN: llvm-objdump -triple armv7a-none-linux-gnueabi -d --no-show-raw-insn %t | ||
|
||
/// Non-preemptible ifuncs are called via a PLT entry which is always Arm | ||
/// state, expect the ARM callers to go direct to the PLT entry, Thumb | ||
/// branches are indirected via state change thunks, the bl is changed to blx. | ||
|
||
.syntax unified | ||
.text | ||
.balign 0x1000 | ||
.type foo STT_GNU_IFUNC | ||
.globl foo | ||
foo: | ||
bx lr | ||
|
||
.section .text.1, "ax", %progbits | ||
.arm | ||
.global _start | ||
_start: | ||
b foo | ||
bl foo | ||
|
||
.section .text.2, "ax", %progbits | ||
.thumb | ||
.global thumb_caller | ||
thumb_caller: | ||
b foo | ||
b.w foo | ||
bl foo | ||
|
||
// CHECK: 00012004 _start: | ||
// CHECK-NEXT: b #36 | ||
// CHECK-NEXT: bl #32 | ||
|
||
// CHECK: 0001200c thumb_caller: | ||
// CHECK-NEXT: b.w #8 | ||
// CHECK-NEXT: b.w #4 | ||
// CHECK-NEXT: blx #24 | ||
|
||
// CHECK: 00012018 __Thumbv7ABSLongThunk_foo: | ||
// CHECK-NEXT: movw r12, #8240 | ||
// CHECK-NEXT: movt r12, #1 | ||
// CHECK-NEXT: bx r12 | ||
|
||
// CHECK: Disassembly of section .iplt: | ||
|
||
// CHECK: 00012030 $a: | ||
// CHECK-NEXT: add r12, pc, #0, #12 | ||
// CHECK-NEXT: add r12, r12, #4096 | ||
// CHECK-NEXT: ldr pc, [r12, #8]! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// REQUIRES: arm | ||
// RUN: llvm-mc --triple=armv7a-linux-gnueabihf -arm-add-build-attributes -filetype=obj -o %t.o %s | ||
// RUN: ld.lld %t.o -o %t | ||
// RUN: llvm-objdump --no-show-raw-insn -d %t | FileCheck %s | ||
|
||
.syntax unified | ||
.section .arm_target, "ax", %progbits | ||
.balign 0x1000 | ||
.arm | ||
arm_func_with_notype: | ||
.type arm_func_with_explicit_notype, %notype | ||
arm_func_with_explicit_notype: | ||
bx lr | ||
|
||
.section .thumb_target, "ax", %progbits | ||
.balign 4 | ||
.thumb | ||
thumb_func_with_notype: | ||
.type thumb_func_with_explicit_notype, %notype | ||
thumb_func_with_explicit_notype: | ||
bx lr | ||
|
||
/// All the symbols that are targets of the branch relocations do not have | ||
/// type STT_FUNC. LLD should not insert interworking thunks as non STT_FUNC | ||
/// symbols have no state information, the ABI assumes the user has manually | ||
/// done the interworking. | ||
.section .arm_caller, "ax", %progbits | ||
.balign 4 | ||
.arm | ||
.global _start | ||
_start: | ||
b .arm_target | ||
b arm_func_with_notype | ||
b arm_func_with_explicit_notype | ||
b .thumb_target | ||
b thumb_func_with_notype | ||
b thumb_func_with_explicit_notype | ||
|
||
.section .thumb_caller, "ax", %progbits | ||
.thumb | ||
.balign 4 | ||
b.w .arm_target | ||
b.w arm_func_with_notype | ||
b.w arm_func_with_explicit_notype | ||
b.w .thumb_target | ||
b.w thumb_func_with_notype | ||
b.w thumb_func_with_explicit_notype | ||
beq.w .arm_target | ||
beq.w arm_func_with_notype | ||
beq.w arm_func_with_explicit_notype | ||
beq.w .thumb_target | ||
beq.w thumb_func_with_notype | ||
beq.w thumb_func_with_explicit_notype | ||
|
||
// CHECK: 00012008 _start: | ||
// CHECK-NEXT: 12008: b #-16 | ||
// CHECK-NEXT: 1200c: b #-20 | ||
// CHECK-NEXT: 12010: b #-24 | ||
// CHECK-NEXT: 12014: b #-24 | ||
// CHECK-NEXT: 12018: b #-28 | ||
// CHECK-NEXT: 1201c: b #-32 | ||
// CHECK: 12020: b.w #-36 | ||
// CHECK-NEXT: 12024: b.w #-40 | ||
// CHECK-NEXT: 12028: b.w #-44 | ||
// CHECK-NEXT: 1202c: b.w #-44 | ||
// CHECK-NEXT: 12030: b.w #-48 | ||
// CHECK-NEXT: 12034: b.w #-52 | ||
// CHECK-NEXT: 12038: beq.w #-60 | ||
// CHECK-NEXT: 1203c: beq.w #-64 | ||
// CHECK-NEXT: 12040: beq.w #-68 | ||
// CHECK-NEXT: 12044: beq.w #-68 | ||
// CHECK-NEXT: 12048: beq.w #-72 | ||
// CHECK-NEXT: 1204c: beq.w #-76 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters