diff options
Diffstat (limited to 'lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp')
| -rw-r--r-- | lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp | 546 |
1 files changed, 331 insertions, 215 deletions
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp b/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp index d1ecc7fa884b..ac7c769ec26d 100644 --- a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp +++ b/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp @@ -13,11 +13,14 @@ #include "llvm/Support/Endian.h" #include "llvm/Support/MathExtras.h" +#define DEBUG_TYPE "AArch64" + using namespace lld; using namespace lld::elf; +using namespace llvm; using namespace llvm::support::endian; -#define PAGE(X) ((X) & ~0x0FFFL) +static int64_t page(int64_t v) { return v & ~int64_t(0xFFF); } /// \brief Check X is in the interval (-2^(bits-1), 2^bits] static bool withinSignedUnsignedRange(int64_t X, int bits) { @@ -28,77 +31,130 @@ static bool withinSignedUnsignedRange(int64_t X, int bits) { static void relocR_AARCH64_ABS64(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { int64_t result = (int64_t)S + A; - DEBUG_WITH_TYPE( - "AArch64", 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"); + 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 void relocR_AARCH64_PREL32(uint8_t *location, uint64_t P, uint64_t S, - int64_t A) { - int32_t result = (int32_t)((S + A) - P); - write32le(location, result + (int32_t)read32le(location)); -} - /// \brief R_AARCH64_ABS32 - word32: S + A static std::error_code relocR_AARCH64_ABS32(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { int64_t result = S + A; if (!withinSignedUnsignedRange(result, 32)) return make_out_of_range_reloc_error(); - DEBUG_WITH_TYPE( - "AArch64", 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"); + 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"); write32le(location, result | read32le(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, +/// \brief R_AARCH64_ABS16 - word16: S + A +static std::error_code relocR_AARCH64_ABS16(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { - uint64_t result = (PAGE(S + A) - PAGE(P)); + int64_t result = S + A; + 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_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) { + int64_t result = S + A - P; + // ELF for the ARM 64-bit architecture manual states the overflow + // for R_AARCH64_PREL32 to be -2^(-31) <= X < 2^32 + if (!withinSignedUnsignedRange(result, 32)) + 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"); + write32le(location, result + read32le(location)); + 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 std::error_code relocR_AARCH64_ADR_PREL_PG_HI21(uint8_t *location, + uint64_t P, uint64_t S, + int64_t A) { + int64_t result = page(S + A) - page(P); + if (!isInt<32>(result)) + return make_out_of_range_reloc_error(); result = result >> 12; uint32_t immlo = result & 0x3; uint32_t immhi = result & 0x1FFFFC; immlo = immlo << 29; immhi = immhi << 3; - 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"); + 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, immlo | immhi | read32le(location)); - // TODO: Make sure this is correct! + return std::error_code(); } /// \brief R_AARCH64_ADR_PREL_LO21 - S + A - P -static void relocR_AARCH64_ADR_PREL_LO21(uint8_t *location, uint64_t P, - uint64_t S, int64_t A) { - uint64_t result = (S + A) - P; +static std::error_code relocR_AARCH64_ADR_PREL_LO21(uint8_t *location, uint64_t P, + uint64_t S, int64_t A) { + uint64_t result = S + A - P; + if (!isInt<20>(result)) + return make_out_of_range_reloc_error(); uint32_t immlo = result & 0x3; uint32_t immhi = result & 0x1FFFFC; immlo = immlo << 29; immhi = immhi << 3; - 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"); + 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, immlo | immhi | read32le(location)); - // TODO: Make sure this is correct! + return std::error_code(); } /// \brief R_AARCH64_ADD_ABS_LO12_NC @@ -106,41 +162,46 @@ static void relocR_AARCH64_ADD_ABS_LO12_NC(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { int32_t result = (int32_t)((S + A) & 0xFFF); result <<= 10; - 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"); + 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"); write32le(location, result | read32le(location)); } -static void relocJump26(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { - int32_t result = (int32_t)((S + A) - P); +/// \brief R_AARCH64_CALL26 and R_AARCH64_JUMP26 +static std::error_code relocJump26(uint8_t *location, uint64_t P, uint64_t S, + int64_t A) { + int64_t result = S + A - P; + if (!isInt<27>(result)) + return make_out_of_range_reloc_error(); result &= 0x0FFFFFFC; result >>= 2; - 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"); + 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"); write32le(location, result | read32le(location)); + return std::error_code(); } /// \brief R_AARCH64_CONDBR19 -static void relocR_AARCH64_CONDBR19(uint8_t *location, uint64_t P, uint64_t S, - int64_t A) { - int32_t result = (int32_t)((S + A) - P); +static std::error_code relocR_AARCH64_CONDBR19(uint8_t *location, uint64_t P, + uint64_t S, int64_t A) { + int64_t result = S + A - P; + if (!isInt<20>(result)) + return make_out_of_range_reloc_error(); result &= 0x01FFFFC; result <<= 3; - 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"); + 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"); write32le(location, result | read32le(location)); + return std::error_code(); } /// \brief R_AARCH64_LDST8_ABS_LO12_NC - S + A @@ -148,12 +209,11 @@ static void relocR_AARCH64_LDST8_ABS_LO12_NC(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { int32_t result = (int32_t)((S + A) & 0xFFF); result <<= 10; - 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"); + 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"); write32le(location, result | read32le(location)); } @@ -163,12 +223,11 @@ static void relocR_AARCH64_LDST16_ABS_LO12_NC(uint8_t *location, uint64_t P, int32_t result = (int32_t)(S + A); result &= 0x0FFC; result <<= 9; - 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"); + 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"); write32le(location, result | read32le(location)); } @@ -178,12 +237,11 @@ static void relocR_AARCH64_LDST32_ABS_LO12_NC(uint8_t *location, uint64_t P, int32_t result = (int32_t)(S + A); result &= 0x0FFC; result <<= 8; - 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"); + 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"); write32le(location, result | read32le(location)); } @@ -193,12 +251,11 @@ static void relocR_AARCH64_LDST64_ABS_LO12_NC(uint8_t *location, uint64_t P, int32_t result = (int32_t)(S + A); result &= 0x0FF8; result <<= 7; - 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"); + 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"); write32le(location, result | read32le(location)); } @@ -208,83 +265,89 @@ static void relocR_AARCH64_LDST128_ABS_LO12_NC(uint8_t *location, uint64_t P, int32_t result = (int32_t)(S + A); result &= 0x0FF8; result <<= 6; - 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"); + 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"); write32le(location, result | read32le(location)); } -static void 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; +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); + if (!isInt<32>(result)) + return make_out_of_range_reloc_error(); + result = (result >> 12) & 0x3FFFF; uint32_t immlo = result & 0x3; uint32_t immhi = result & 0x1FFFFC; immlo = immlo << 29; immhi = immhi << 3; - 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, result | read32le(location)); + 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, 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, - uint64_t S, int64_t A) { +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_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"); + DEBUG(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 static void relocADD_AARCH64_GOTRELINDEX(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { int32_t result = S + A; - 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"); + 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"); result &= 0xFFF; result <<= 10; write32le(location, result | read32le(location)); } // R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 -static void relocR_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21(uint8_t *location, - uint64_t P, uint64_t S, - int64_t A) { - int64_t result = PAGE(S + A) - PAGE(P); +static std::error_code relocR_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21(uint8_t *location, + uint64_t P, + uint64_t S, + int64_t A) { + int64_t result = page(S + A) - page(P); + if (!isInt<32>(result)) + return make_out_of_range_reloc_error(); result >>= 12; uint32_t immlo = result & 0x3; uint32_t immhi = result & 0x1FFFFC; immlo = immlo << 29; immhi = immhi << 3; - 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"); + 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, immlo | immhi | read32le(location)); + return std::error_code(); } // R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC @@ -294,28 +357,31 @@ static void relocR_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC(uint8_t *location, int32_t result = S + A; result &= 0xFF8; result <<= 7; - 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"); + 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"); write32le(location, result | read32le(location)); } /// \brief R_AARCH64_TLSLE_ADD_TPREL_HI12 -static void relocR_AARCH64_TLSLE_ADD_TPREL_HI12(uint8_t *location, uint64_t P, - uint64_t S, int64_t A) { - int32_t result = S + A; +static std::error_code relocR_AARCH64_TLSLE_ADD_TPREL_HI12(uint8_t *location, + uint64_t P, + uint64_t S, + int64_t A) { + int64_t result = S + A; + if (!isUInt<24>(result)) + return make_out_of_range_reloc_error(); result &= 0x0FFF000; result >>= 2; - 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"); + 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"); write32le(location, result | read32le(location)); + return std::error_code(); } /// \brief R_AARCH64_TLSLE_ADD_TPREL_LO12_NC @@ -325,22 +391,76 @@ static void relocR_AARCH64_TLSLE_ADD_TPREL_LO12_NC(uint8_t *location, int32_t result = S + A; result &= 0x0FFF; result <<= 10; - 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"); + 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"); + write32le(location, result | read32le(location)); +} + +/// \brief R_AARCH64_TLSDESC_ADR_PAGE21 - Page(G(GTLSDESC(S+A))) - Page(P) +static std::error_code relocR_AARCH64_TLSDESC_ADR_PAGE21(uint8_t *location, + uint64_t P, uint64_t S, + int64_t A) { + int64_t result = page(S + A) - page(P); + if (!isInt<32>(result)) + return make_out_of_range_reloc_error(); + result = result >> 12; + uint32_t immlo = result & 0x3; + uint32_t immhi = result & 0x1FFFFC; + 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, immlo | immhi | read32le(location)); + return std::error_code(); +} + +/// \brief R_AARCH64_TLSDESC_LD64_LO12_NC - G(GTLSDESC(S+A)) -> S + A +static std::error_code relocR_AARCH64_TLSDESC_LD64_LO12_NC(uint8_t *location, + uint64_t P, + uint64_t S, + int64_t A) { + int32_t result = S + A; + DEBUG(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(); +} + +/// \brief R_AARCH64_TLSDESC_ADD_LO12_NC - G(GTLSDESC(S+A)) -> S + A +static void relocR_AARCH64_TLSDESC_ADD_LO12_NC(uint8_t *location, uint64_t P, + uint64_t S, int64_t A) { + int32_t result = (int32_t)((S + A) & 0xFFF); + result <<= 10; + 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"); write32le(location, result | read32le(location)); } std::error_code AArch64TargetRelocationHandler::applyRelocation( - ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom, + ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom, const Reference &ref) const { uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset; - uint8_t *location = atomContent + ref.offsetInAtom(); - uint64_t targetVAddress = writer.addressOfAtom(ref.target()); - uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom(); + uint8_t *loc = atomContent + ref.offsetInAtom(); + uint64_t target = writer.addressOfAtom(ref.target()); + uint64_t reloc = atom._virtualAddr + ref.offsetInAtom(); + int64_t addend = ref.addend(); if (ref.kindNamespace() != Reference::KindNamespace::ELF) return std::error_code(); @@ -349,92 +469,88 @@ std::error_code AArch64TargetRelocationHandler::applyRelocation( case R_AARCH64_NONE: break; case R_AARCH64_ABS64: - relocR_AARCH64_ABS64(location, relocVAddress, targetVAddress, ref.addend()); - break; - case R_AARCH64_PREL32: - relocR_AARCH64_PREL32(location, relocVAddress, targetVAddress, - ref.addend()); + relocR_AARCH64_ABS64(loc, reloc, target, addend); break; case R_AARCH64_ABS32: - return relocR_AARCH64_ABS32(location, relocVAddress, targetVAddress, - ref.addend()); - // Runtime only relocations. Ignore here. - case R_AARCH64_RELATIVE: - case R_AARCH64_IRELATIVE: - case R_AARCH64_JUMP_SLOT: - case R_AARCH64_GLOB_DAT: + 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); + case R_AARCH64_PREL16: + return relocR_AARCH64_PREL16(loc, reloc, target, addend); case R_AARCH64_ADR_PREL_PG_HI21: - relocR_AARCH64_ADR_PREL_PG_HI21(location, relocVAddress, targetVAddress, - ref.addend()); - break; + return relocR_AARCH64_ADR_PREL_PG_HI21(loc, reloc, target, addend); case R_AARCH64_ADR_PREL_LO21: - relocR_AARCH64_ADR_PREL_LO21(location, relocVAddress, targetVAddress, - ref.addend()); - break; + return relocR_AARCH64_ADR_PREL_LO21(loc, reloc, target, addend); case R_AARCH64_ADD_ABS_LO12_NC: - relocR_AARCH64_ADD_ABS_LO12_NC(location, relocVAddress, targetVAddress, - ref.addend()); + relocR_AARCH64_ADD_ABS_LO12_NC(loc, reloc, target, addend); break; case R_AARCH64_CALL26: case R_AARCH64_JUMP26: - relocJump26(location, relocVAddress, targetVAddress, ref.addend()); - break; + return relocJump26(loc, reloc, target, addend); case R_AARCH64_CONDBR19: - relocR_AARCH64_CONDBR19(location, relocVAddress, targetVAddress, - ref.addend()); - break; + return relocR_AARCH64_CONDBR19(loc, reloc, target, addend); case R_AARCH64_ADR_GOT_PAGE: - relocR_AARCH64_ADR_GOT_PAGE(location, relocVAddress, targetVAddress, - ref.addend()); - break; + return relocR_AARCH64_ADR_GOT_PAGE(loc, reloc, target, 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(loc, reloc, target, addend); case R_AARCH64_LDST8_ABS_LO12_NC: - relocR_AARCH64_LDST8_ABS_LO12_NC(location, relocVAddress, targetVAddress, - ref.addend()); + relocR_AARCH64_LDST8_ABS_LO12_NC(loc, reloc, target, addend); break; case R_AARCH64_LDST16_ABS_LO12_NC: - relocR_AARCH64_LDST16_ABS_LO12_NC(location, relocVAddress, targetVAddress, - ref.addend()); + relocR_AARCH64_LDST16_ABS_LO12_NC(loc, reloc, target, addend); break; case R_AARCH64_LDST32_ABS_LO12_NC: - relocR_AARCH64_LDST32_ABS_LO12_NC(location, relocVAddress, targetVAddress, - ref.addend()); + relocR_AARCH64_LDST32_ABS_LO12_NC(loc, reloc, target, addend); break; case R_AARCH64_LDST64_ABS_LO12_NC: - relocR_AARCH64_LDST64_ABS_LO12_NC(location, relocVAddress, targetVAddress, - ref.addend()); + relocR_AARCH64_LDST64_ABS_LO12_NC(loc, reloc, target, addend); break; case R_AARCH64_LDST128_ABS_LO12_NC: - relocR_AARCH64_LDST128_ABS_LO12_NC(location, relocVAddress, targetVAddress, - ref.addend()); + relocR_AARCH64_LDST128_ABS_LO12_NC(loc, reloc, target, addend); break; case ADD_AARCH64_GOTRELINDEX: - relocADD_AARCH64_GOTRELINDEX(location, relocVAddress, targetVAddress, - ref.addend()); + relocADD_AARCH64_GOTRELINDEX(loc, reloc, target, addend); break; case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: - relocR_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21(location, relocVAddress, - targetVAddress, ref.addend()); - break; + return relocR_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21(loc, reloc, target, addend); case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: - relocR_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC(location, relocVAddress, - targetVAddress, ref.addend()); + relocR_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC(loc, reloc, target, addend); break; case R_AARCH64_TLSLE_ADD_TPREL_HI12: - relocR_AARCH64_TLSLE_ADD_TPREL_HI12(location, relocVAddress, targetVAddress, - ref.addend()); + case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: { + auto tpoffset = _layout.getTPOffset(); + if (ref.kindValue() == R_AARCH64_TLSLE_ADD_TPREL_HI12) + return relocR_AARCH64_TLSLE_ADD_TPREL_HI12(loc, reloc, target + tpoffset, + addend); + else + relocR_AARCH64_TLSLE_ADD_TPREL_LO12_NC(loc, reloc, target + tpoffset, + addend); + } break; + case R_AARCH64_TLSDESC_ADR_PAGE21: + return relocR_AARCH64_TLSDESC_ADR_PAGE21(loc, reloc, target, addend); + case R_AARCH64_TLSDESC_LD64_LO12_NC: + return relocR_AARCH64_TLSDESC_LD64_LO12_NC(loc, reloc, target, addend); + case R_AARCH64_TLSDESC_ADD_LO12_NC: + relocR_AARCH64_TLSDESC_ADD_LO12_NC(loc, reloc, target, addend); + break; + case R_AARCH64_TLSDESC_CALL: + // Relaxation only to optimize TLS access. Ignore for now. break; - case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: - relocR_AARCH64_TLSLE_ADD_TPREL_LO12_NC(location, relocVAddress, - targetVAddress, ref.addend()); + // Runtime only relocations. Ignore here. + case R_AARCH64_RELATIVE: + case R_AARCH64_IRELATIVE: + case R_AARCH64_JUMP_SLOT: + case R_AARCH64_GLOB_DAT: + case R_AARCH64_TLS_TPREL64: + case R_AARCH64_TLSDESC: break; default: return make_unhandled_reloc_error(); } - return std::error_code(); } |
