Index: lld/ELF/Arch/ARM.cpp =================================================================== --- lld/ELF/Arch/ARM.cpp +++ lld/ELF/Arch/ARM.cpp @@ -263,7 +263,8 @@ } bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file, - uint64_t branchAddr, const Symbol &s, int64_t /*a*/) const { + 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()) @@ -276,8 +277,8 @@ 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) == 1)) return true; LLVM_FALLTHROUGH; case R_ARM_CALL: { @@ -287,8 +288,8 @@ 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: { Index: lld/test/ELF/arm-thumb-interwork-notfunc.s =================================================================== --- /dev/null +++ lld/test/ELF/arm-thumb-interwork-notfunc.s @@ -0,0 +1,57 @@ +// 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 4 +.arm +arm_func_with_notype: + bx lr + +.section .thumb_target, "ax", %progbits +.balign 4 +.thumb +thumb_func_with_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 .thumb_target + b thumb_func_with_notype + + .section .thumb_caller, "ax", %progbits + .thumb + .balign 4 + b.w .arm_target + b.w arm_func_with_notype + b.w .thumb_target + b.w thumb_func_with_notype + beq.w .arm_target + beq.w arm_func_with_notype + beq.w .thumb_target + beq.w thumb_func_with_notype + +// CHECK: 000110bc _start: +// CHECK-NEXT: 110bc: b #-16 +// CHECK-NEXT: 110c0: b #-20 +// CHECK-NEXT: 110c4: b #-20 +// CHECK-NEXT: 110c8: b #-24 +// CHECK: 110cc: b.w #-28 +// CHECK-NEXT: 110d0: b.w #-32 +// CHECK-NEXT: 110d4: b.w #-32 +// CHECK-NEXT: 110d8: b.w #-36 +// CHECK-NEXT: 110dc: beq.w #-44 +// CHECK-NEXT: 110e0: beq.w #-48 +// CHECK-NEXT: 110e4: beq.w #-48 +// CHECK-NEXT: 110e8: beq.w #-52 Index: lld/test/ELF/arm-thunk-edgecase.s =================================================================== --- lld/test/ELF/arm-thunk-edgecase.s +++ lld/test/ELF/arm-thunk-edgecase.s @@ -18,6 +18,7 @@ .arm .section .text_armfunc, "ax", %progbits .globl armfunc +.type armfunc, %function armfunc: b thumbfunc