diff --git a/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp index d0a00147f5d6..8a967d40eedb 100644 --- a/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp @@ -69,6 +69,18 @@ static std::error_code relocR_AARCH64_ABS16(uint8_t *location, uint64_t P, return std::error_code(); } +/// \brief R_AARCH64_PREL64 - word64: S + A - P +static void relocR_AARCH64_PREL64(uint8_t *location, uint64_t P, + uint64_t S, int64_t A) { + int64_t result = S + A - P; + DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; + llvm::dbgs() << " S: 0x" << Twine::utohexstr(S); + llvm::dbgs() << " A: 0x" << Twine::utohexstr(A); + llvm::dbgs() << " P: 0x" << Twine::utohexstr(P); + llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n"); + write64le(location, result + read64le(location)); +} + /// \brief R_AARCH64_PREL32 - word32: S + A - P static std::error_code relocR_AARCH64_PREL32(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { @@ -365,6 +377,9 @@ std::error_code AArch64TargetRelocationHandler::applyRelocation( return relocR_AARCH64_ABS32(loc, reloc, target, addend); case R_AARCH64_ABS16: return relocR_AARCH64_ABS16(loc, reloc, target, addend); + case R_AARCH64_PREL64: + relocR_AARCH64_PREL64(loc, reloc, target, addend); + break; case R_AARCH64_PREL32: return relocR_AARCH64_PREL32(loc, reloc, target, addend); // Runtime only relocations. Ignore here. diff --git a/lld/test/elf/AArch64/rel-prel64.test b/lld/test/elf/AArch64/rel-prel64.test new file mode 100644 index 000000000000..896776da2142 --- /dev/null +++ b/lld/test/elf/AArch64/rel-prel64.test @@ -0,0 +1,59 @@ +# Check handling of R_AARCH64_PREL64 relocation. +# RUN: yaml2obj -format=elf %s > %t-obj +# RUN: lld -flavor gnu -target arm64 -o %t-exe %t-obj +# RUN: llvm-objdump -s -t %t-exe | FileCheck %s + +# CHECK: Contents of section .data: +# CHECK-NEXT: 401060 09000000 00000080 f9ffffff ffffff7f ................ +# ^^ data2 - data1 + 0x8000000000000001 = 0x8000000000000009 +# ^^ data1 - data2 + 0x8000000000000001 = 0x7ffffffffffffff9 +# CHECK: SYMBOL TABLE: +# CHECK: 00401060 g .data 00000008 data1 +# CHECK: 00401068 g .data 00000008 data2 + +!ELF +FileHeader: !FileHeader + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_AARCH64 + +Sections: +- Name: .text + Type: SHT_PROGBITS + Content: "00000000" + AddressAlign: 16 + Flags: [SHF_ALLOC, SHF_EXECINSTR] +- Name: .data + Type: SHT_PROGBITS + Content: "00000000000000000000000000000000" + AddressAlign: 16 + Flags: [SHF_ALLOC, SHF_WRITE] + +- Name: .rela.data + Type: SHT_RELA + Info: .data + AddressAlign: 8 + Relocations: + - Offset: 0x0 + Symbol: data2 + Type: R_AARCH64_PREL64 + Addend: -9223372036854775807 + - Offset: 0x8 + Symbol: data1 + Type: R_AARCH64_PREL64 + Addend: -9223372036854775807 + +Symbols: + Global: + - Name: _start + Section: .text + Value: 0x0 + Size: 4 + - Name: data1 + Section: .data + Size: 8 + - Name: data2 + Section: .data + Value: 0x8 + Size: 8