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 Index: test/ELF/relocation-b-aarch64.test =================================================================== --- /dev/null +++ test/ELF/relocation-b-aarch64.test @@ -0,0 +1,39 @@ +# REQUIRES: aarch64 + +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t.out +# RUN: llvm-objdump -d -triple=aarch64-none-linux %t.out | FileCheck %s + +# REQUIRES: aarch64 + +# Check that the R_AARCH64_JUMP26 writes the branch opcode as well as the +# immediate. We use this property to overwrite instructions with a branch. + +# CHECK: Disassembly of section .text: +# CHECK-NEXT: foo: +# CHECK-NEXT: 20000: 00 00 00 14 b #0 + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_AARCH64 +Sections: + - Type: SHT_PROGBITS + Name: .text + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Content: "00000000" + - Type: SHT_RELA + Name: .rela.text + Link: .symtab + Info: .text + Relocations: + - Offset: 0 + Symbol: foo + Type: R_AARCH64_JUMP26 +Symbols: + Local: + - Type: STT_FUNC + Section: .text + Name: foo