diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp --- a/lld/ELF/Arch/ARM.cpp +++ b/lld/ELF/Arch/ARM.cpp @@ -90,6 +90,7 @@ case R_ARM_THM_MOVW_ABS_NC: case R_ARM_THM_MOVT_ABS: return R_ABS; + case R_ARM_THM_JUMP8: case R_ARM_THM_JUMP11: return R_PC; case R_ARM_CALL: @@ -520,7 +521,13 @@ checkInt(loc, val, 26, rel); write32le(loc, (read32le(loc) & ~0x00ffffff) | ((val >> 2) & 0x00ffffff)); break; + case R_ARM_THM_JUMP8: + // We do a 9 bit check because val is right-shifted by 1 bit. + checkInt(loc, val, 9, rel); + write16le(loc, (read32le(loc) & 0xff00) | ((val >> 1) & 0x00ff)); + break; case R_ARM_THM_JUMP11: + // We do a 12 bit check because val is right-shifted by 1 bit. checkInt(loc, val, 12, rel); write16le(loc, (read32le(loc) & 0xf800) | ((val >> 1) & 0x07ff)); break; @@ -748,6 +755,8 @@ case R_ARM_PC24: case R_ARM_PLT32: return SignExtend64<26>(read32le(buf) << 2); + case R_ARM_THM_JUMP8: + return SignExtend64<9>(read16le(buf) << 1); case R_ARM_THM_JUMP11: return SignExtend64<12>(read16le(buf) << 1); case R_ARM_THM_JUMP19: { diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -495,6 +495,7 @@ switch (type) { // Unresolved branch relocations to weak references resolve to next // instruction, this will be either 2 or 4 bytes on from P. + case R_ARM_THM_JUMP8: case R_ARM_THM_JUMP11: return p + 2 + a; case R_ARM_CALL: diff --git a/lld/test/ELF/Inputs/arm-thumb-narrow-branch.o b/lld/test/ELF/Inputs/arm-thumb-narrow-branch.o index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@ %t.script // RUN: ld.lld --script %t.script %t %S/Inputs/arm-thumb-narrow-branch.o -o %t2 // RUN: llvm-objdump -d %t2 | FileCheck %s -// Test the R_ARM_PC11 relocation which is used with the narrow encoding of B.N -// the source of these relocations is a binary file arm-thumb-narrow-branch.o +// Test the R_ARM_THM_JUMP11 and R_ARM_THM_JUMP8 relocations which are used +// with the narrow encoding of B.N and BEQ.N. +// +// The source of these relocations is a binary file arm-thumb-narrow-branch.o // which has been assembled with the GNU assembler as llvm-mc doesn't emit it // as the range of +-2048 bytes is too small to be practically useful for out // of section branches. @@ -20,7 +22,11 @@ .type callee_low_far,%function callee_low_far = 0x809 - .section .R_ARM_PC11_1,"ax",%progbits +.global callee_low_near +.type callee_low_near,%function +callee_low_near = 0xfff + + .section .callee_low,"ax",%progbits .thumb .balign 0x1000 .type callee_low,%function @@ -37,7 +43,7 @@ bl callers bx lr - .section .R_ARM_PC11_2,"ax",%progbits + .section .callee_high,"ax",%progbits .thumb .align 2 .type callee_high,%function @@ -45,11 +51,15 @@ callee_high: bx lr +.global callee_high_near +.type callee_high_near,%function +callee_high_near = 0x10ff + .global callee_high_far .type callee_high_far,%function callee_high_far = 0x180d -// CHECK: Disassembly of section .R_ARM_PC11_1: +// CHECK: Disassembly of section .callee_low: // CHECK-EMPTY: // CHECK-NEXT: : // CHECK-NEXT: 1000: 70 47 bx lr @@ -60,19 +70,25 @@ /// callee_low_far = 0x809 // CHECK-NEXT: 1004: 00 e4 b 0x808 // CHECK-NEXT: 1006: fb e7 b 0x1000 -// CHECK-NEXT: 1008: 02 e0 b 0x1010 +// CHECK-NEXT: 1008: 06 e0 b 0x1018 /// callee_high_far = 0x180d // CHECK-NEXT: 100a: ff e3 b 0x180c -// CHECK-NEXT: 100c: 70 47 bx lr -// CHECK-NEXT: 100e: 00 bf nop +/// callee_low_near = 0xfff +// CHECK-NEXT: 100c: f7 d0 beq 0xffe +// CHECK-NEXT: 100e: f7 d0 beq 0x1000 +// CHECK-NEXT: 1010: 02 d0 beq 0x1018 +/// callee_high_near = 0x10ff +// CHECK-NEXT: 1012: 74 d0 beq 0x10fe +// CHECK-NEXT: 1014: 70 47 bx lr +// CHECK-NEXT: 1016: c0 46 mov r8, r8 // CHECK-EMPTY: -// CHECK-NEXT: Disassembly of section .R_ARM_PC11_2: +// CHECK-NEXT: Disassembly of section .callee_high: // CHECK-EMPTY: // CHECK-NEXT: : -// CHECK-NEXT: 1010: 70 47 bx lr +// CHECK-NEXT: 1018: 70 47 bx lr // CHECK-EMPTY: // CHECK-NEXT: Disassembly of section .text: // CHECK-EMPTY: // CHECK-NEXT: <_start>: -// CHECK-NEXT: 1014: ff f7 f6 ff bl 0x1004 -// CHECK-NEXT: 1018: 70 47 bx lr +// CHECK-NEXT: 101c: ff f7 f2 ff bl 0x1004 +// CHECK-NEXT: 1020: 70 47 bx lr diff --git a/lld/test/ELF/arm-thumb-undefined-weak-narrow.test b/lld/test/ELF/arm-thumb-undefined-weak-narrow.test --- a/lld/test/ELF/arm-thumb-undefined-weak-narrow.test +++ b/lld/test/ELF/arm-thumb-undefined-weak-narrow.test @@ -7,11 +7,12 @@ # CHECK-EMPTY: # CHECK-NEXT: <_start>: # CHECK-NEXT: ff e7 b 0x200b6 <_start+0x2> @ imm = #-2 +# CHECK-NEXT: fe d0 beq 0x200b6 <_start+0x2> @ imm = #-4 -# Test the R_ARM_THM_JUMP11 relocation (102) to an undefined weak reference -# It should resolve to the next instruction, which is an offset of -2 which -# when added to the Thumb PC-bias of 4 is +2. We can't use llvm-mc to construct -# the object as it relaxes b.n to b.w (R_ARM_JUMP24). +# Test the R_ARM_THM_JUMP11 (102) and R_ARM_THM_JUMP8 (103) relocations to an +# undefined weak reference. It should resolve to the next instruction, which +# is an offset of -2 which when added to the Thumb PC-bias of 4 is +2. We can't +# use llvm-mc to construct the object as it relaxes b.n to b.w (R_ARM_JUMP24). !ELF FileHeader: @@ -23,7 +24,7 @@ - Type: SHT_PROGBITS Name: .text Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - Content: "fee7" + Content: "fee7fed0" - Type: SHT_REL Name: .rel.text Link: .symtab @@ -31,6 +32,8 @@ Relocations: - Symbol: undefined_weak Type: R_ARM_THM_JUMP11 + - Symbol: undefined_weak + Type: R_ARM_THM_JUMP8 Symbols: - Type: STT_NOTYPE