Index: lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp +++ lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp @@ -65,9 +65,7 @@ llvm::dbgs() << " A: 0x" << Twine::utohexstr(A); llvm::dbgs() << " P: 0x" << Twine::utohexstr(P); llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n"); - *reinterpret_cast(location) = - result | - (int16_t) * reinterpret_cast(location); + write16le(location, result | read16le(location)); return std::error_code(); } @@ -75,9 +73,7 @@ static void relocR_AARCH64_PREL64(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { int64_t result = S + A - P; - *reinterpret_cast(location) = - result + - (int64_t) * reinterpret_cast(location); + write64le(location, result | read64le(location)); } /// \brief R_AARCH64_PREL32 - word32: S + A - P @@ -86,9 +82,7 @@ int64_t result = S + A - P; if (!withinSignedUnsignedRange(result, 32)) return make_out_of_range_reloc_error(); - *reinterpret_cast(location) = - result + - (int32_t) * reinterpret_cast(location); + write32le(location, result | read32le(location)); return std::error_code(); } @@ -98,9 +92,7 @@ int64_t result = S + A - P; if (!withinSignedUnsignedRange(result, 16)) return make_out_of_range_reloc_error(); - *reinterpret_cast(location) = - result + - (int16_t) * reinterpret_cast(location); + write16le(location, result | read16le(location)); return std::error_code(); } @@ -255,36 +247,44 @@ write32le(location, result | read32le(location)); } -static void relocR_AARCH64_ADR_GOT_PAGE(uint8_t *location, uint64_t P, +static std::error_code relocR_AARCH64_ADR_GOT_PAGE(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { uint64_t result = PAGE(S + A) - PAGE(P); - result >>= 12; - uint32_t immlo = result & 0x3; - uint32_t immhi = result & 0x1FFFFC; + if (!isInt<32>(result)) + return make_out_of_range_reloc_error(); + result = (result >> 12) & 0x3FFFFL; + uint32_t immlo = result & 0x3L; + uint32_t immhi = result & 0x1FFFFCL; immlo = immlo << 29; immhi = immhi << 3; - DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; - llvm::dbgs() << " S: " << Twine::utohexstr(S); - llvm::dbgs() << " A: " << Twine::utohexstr(A); - llvm::dbgs() << " P: " << Twine::utohexstr(P); - llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi); - llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo); - llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n"); - write32le(location, result | read32le(location)); + DEBUG_WITH_TYPE( + "AArch64", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; + llvm::dbgs() << " S: " << Twine::utohexstr(S); + llvm::dbgs() << " A: " << Twine::utohexstr(A); + llvm::dbgs() << " P: " << Twine::utohexstr(P); + llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi); + llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo); + llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n"); + write32le(location, immlo | immhi | read32le(location)); + return std::error_code(); } // R_AARCH64_LD64_GOT_LO12_NC -static void relocR_AARCH64_LD64_GOT_LO12_NC(uint8_t *location, uint64_t P, +static std::error_code relocR_AARCH64_LD64_GOT_LO12_NC(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { int32_t result = S + A; - DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; - llvm::dbgs() << " S: " << Twine::utohexstr(S); - llvm::dbgs() << " A: " << Twine::utohexstr(A); - llvm::dbgs() << " P: " << Twine::utohexstr(P); - llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n"); + DEBUG_WITH_TYPE( + "AArch64", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; + llvm::dbgs() << " S: " << Twine::utohexstr(S); + llvm::dbgs() << " A: " << Twine::utohexstr(A); + llvm::dbgs() << " P: " << Twine::utohexstr(P); + llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n"); + if ((result & 0x7) != 0) + return make_unaligned_range_reloc_error(); result &= 0xFF8; result <<= 7; write32le(location, result | read32le(location)); + return std::error_code(); } // ADD_AARCH64_GOTRELINDEX @@ -424,13 +424,11 @@ ref.addend()); break; case R_AARCH64_ADR_GOT_PAGE: - relocR_AARCH64_ADR_GOT_PAGE(location, relocVAddress, targetVAddress, - ref.addend()); - break; + return relocR_AARCH64_ADR_GOT_PAGE(location, relocVAddress, targetVAddress, + ref.addend()); case R_AARCH64_LD64_GOT_LO12_NC: - relocR_AARCH64_LD64_GOT_LO12_NC(location, relocVAddress, targetVAddress, - ref.addend()); - break; + return relocR_AARCH64_LD64_GOT_LO12_NC(location, relocVAddress, targetVAddress, + ref.addend()); case R_AARCH64_LDST8_ABS_LO12_NC: relocR_AARCH64_LDST8_ABS_LO12_NC(location, relocVAddress, targetVAddress, ref.addend()); Index: lib/ReaderWriter/ELF/TargetHandler.h =================================================================== --- lib/ReaderWriter/ELF/TargetHandler.h +++ lib/ReaderWriter/ELF/TargetHandler.h @@ -78,6 +78,10 @@ return make_dynamic_error_code(Twine("Relocation out of range")); } +inline std::error_code make_unaligned_range_reloc_error() { + return make_dynamic_error_code(Twine("Relocation not aligned")); +} + } // end namespace elf } // end namespace lld