case R_ARM_PLT32:
case R_ARM_JUMP24:
// Source is ARM, all PLT entries are ARM so no interworking required.
- // Otherwise we need to interwork if Symbol has bit 0 set (Thumb).
- if (expr == R_PC && ((s.getVA() & 1) == 1))
+ // Otherwise we need to interwork if STT_FUNC Symbol has bit 0 set (Thumb).
+ if (s.isFunc() && expr == R_PC && (s.getVA() & 1))
return true;
LLVM_FALLTHROUGH;
case R_ARM_CALL: {
case R_ARM_THM_JUMP19:
case R_ARM_THM_JUMP24:
// Source is Thumb, all PLT entries are ARM so interworking is required.
- // Otherwise we need to interwork if Symbol has bit 0 clear (ARM).
- if (expr == R_PLT_PC || ((s.getVA() & 1) == 0))
+ // Otherwise we need to interwork if STT_FUNC Symbol has bit 0 clear (ARM).
+ if (expr == R_PLT_PC || (s.isFunc() && (s.getVA() & 1) == 0))
return true;
LLVM_FALLTHROUGH;
case R_ARM_THM_CALL: {
--- /dev/null
+// 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]!
--- /dev/null
+// 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