Index: ELF/Arch/AArch64.cpp =================================================================== --- ELF/Arch/AArch64.cpp +++ ELF/Arch/AArch64.cpp @@ -232,8 +232,13 @@ checkInt<21>(Loc, Val, Type); write32AArch64Addr(Loc, Val); break; - case R_AARCH64_CALL26: case R_AARCH64_JUMP26: + // When patching instructions we may use a branch immediate to overwrite a + // potentially non-branch instruction so write the full branch instruction + // opcode (0 001 | 01 imm26). + write32le(Loc, 0x14000000); + // Fallthrough + case R_AARCH64_CALL26: checkInt<28>(Loc, Val, Type); or32le(Loc, (Val & 0x0FFFFFFC) >> 2); break; Index: test/ELF/aarch64-branch-fullrange.s =================================================================== --- /dev/null +++ test/ELF/aarch64-branch-fullrange.s @@ -0,0 +1,42 @@ +// REQUIRES: aarch64 +// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o +// RUN: echo "SECTIONS { \ +// RUN: .text.below 0x1000 : { *(.text.below) } \ +// RUN: .text 0x8001000 : { *.(.text) } \ +// RUN: .text.high 0x10001000 : { *(.text.high) } }" > %t.script +// RUN: ld.lld --script %t.script %t.o -o %t2 +// RUN: llvm-objdump -d -triple=aarch64-none-linux %t2 | FileCheck %s +// Test extremes of AArch64 branch range + .section .text.below, "ax", %progbits + .balign 4 + .globl low + .type low, %function +low: + ret + + .text + .balign 4 + .globl _start + .type _start, %function +_start: + b low + b high + ret + + .section .text.high, "ax", %progbits + .balign 4 + .globl high + .type high, %function +high: + ret +// CHECK: Disassembly of section .text.below: +// CHECK-NEXT: low: +// CHECK-NEXT: 1000: c0 03 5f d6 ret +// CHECK-NEXT: Disassembly of section .text: +// CHECK-NEXT: _start: +// CHECK-NEXT: 8001000: 00 00 00 16 b #-134217728 +// CHECK-NEXT: 8001004: ff ff ff 15 b #134217724 +// CHECK-NEXT: 8001008: c0 03 5f d6 ret +// CHECK-NEXT: Disassembly of section .text.high: +// CHECK-NEXT: high: +// CHECK-NEXT: 10001000: c0 03 5f d6 ret