diff --git a/root-aarch64.patch b/root-aarch64.patch new file mode 100644 index 0000000..268f37b --- /dev/null +++ b/root-aarch64.patch @@ -0,0 +1,196 @@ +diff --git a/interpreter/llvm/src/include/llvm/Object/ELFObjectFile.h b/interpreter/llvm/src/include/llvm/Object/ELFObjectFile.h +index 6dcd2d4..bafbd36 100644 +--- a/interpreter/llvm/src/include/llvm/Object/ELFObjectFile.h ++++ b/interpreter/llvm/src/include/llvm/Object/ELFObjectFile.h +@@ -905,7 +905,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/interpreter/llvm/src/include/llvm/Object/RelocVisitor.h b/interpreter/llvm/src/include/llvm/Object/RelocVisitor.h +index 5e0df98..b59e8ec 100644 +--- a/interpreter/llvm/src/include/llvm/Object/RelocVisitor.h ++++ b/interpreter/llvm/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/interpreter/llvm/src/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/interpreter/llvm/src/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +index f2a46b8..9e306bb 100644 +--- a/interpreter/llvm/src/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp ++++ b/interpreter/llvm/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/root.spec b/root.spec index acbfd13..a047ab8 100644 --- a/root.spec +++ b/root.spec @@ -23,7 +23,7 @@ Name: root Version: 6.08.06 %global libversion %(cut -d. -f 1-2 <<< %{version}) -Release: 1%{?dist} +Release: 2%{?dist} Summary: Numerical data analysis framework License: LGPLv2+ @@ -100,11 +100,14 @@ Patch19: %{name}-format.patch # Allow both absolute and relative python install paths # https://github.com/root-project/root/pull/382 Patch20: %{name}-python-install-path.patch - -# The build on aarch64 used to work, but is now broken again +# Fix relocation problems on aarch64 +# Based on the patch in Fedora's llvm package +# https://reviews.llvm.org/D27609 # https://pagure.io/releng/issue/6653 # https://sft.its.cern.ch/jira/browse/ROOT-8702 -ExcludeArch: aarch64 +# https://github.com/root-project/root/pull/430 +Patch21: %{name}-aarch64.patch + # s390 is not supported by cling: "error: unknown target # triple 's390-ibm-linux', please use -triple or -arch" ExcludeArch: s390 @@ -1578,6 +1581,7 @@ ROOT as a Jupyter Notebook. %patch18 -p1 %patch19 -p1 %patch20 -p1 +%patch21 -p1 # Remove bundled sources in order to be sure they are not used # * afterimage @@ -3136,6 +3140,10 @@ fi %{_datadir}/%{name}/notebook %changelog +* Wed Mar 15 2017 Mattias Ellert - 6.08.06-2 +- Fix relocation problems on aarch64 - using patch from the llvm package +- Re-enable building on aarch64 - works again with the above patch + * Thu Mar 02 2017 Mattias Ellert - 6.08.06-1 - Update to 6.08.06 - Drop obsolete patch: root-tformulaparsingtests.patch