summaryrefslogtreecommitdiff
path: root/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp')
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp546
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();
}