From 3274a849f46891c1748a494893918ff1eeb4fe7b Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Mon, 13 Apr 2015 11:40:50 +0000 Subject: [PATCH] ELF/AArch64: Add support for R_AARCH64_PREL16 Add support for the R_AARCH64_PREL16 relocation type and add tests. Patch by Will Newton. llvm-svn: 234742 --- .../ELF/AArch64/AArch64RelocationHandler.cpp | 18 +++++- lld/test/elf/AArch64/rel-prel16-overflow.test | 53 +++++++++++++++++ lld/test/elf/AArch64/rel-prel16.test | 59 +++++++++++++++++++ 3 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 lld/test/elf/AArch64/rel-prel16-overflow.test create mode 100644 lld/test/elf/AArch64/rel-prel16.test diff --git a/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp index 8a967d40eedb..2d3052241b33 100644 --- a/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp @@ -98,6 +98,21 @@ static std::error_code relocR_AARCH64_PREL32(uint8_t *location, uint64_t P, return std::error_code(); } +/// \brief R_AARCH64_PREL16 - word16: S + A - P +static std::error_code relocR_AARCH64_PREL16(uint8_t *location, uint64_t P, + uint64_t S, int64_t A) { + int64_t result = S + A - P; + if (!withinSignedUnsignedRange(result, 16)) + return make_out_of_range_reloc_error(); + 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"); + write16le(location, result + read16le(location)); + return std::error_code(); +} + /// \brief R_AARCH64_ADR_PREL_PG_HI21 - Page(S+A) - Page(P) static void relocR_AARCH64_ADR_PREL_PG_HI21(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { @@ -115,7 +130,6 @@ static void relocR_AARCH64_ADR_PREL_PG_HI21(uint8_t *location, uint64_t P, llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo); llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n"); write32le(location, immlo | immhi | read32le(location)); - // TODO: Make sure this is correct! } /// \brief R_AARCH64_ADR_PREL_LO21 - S + A - P @@ -382,6 +396,8 @@ std::error_code AArch64TargetRelocationHandler::applyRelocation( break; case R_AARCH64_PREL32: return relocR_AARCH64_PREL32(loc, reloc, target, addend); + case R_AARCH64_PREL16: + return relocR_AARCH64_PREL16(loc, reloc, target, addend); // Runtime only relocations. Ignore here. case R_AARCH64_RELATIVE: case R_AARCH64_IRELATIVE: diff --git a/lld/test/elf/AArch64/rel-prel16-overflow.test b/lld/test/elf/AArch64/rel-prel16-overflow.test new file mode 100644 index 000000000000..0e9987be918d --- /dev/null +++ b/lld/test/elf/AArch64/rel-prel16-overflow.test @@ -0,0 +1,53 @@ +# Check handling of R_AARCH64_PREL16 relocation overflow. +# RUN: yaml2obj -format=elf %s > %t-obj +# RUN: not lld -flavor gnu -target arm64 -o %t-exe %t-obj 2>&1 | FileCheck %s + +# CHECK: Relocation out of range in file {{.*}}: reference from data1+0 to data2+524289 of type 262 (R_AARCH64_PREL16) +# CHECK: Relocation out of range in file {{.*}}: reference from data2+0 to data1+524289 of type 262 (R_AARCH64_PREL16) + +!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: "0000000000000000" + 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_PREL16 + Addend: 0x80001 + - Offset: 0x2 + Symbol: data1 + Type: R_AARCH64_PREL16 + Addend: 0x80001 + +Symbols: + Global: + - Name: _start + Section: .text + Value: 0x0 + Size: 4 + - Name: data1 + Section: .data + Size: 2 + - Name: data2 + Section: .data + Value: 0x2 + Size: 2 diff --git a/lld/test/elf/AArch64/rel-prel16.test b/lld/test/elf/AArch64/rel-prel16.test new file mode 100644 index 000000000000..f78d2cfafaf9 --- /dev/null +++ b/lld/test/elf/AArch64/rel-prel16.test @@ -0,0 +1,59 @@ +# Check handling of R_AARCH64_PREL16 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 0380ff7f 00000000 ........ +# ^^ data2 - data1 + 0x8001 = 0x8003 +# ^^ data1 - data2 + 0x8001 = 0x7fff +# CHECK: SYMBOL TABLE: +# CHECK: 00401060 g .data 00000002 data1 +# CHECK: 00401062 g .data 00000006 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: "0000000000000000" + 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_PREL16 + Addend: 0x8001 + - Offset: 0x2 + Symbol: data1 + Type: R_AARCH64_PREL16 + Addend: 0x8001 + +Symbols: + Global: + - Name: _start + Section: .text + Value: 0x0 + Size: 4 + - Name: data1 + Section: .data + Size: 2 + - Name: data2 + Section: .data + Value: 0x2 + Size: 2