From 146ec0c4aa2ced4394456258b300c38767039674 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Sun, 12 Mar 2017 19:22:26 +0000 Subject: [PATCH] Fix missing mask on relocation for aarch64 (rhbz 1429050) --- ...ix-R_AARCH64_MOVW_UABS_G3-relocation.patch | 435 ++++++++++++++++++ llvm.spec | 8 +- 2 files changed, 442 insertions(+), 1 deletion(-) create mode 100644 0001-Fix-R_AARCH64_MOVW_UABS_G3-relocation.patch diff --git a/0001-Fix-R_AARCH64_MOVW_UABS_G3-relocation.patch b/0001-Fix-R_AARCH64_MOVW_UABS_G3-relocation.patch new file mode 100644 index 0000000..c5517ad --- /dev/null +++ b/0001-Fix-R_AARCH64_MOVW_UABS_G3-relocation.patch @@ -0,0 +1,435 @@ +From 29cf3bd00fe84ddab138c9311fe288bb9da8a273 Mon Sep 17 00:00:00 2001 +From: root +Date: Thu, 9 Mar 2017 12:22:48 -0600 +Subject: [PATCH] Fix R_AARCH64_MOVW_UABS_G3 relocation + +Summary: The relocation is missing mask so an address that +has non-zero bits in 47:43 may overwrite the register +number. (Frequently shows up as target register changed +to xzr....) + +Reviewers: t.p.northover, lhames +Subscribers: davide, aemerson, rengolin, llvm-commits +Differential Revision: https://reviews.llvm.org/D27609 +--- + llvm-3.9.1.src/include/llvm/Object/ELFObjectFile.h | 2 +- + llvm-3.9.1.src/include/llvm/Object/RelocVisitor.h | 1 + + .../ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 67 +++++++++----- + .../RuntimeDyld/AArch64/ELF_ARM64_BE-relocations.s | 102 +++++++++++++++++++++ + .../RuntimeDyld/AArch64/ELF_ARM64_relocations.s | 99 ++++++++++++++++++++ + 5 files changed, 249 insertions(+), 22 deletions(-) + create mode 100644 llvm-3.9.1.src/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_BE-relocations.s + create mode 100644 llvm-3.9.1.src/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_relocations.s + +diff --git a/llvm-3.9.1.src/include/llvm/Object/ELFObjectFile.h b/llvm-3.9.1.src/include/llvm/Object/ELFObjectFile.h +index 07c6364..d3b83f9 100644 +--- a/llvm-3.9.1.src/include/llvm/Object/ELFObjectFile.h ++++ b/llvm-3.9.1.src/include/llvm/Object/ELFObjectFile.h +@@ -907,7 +907,7 @@ unsigned ELFObjectFile::getArch() const { + case ELF::EM_X86_64: + return Triple::x86_64; + case ELF::EM_AARCH64: +- return Triple::aarch64; ++ return IsLittleEndian ? Triple::aarch64 : Triple::aarch64_be; + case ELF::EM_ARM: + return Triple::arm; + case ELF::EM_AVR: +diff --git a/llvm-3.9.1.src/include/llvm/Object/RelocVisitor.h b/llvm-3.9.1.src/include/llvm/Object/RelocVisitor.h +index 5e0df98..b59e8ec 100644 +--- a/llvm-3.9.1.src/include/llvm/Object/RelocVisitor.h ++++ b/llvm-3.9.1.src/include/llvm/Object/RelocVisitor.h +@@ -86,6 +86,7 @@ private: + return RelocToApply(); + } + case Triple::aarch64: ++ case Triple::aarch64_be: + switch (RelocType) { + case llvm::ELF::R_AARCH64_ABS32: + return visitELF_AARCH64_ABS32(R, Value); +diff --git a/llvm-3.9.1.src/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm-3.9.1.src/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +index 9cbdb13..9e04b5d 100644 +--- a/llvm-3.9.1.src/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp ++++ b/llvm-3.9.1.src/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +@@ -309,6 +309,8 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, + uint32_t *TargetPtr = + reinterpret_cast(Section.getAddressWithOffset(Offset)); + uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); ++ // Data should use target endian. Code should always use little endian. ++ bool isBE = Arch == Triple::aarch64_be; + + DEBUG(dbgs() << "resolveAArch64Relocation, LocalAddress: 0x" + << format("%llx", Section.getAddressWithOffset(Offset)) +@@ -324,14 +326,22 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, + case ELF::R_AARCH64_ABS64: { + uint64_t *TargetPtr = + reinterpret_cast(Section.getAddressWithOffset(Offset)); +- *TargetPtr = Value + Addend; ++ if (isBE) ++ support::ubig64_t::ref{TargetPtr} = Value + Addend; ++ else ++ support::ulittle64_t::ref{TargetPtr} = Value + Addend; + break; + } + case ELF::R_AARCH64_PREL32: { + uint64_t Result = Value + Addend - FinalAddress; + assert(static_cast(Result) >= INT32_MIN && + static_cast(Result) <= UINT32_MAX); +- *TargetPtr = static_cast(Result & 0xffffffffU); ++ if (isBE) ++ support::ubig32_t::ref{TargetPtr} = ++ static_cast(Result & 0xffffffffU); ++ else ++ support::ulittle32_t::ref{TargetPtr} = ++ static_cast(Result & 0xffffffffU); + break; + } + case ELF::R_AARCH64_CALL26: // fallthrough +@@ -339,6 +349,7 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, + // Operation: S+A-P. Set Call or B immediate value to bits fff_fffc of the + // calculation. + uint64_t BranchImm = Value + Addend - FinalAddress; ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // "Check that -2^27 <= result < 2^27". + assert(isInt<28>(BranchImm)); +@@ -352,91 +363,105 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, + } + case ELF::R_AARCH64_MOVW_UABS_G3: { + uint64_t Result = Value + Addend; ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0xffe0001fU; ++ TargetValue &= 0xffe0001fU; + // Immediate goes in bits 20:5 of MOVZ/MOVK instruction +- *TargetPtr |= Result >> (48 - 5); ++ TargetValue |= ((Result & 0xffff000000000000ULL) >> (48 - 5)); + // Shift must be "lsl #48", in bits 22:21 +- assert((*TargetPtr >> 21 & 0x3) == 3 && "invalid shift for relocation"); ++ assert((TargetValue >> 21 & 0x3) == 3 && "invalid shift for relocation"); ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + case ELF::R_AARCH64_MOVW_UABS_G2_NC: { + uint64_t Result = Value + Addend; ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0xffe0001fU; ++ TargetValue &= 0xffe0001fU; + // Immediate goes in bits 20:5 of MOVZ/MOVK instruction +- *TargetPtr |= ((Result & 0xffff00000000ULL) >> (32 - 5)); ++ TargetValue |= ((Result & 0xffff00000000ULL) >> (32 - 5)); + // Shift must be "lsl #32", in bits 22:21 +- assert((*TargetPtr >> 21 & 0x3) == 2 && "invalid shift for relocation"); ++ assert((TargetValue >> 21 & 0x3) == 2 && "invalid shift for relocation"); ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + case ELF::R_AARCH64_MOVW_UABS_G1_NC: { + uint64_t Result = Value + Addend; ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0xffe0001fU; ++ TargetValue &= 0xffe0001fU; + // Immediate goes in bits 20:5 of MOVZ/MOVK instruction +- *TargetPtr |= ((Result & 0xffff0000U) >> (16 - 5)); ++ TargetValue |= ((Result & 0xffff0000U) >> (16 - 5)); + // Shift must be "lsl #16", in bits 22:2 +- assert((*TargetPtr >> 21 & 0x3) == 1 && "invalid shift for relocation"); ++ assert((TargetValue >> 21 & 0x3) == 1 && "invalid shift for relocation"); ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + case ELF::R_AARCH64_MOVW_UABS_G0_NC: { + uint64_t Result = Value + Addend; ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0xffe0001fU; ++ TargetValue &= 0xffe0001fU; + // Immediate goes in bits 20:5 of MOVZ/MOVK instruction +- *TargetPtr |= ((Result & 0xffffU) << 5); ++ TargetValue |= ((Result & 0xffffU) << 5); + // Shift must be "lsl #0", in bits 22:21. +- assert((*TargetPtr >> 21 & 0x3) == 0 && "invalid shift for relocation"); ++ assert((TargetValue >> 21 & 0x3) == 0 && "invalid shift for relocation"); ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + case ELF::R_AARCH64_ADR_PREL_PG_HI21: { + // Operation: Page(S+A) - Page(P) + uint64_t Result = + ((Value + Addend) & ~0xfffULL) - (FinalAddress & ~0xfffULL); ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // Check that -2^32 <= X < 2^32 + assert(isInt<33>(Result) && "overflow check failed for relocation"); + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0x9f00001fU; ++ TargetValue &= 0x9f00001fU; + // Immediate goes in bits 30:29 + 5:23 of ADRP instruction, taken + // from bits 32:12 of X. +- *TargetPtr |= ((Result & 0x3000U) << (29 - 12)); +- *TargetPtr |= ((Result & 0x1ffffc000ULL) >> (14 - 5)); ++ TargetValue |= ((Result & 0x3000U) << (29 - 12)); ++ TargetValue |= ((Result & 0x1ffffc000ULL) >> (14 - 5)); ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + case ELF::R_AARCH64_LDST32_ABS_LO12_NC: { + // Operation: S + A + uint64_t Result = Value + Addend; ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0xffc003ffU; ++ TargetValue &= 0xffc003ffU; + // Immediate goes in bits 21:10 of LD/ST instruction, taken + // from bits 11:2 of X +- *TargetPtr |= ((Result & 0xffc) << (10 - 2)); ++ TargetValue |= ((Result & 0xffc) << (10 - 2)); ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + case ELF::R_AARCH64_LDST64_ABS_LO12_NC: { + // Operation: S + A + uint64_t Result = Value + Addend; ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0xffc003ffU; ++ TargetValue &= 0xffc003ffU; + // Immediate goes in bits 21:10 of LD/ST instruction, taken + // from bits 11:3 of X +- *TargetPtr |= ((Result & 0xff8) << (10 - 3)); ++ TargetValue |= ((Result & 0xff8) << (10 - 3)); ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + } +diff --git a/llvm-3.9.1.src/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_BE-relocations.s b/llvm-3.9.1.src/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_BE-relocations.s +new file mode 100644 +index 0000000..01d01e5 +--- /dev/null ++++ b/llvm-3.9.1.src/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_BE-relocations.s +@@ -0,0 +1,102 @@ ++# RUN: llvm-mc -triple=aarch64_be-none-linux-gnu -filetype=obj -o %T/be-reloc.o %s ++# RUN: llvm-rtdyld -triple=aarch64_be-none-linux-gnu -verify -dummy-extern f=0x0123456789abcdef -check=%s %T/be-reloc.o ++ ++ .text ++ .globl g ++ .p2align 2 ++ .type g,@function ++g: ++# R_AARCH64_MOVW_UABS_G3 ++ movz x0, #:abs_g3:f ++# R_AARCH64_MOVW_UABS_G2_NC ++ movk x0, #:abs_g2_nc:f ++# R_AARCH64_MOVW_UABS_G1_NC ++ movk x0, #:abs_g1_nc:f ++# R_AARCH64_MOVW_UABS_G0_NC ++ movk x0, #:abs_g0_nc:f ++ ret ++ .Lfunc_end0: ++ .size g, .Lfunc_end0-g ++ ++ .type k,@object ++ .data ++ .globl k ++ .p2align 3 ++k: ++ .xword f ++ .size k, 8 ++ ++# LE instructions read as BE ++# rtdyld-check: *{4}(g) = 0x6024e0d2 ++# rtdyld-check: *{4}(g + 4) = 0xe0acc8f2 ++# rtdyld-check: *{4}(g + 8) = 0x6035b1f2 ++# rtdyld-check: *{4}(g + 12) = 0xe0bd99f2 ++# rtdyld-check: *{8}k = f ++# RUN: llvm-mc -triple=aarch64_be-none-linux-gnu -filetype=obj -o %T/be-reloc.o %s ++# RUN: llvm-rtdyld -triple=aarch64_be-none-linux-gnu -verify -dummy-extern f=0x0123456789abcdef -check=%s %T/be-reloc.o ++ ++ .text ++ .globl g ++ .p2align 2 ++ .type g,@function ++g: ++# R_AARCH64_MOVW_UABS_G3 ++ movz x0, #:abs_g3:f ++# R_AARCH64_MOVW_UABS_G2_NC ++ movk x0, #:abs_g2_nc:f ++# R_AARCH64_MOVW_UABS_G1_NC ++ movk x0, #:abs_g1_nc:f ++# R_AARCH64_MOVW_UABS_G0_NC ++ movk x0, #:abs_g0_nc:f ++ ret ++ .Lfunc_end0: ++ .size g, .Lfunc_end0-g ++ ++ .type k,@object ++ .data ++ .globl k ++ .p2align 3 ++k: ++ .xword f ++ .size k, 8 ++ ++# LE instructions read as BE ++# rtdyld-check: *{4}(g) = 0x6024e0d2 ++# rtdyld-check: *{4}(g + 4) = 0xe0acc8f2 ++# rtdyld-check: *{4}(g + 8) = 0x6035b1f2 ++# rtdyld-check: *{4}(g + 12) = 0xe0bd99f2 ++# rtdyld-check: *{8}k = f ++# RUN: llvm-mc -triple=aarch64_be-none-linux-gnu -filetype=obj -o %T/be-reloc.o %s ++# RUN: llvm-rtdyld -triple=aarch64_be-none-linux-gnu -verify -dummy-extern f=0x0123456789abcdef -check=%s %T/be-reloc.o ++ ++ .text ++ .globl g ++ .p2align 2 ++ .type g,@function ++g: ++# R_AARCH64_MOVW_UABS_G3 ++ movz x0, #:abs_g3:f ++# R_AARCH64_MOVW_UABS_G2_NC ++ movk x0, #:abs_g2_nc:f ++# R_AARCH64_MOVW_UABS_G1_NC ++ movk x0, #:abs_g1_nc:f ++# R_AARCH64_MOVW_UABS_G0_NC ++ movk x0, #:abs_g0_nc:f ++ ret ++ .Lfunc_end0: ++ .size g, .Lfunc_end0-g ++ ++ .type k,@object ++ .data ++ .globl k ++ .p2align 3 ++k: ++ .xword f ++ .size k, 8 ++ ++# LE instructions read as BE ++# rtdyld-check: *{4}(g) = 0x6024e0d2 ++# rtdyld-check: *{4}(g + 4) = 0xe0acc8f2 ++# rtdyld-check: *{4}(g + 8) = 0x6035b1f2 ++# rtdyld-check: *{4}(g + 12) = 0xe0bd99f2 ++# rtdyld-check: *{8}k = f +diff --git a/llvm-3.9.1.src/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_relocations.s b/llvm-3.9.1.src/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_relocations.s +new file mode 100644 +index 0000000..e07fa97 +--- /dev/null ++++ b/llvm-3.9.1.src/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_relocations.s +@@ -0,0 +1,99 @@ ++# RUN: llvm-mc -triple=arm64-none-linux-gnu -filetype=obj -o %T/reloc.o %s ++# RUN: llvm-rtdyld -triple=arm64-none-linux-gnu -verify -dummy-extern f=0x0123456789abcdef -check=%s %T/reloc.o ++ ++ .text ++ .globl g ++ .p2align 2 ++ .type g,@function ++g: ++# R_AARCH64_MOVW_UABS_G3 ++ movz x0, #:abs_g3:f ++# R_AARCH64_MOVW_UABS_G2_NC ++ movk x0, #:abs_g2_nc:f ++# R_AARCH64_MOVW_UABS_G1_NC ++ movk x0, #:abs_g1_nc:f ++# R_AARCH64_MOVW_UABS_G0_NC ++ movk x0, #:abs_g0_nc:f ++ ret ++ .Lfunc_end0: ++ .size g, .Lfunc_end0-g ++ ++ .type k,@object ++ .data ++ .globl k ++ .p2align 3 ++k: ++ .xword f ++ .size k, 8 ++ ++# rtdyld-check: *{4}(g) = 0xd2e02460 ++# rtdyld-check: *{4}(g + 4) = 0xf2c8ace0 ++# rtdyld-check: *{4}(g + 8) = 0xf2b13560 ++# rtdyld-check: *{4}(g + 12) = 0xf299bde0 ++# rtdyld-check: *{8}k = f ++# RUN: llvm-mc -triple=arm64-none-linux-gnu -filetype=obj -o %T/reloc.o %s ++# RUN: llvm-rtdyld -triple=arm64-none-linux-gnu -verify -dummy-extern f=0x0123456789abcdef -check=%s %T/reloc.o ++ ++ .text ++ .globl g ++ .p2align 2 ++ .type g,@function ++g: ++# R_AARCH64_MOVW_UABS_G3 ++ movz x0, #:abs_g3:f ++# R_AARCH64_MOVW_UABS_G2_NC ++ movk x0, #:abs_g2_nc:f ++# R_AARCH64_MOVW_UABS_G1_NC ++ movk x0, #:abs_g1_nc:f ++# R_AARCH64_MOVW_UABS_G0_NC ++ movk x0, #:abs_g0_nc:f ++ ret ++ .Lfunc_end0: ++ .size g, .Lfunc_end0-g ++ ++ .type k,@object ++ .data ++ .globl k ++ .p2align 3 ++k: ++ .xword f ++ .size k, 8 ++ ++# rtdyld-check: *{4}(g) = 0xd2e02460 ++# rtdyld-check: *{4}(g + 4) = 0xf2c8ace0 ++# rtdyld-check: *{4}(g + 8) = 0xf2b13560 ++# rtdyld-check: *{4}(g + 12) = 0xf299bde0 ++# rtdyld-check: *{8}k = f ++# RUN: llvm-mc -triple=arm64-none-linux-gnu -filetype=obj -o %T/reloc.o %s ++# RUN: llvm-rtdyld -triple=arm64-none-linux-gnu -verify -dummy-extern f=0x0123456789abcdef -check=%s %T/reloc.o ++ ++ .text ++ .globl g ++ .p2align 2 ++ .type g,@function ++g: ++# R_AARCH64_MOVW_UABS_G3 ++ movz x0, #:abs_g3:f ++# R_AARCH64_MOVW_UABS_G2_NC ++ movk x0, #:abs_g2_nc:f ++# R_AARCH64_MOVW_UABS_G1_NC ++ movk x0, #:abs_g1_nc:f ++# R_AARCH64_MOVW_UABS_G0_NC ++ movk x0, #:abs_g0_nc:f ++ ret ++ .Lfunc_end0: ++ .size g, .Lfunc_end0-g ++ ++ .type k,@object ++ .data ++ .globl k ++ .p2align 3 ++k: ++ .xword f ++ .size k, 8 ++ ++# rtdyld-check: *{4}(g) = 0xd2e02460 ++# rtdyld-check: *{4}(g + 4) = 0xf2c8ace0 ++# rtdyld-check: *{4}(g + 8) = 0xf2b13560 ++# rtdyld-check: *{4}(g + 12) = 0xf299bde0 ++# rtdyld-check: *{8}k = f +-- +2.12.0 + diff --git a/llvm.spec b/llvm.spec index 5736e36..1071bac 100644 --- a/llvm.spec +++ b/llvm.spec @@ -7,7 +7,7 @@ Name: llvm Version: 3.9.1 -Release: 3%{?dist} +Release: 4%{?dist} Summary: The Low Level Virtual Machine License: NCSA @@ -30,6 +30,8 @@ Patch5: 0001-cmake-Install-CheckAtomic.cmake-needed-by-lldb.patch Patch6: llvm-r294646.patch # This fix caused regressions Patch7: 0001-Revert-Merging-r280589.patch +# https://reviews.llvm.org/D27609 +Patch8: 0001-Fix-R_AARCH64_MOVW_UABS_G3-relocation.patch # backports cribbed from https://github.com/rust-lang/llvm/ Patch47: rust-lang-llvm-pr47.patch @@ -96,6 +98,7 @@ Static libraries for the LLVM compiler infrastructure. %patch5 -p1 -b .lldbfix %patch6 -p0 -b .doc-lit %patch7 -p1 -b .amdfix +%patch8 -p2 -b .arm64 %patch47 -p1 -b .rust47 %patch53 -p1 -b .rust53 %patch54 -p1 -b .rust54 @@ -217,6 +220,9 @@ make check-all || : %{_libdir}/*.a %changelog +* Sun Mar 12 2017 Peter Robinson 3.9.1-4 +- Fix missing mask on relocation for aarch64 (rhbz 1429050) + * Wed Mar 01 2017 Dave Airlie - 3.9.1-3 - revert upstream radeonsi breaking change.