summaryrefslogtreecommitdiff
path: root/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp')
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp328
1 files changed, 154 insertions, 174 deletions
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp b/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
index 21967d356a311..0a201b32b5f10 100644
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
+++ b/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
@@ -7,10 +7,10 @@
//
//===----------------------------------------------------------------------===//
+#include "HexagonEncodings.h"
#include "HexagonLinkingContext.h"
-#include "HexagonRelocationFunctions.h"
-#include "HexagonTargetHandler.h"
#include "HexagonRelocationHandler.h"
+#include "HexagonTargetHandler.h"
#include "llvm/Support/Endian.h"
using namespace lld;
@@ -18,263 +18,250 @@ using namespace lld::elf;
using namespace llvm::ELF;
using namespace llvm::support::endian;
-#define APPLY_RELOC(result) \
- write32le(location, result | read32le(location));
+// Scatter val's bits as specified by the mask. Example:
+//
+// Val: 0bABCDEFG
+// Mask: 0b10111100001011
+// Output: 0b00ABCD0000E0FG
+static uint32_t scatterBits(uint32_t val, uint32_t mask) {
+ uint32_t result = 0;
+ size_t off = 0;
+ for (size_t bit = 0; bit < 32; ++bit) {
+ if ((mask >> bit) & 1) {
+ uint32_t valBit = (val >> off) & 1;
+ result |= valBit << bit;
+ ++off;
+ }
+ }
+ return result;
+}
-static int relocBNPCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A,
- int32_t nBits) {
- int32_t result = (uint32_t)(((S + A) - P) >> 2);
+static void relocBNPCREL(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A,
+ int32_t nBits) {
+ int32_t result = (S + A - P) >> 2;
int32_t range = 1 << nBits;
if (result < range && result > -range) {
- result = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
- return 1;
}
/// \brief Word32_LO: 0x00c03fff : (S + A) : Truncate
-static int relocLO16(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
- uint32_t result = (uint32_t)(S + A);
- result = lld::scatterBits<int32_t>(result, 0x00c03fff);
- APPLY_RELOC(result);
- return 0;
+static void relocLO16(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A) {
+ uint32_t result = S + A;
+ result = scatterBits(result, 0x00c03fff);
+ write32le(loc, result | read32le(loc));
}
/// \brief Word32_LO: 0x00c03fff : (S + A) >> 16 : Truncate
-static int relocHI16(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
- uint32_t result = (uint32_t)((S + A) >> 16);
- result = lld::scatterBits<int32_t>(result, 0x00c03fff);
- APPLY_RELOC(result);
- return 0;
+static void relocHI16(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A) {
+ uint32_t result = (S + A) >> 16;
+ result = scatterBits(result, 0x00c03fff);
+ write32le(loc, result | read32le(loc));
}
/// \brief Word32: 0xffffffff : (S + A) : Truncate
-static int reloc32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
- uint32_t result = (uint32_t)(S + A);
- APPLY_RELOC(result);
- return 0;
+static void reloc32(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A) {
+ uint32_t result = S + A;
+ write32le(loc, result | read32le(loc));
}
-static int reloc32_6_X(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
- int64_t result = ((S + A) >> 6);
- int64_t range = ((int64_t)1) << 32;
+static void reloc32_6_X(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A) {
+ int64_t result = (S + A) >> 6;
+ int64_t range = int64_t(1) << 32;
if (result > range)
- return 1;
- result = lld::scatterBits<int32_t>(result, 0xfff3fff);
- APPLY_RELOC(result);
- return 0;
+ result = scatterBits(result, 0xfff3fff);
+ write32le(loc, result | read32le(loc));
}
// R_HEX_B32_PCREL_X
-static int relocHexB32PCRELX(uint8_t *location, uint64_t P, uint64_t S,
- uint64_t A) {
- int64_t result = ((S + A - P) >> 6);
- result = lld::scatterBits<int32_t>(result, 0xfff3fff);
- APPLY_RELOC(result);
- return 0;
+static void relocHexB32PCRELX(uint8_t *loc, uint64_t P, uint64_t S,
+ uint64_t A) {
+ int64_t result = (S + A - P) >> 6;
+ result = scatterBits(result, 0xfff3fff);
+ write32le(loc, result | read32le(loc));
}
// R_HEX_BN_PCREL_X
-static int relocHexBNPCRELX(uint8_t *location, uint64_t P, uint64_t S,
- uint64_t A, int nbits) {
- int32_t result = ((S + A - P) & 0x3f);
+static void relocHexBNPCRELX(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A,
+ int nbits) {
+ int32_t result = (S + A - P) & 0x3f;
int32_t range = 1 << nbits;
if (result < range && result > -range) {
- result = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
- return 1;
}
// R_HEX_6_PCREL_X
-static int relocHex6PCRELX(uint8_t *location, uint64_t P, uint64_t S,
- uint64_t A) {
- int32_t result = (S + A - P);
- result = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+static void relocHex6PCRELX(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A) {
+ int32_t result = S + A - P;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
// R_HEX_N_X : Word32_U6 : (S + A) : Unsigned Truncate
-static int relocHex_N_X(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
- uint32_t result = (S + A);
- result = lld::scatterBits<uint32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+static void relocHex_N_X(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A) {
+ uint32_t result = S + A;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
-// GP REL relocations
-static int relocHexGPRELN(uint8_t *location, uint64_t P, uint64_t S, uint64_t A,
- uint64_t GP, int nShiftBits) {
- int32_t result = (int64_t)((S + A - GP) >> nShiftBits);
+// GP REL relocs
+static void relocHexGPRELN(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A,
+ uint64_t GP, int nShiftBits) {
+ int32_t result = (S + A - GP) >> nShiftBits;
int32_t range = 1L << 16;
if (result <= range) {
- result = lld::scatterBits<uint32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
- return 1;
}
/// \brief Word32_LO: 0x00c03fff : (G) : Truncate
-static int relocHexGOTLO16(uint8_t *location, uint64_t A, uint64_t GOT) {
- int32_t result = (int32_t)(A-GOT);
- result = lld::scatterBits<int32_t>(result, 0x00c03fff);
- APPLY_RELOC(result);
- return 0;
+static void relocHexGOTLO16(uint8_t *loc, uint64_t A, uint64_t GOT) {
+ int32_t result = A - GOT;
+ result = scatterBits(result, 0x00c03fff);
+ write32le(loc, result | read32le(loc));
}
/// \brief Word32_LO: 0x00c03fff : (G) >> 16 : Truncate
-static int relocHexGOTHI16(uint8_t *location, uint64_t A, uint64_t GOT) {
- int32_t result = (int32_t)((A-GOT) >> 16);
- result = lld::scatterBits<int32_t>(result, 0x00c03fff);
- APPLY_RELOC(result);
- return 0;
+static void relocHexGOTHI16(uint8_t *loc, uint64_t A, uint64_t GOT) {
+ int32_t result = (A - GOT) >> 16;
+ result = scatterBits(result, 0x00c03fff);
+ write32le(loc, result | read32le(loc));
}
/// \brief Word32: 0xffffffff : (G) : Truncate
-static int relocHexGOT32(uint8_t *location, uint64_t A, uint64_t GOT) {
- int32_t result = (int32_t)(GOT - A);
- APPLY_RELOC(result);
- return 0;
+static void relocHexGOT32(uint8_t *loc, uint64_t A, uint64_t GOT) {
+ int32_t result = GOT - A;
+ write32le(loc, result | read32le(loc));
}
/// \brief Word32_U16 : (G) : Truncate
-static int relocHexGOT16(uint8_t *location, uint64_t A, uint64_t GOT) {
- int32_t result = (int32_t)(GOT-A);
+static void relocHexGOT16(uint8_t *loc, uint64_t A, uint64_t GOT) {
+ int32_t result = GOT - A;
int32_t range = 1L << 16;
if (result <= range) {
- result = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
- return 1;
}
-static int relocHexGOT32_6_X(uint8_t *location, uint64_t A, uint64_t GOT) {
- int32_t result = (int32_t)((A-GOT) >> 6);
- result = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+static void relocHexGOT32_6_X(uint8_t *loc, uint64_t A, uint64_t GOT) {
+ int32_t result = (A - GOT) >> 6;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
-static int relocHexGOT16_X(uint8_t *location, uint64_t A, uint64_t GOT) {
- int32_t result = (int32_t)(A-GOT);
+static void relocHexGOT16_X(uint8_t *loc, uint64_t A, uint64_t GOT) {
+ int32_t result = A - GOT;
int32_t range = 1L << 6;
if (result <= range) {
- result = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
- return 1;
}
-static int relocHexGOT11_X(uint8_t *location, uint64_t A, uint64_t GOT) {
- uint32_t result = (uint32_t)(A-GOT);
- result = lld::scatterBits<uint32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+static void relocHexGOT11_X(uint8_t *loc, uint64_t A, uint64_t GOT) {
+ uint32_t result = A - GOT;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
-static int relocHexGOTRELSigned(uint8_t *location, uint64_t P, uint64_t S,
- uint64_t A, uint64_t GOT, int shiftBits = 0) {
- int32_t result = (int32_t)((S + A - GOT) >> shiftBits);
- result = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+static void relocHexGOTRELSigned(uint8_t *loc, uint64_t P, uint64_t S,
+ uint64_t A, uint64_t GOT, int shiftBits) {
+ int32_t result = (S + A - GOT) >> shiftBits;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
-static int relocHexGOTRELUnsigned(uint8_t *location, uint64_t P, uint64_t S,
- uint64_t A, uint64_t GOT, int shiftBits = 0) {
- uint32_t result = (uint32_t)((S + A - GOT) >> shiftBits);
- result = lld::scatterBits<uint32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+static void relocHexGOTRELUnsigned(uint8_t *loc, uint64_t P, uint64_t S,
+ uint64_t A, uint64_t GOT) {
+ uint32_t result = S + A - GOT;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
-static int relocHexGOTREL_HILO16(uint8_t *location, uint64_t P, uint64_t S,
- uint64_t A, uint64_t GOT, int shiftBits = 0) {
- int32_t result = (int32_t)((S + A - GOT) >> shiftBits);
- result = lld::scatterBits<int32_t>(result, 0x00c03fff);
- APPLY_RELOC(result);
- return 0;
+static void relocHexGOTREL_HILO16(uint8_t *loc, uint64_t P, uint64_t S,
+ uint64_t A, uint64_t GOT, int shiftBits) {
+ int32_t result = (S + A - GOT) >> shiftBits;
+ result = scatterBits(result, 0x00c03fff);
+ write32le(loc, result | read32le(loc));
}
-static int relocHexGOTREL_32(uint8_t *location, uint64_t P, uint64_t S,
- uint64_t A, uint64_t GOT) {
- int32_t result = (int32_t)(S + A - GOT);
- APPLY_RELOC(result);
- return 0;
+static void relocHexGOTREL_32(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A,
+ uint64_t GOT) {
+ int32_t result = S + A - GOT;
+ write32le(loc, result | read32le(loc));
}
std::error_code HexagonTargetRelocationHandler::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();
if (ref.kindNamespace() != Reference::KindNamespace::ELF)
return std::error_code();
assert(ref.kindArch() == Reference::KindArch::Hexagon);
switch (ref.kindValue()) {
case R_HEX_B22_PCREL:
- relocBNPCREL(location, relocVAddress, targetVAddress, ref.addend(), 21);
+ relocBNPCREL(loc, reloc, target, ref.addend(), 21);
break;
case R_HEX_B15_PCREL:
- relocBNPCREL(location, relocVAddress, targetVAddress, ref.addend(), 14);
+ relocBNPCREL(loc, reloc, target, ref.addend(), 14);
break;
case R_HEX_B9_PCREL:
- relocBNPCREL(location, relocVAddress, targetVAddress, ref.addend(), 8);
+ relocBNPCREL(loc, reloc, target, ref.addend(), 8);
break;
case R_HEX_LO16:
- relocLO16(location, relocVAddress, targetVAddress, ref.addend());
+ relocLO16(loc, reloc, target, ref.addend());
break;
case R_HEX_HI16:
- relocHI16(location, relocVAddress, targetVAddress, ref.addend());
+ relocHI16(loc, reloc, target, ref.addend());
break;
case R_HEX_32:
- reloc32(location, relocVAddress, targetVAddress, ref.addend());
+ reloc32(loc, reloc, target, ref.addend());
break;
case R_HEX_32_6_X:
- reloc32_6_X(location, relocVAddress, targetVAddress, ref.addend());
+ reloc32_6_X(loc, reloc, target, ref.addend());
break;
case R_HEX_B32_PCREL_X:
- relocHexB32PCRELX(location, relocVAddress, targetVAddress, ref.addend());
+ relocHexB32PCRELX(loc, reloc, target, ref.addend());
break;
case R_HEX_B22_PCREL_X:
- relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 21);
+ relocHexBNPCRELX(loc, reloc, target, ref.addend(), 21);
break;
case R_HEX_B15_PCREL_X:
- relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 14);
+ relocHexBNPCRELX(loc, reloc, target, ref.addend(), 14);
break;
case R_HEX_B13_PCREL_X:
- relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 12);
+ relocHexBNPCRELX(loc, reloc, target, ref.addend(), 12);
break;
case R_HEX_B9_PCREL_X:
- relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 8);
+ relocHexBNPCRELX(loc, reloc, target, ref.addend(), 8);
break;
case R_HEX_B7_PCREL_X:
- relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 6);
+ relocHexBNPCRELX(loc, reloc, target, ref.addend(), 6);
break;
case R_HEX_GPREL16_0:
- relocHexGPRELN(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getSDataSection()->virtualAddr(), 0);
+ relocHexGPRELN(loc, reloc, target, ref.addend(),
+ _targetLayout.getSDataSection()->virtualAddr(), 0);
break;
case R_HEX_GPREL16_1:
- relocHexGPRELN(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getSDataSection()->virtualAddr(), 1);
+ relocHexGPRELN(loc, reloc, target, ref.addend(),
+ _targetLayout.getSDataSection()->virtualAddr(), 1);
break;
case R_HEX_GPREL16_2:
- relocHexGPRELN(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getSDataSection()->virtualAddr(), 2);
+ relocHexGPRELN(loc, reloc, target, ref.addend(),
+ _targetLayout.getSDataSection()->virtualAddr(), 2);
break;
case R_HEX_GPREL16_3:
- relocHexGPRELN(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getSDataSection()->virtualAddr(), 3);
+ relocHexGPRELN(loc, reloc, target, ref.addend(),
+ _targetLayout.getSDataSection()->virtualAddr(), 3);
break;
case R_HEX_16_X:
case R_HEX_12_X:
@@ -284,62 +271,55 @@ std::error_code HexagonTargetRelocationHandler::applyRelocation(
case R_HEX_8_X:
case R_HEX_7_X:
case R_HEX_6_X:
- relocHex_N_X(location, relocVAddress, targetVAddress, ref.addend());
+ relocHex_N_X(loc, reloc, target, ref.addend());
break;
case R_HEX_6_PCREL_X:
- relocHex6PCRELX(location, relocVAddress, targetVAddress, ref.addend());
+ relocHex6PCRELX(loc, reloc, target, ref.addend());
break;
case R_HEX_JMP_SLOT:
case R_HEX_GLOB_DAT:
break;
case R_HEX_GOTREL_32:
- relocHexGOTREL_32(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOTREL_32(loc, reloc, target, ref.addend(),
+ _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOTREL_LO16:
- relocHexGOTREL_HILO16(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOTREL_HILO16(loc, reloc, target, ref.addend(),
+ _targetLayout.getGOTSymAddr(), 0);
break;
case R_HEX_GOTREL_HI16:
- relocHexGOTREL_HILO16(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getGOTSymAddr(), 16);
+ relocHexGOTREL_HILO16(loc, reloc, target, ref.addend(),
+ _targetLayout.getGOTSymAddr(), 16);
break;
case R_HEX_GOT_LO16:
- relocHexGOTLO16(location, targetVAddress,
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOTLO16(loc, target, _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOT_HI16:
- relocHexGOTHI16(location, targetVAddress,
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOTHI16(loc, target, _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOT_32:
- relocHexGOT32(location, targetVAddress,
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOT32(loc, target, _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOT_16:
- relocHexGOT16(location, targetVAddress,
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOT16(loc, target, _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOT_32_6_X:
- relocHexGOT32_6_X(location, targetVAddress,
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOT32_6_X(loc, target, _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOT_16_X:
- relocHexGOT16_X(location, targetVAddress,
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOT16_X(loc, target, _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOT_11_X:
- relocHexGOT11_X(location, targetVAddress,
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOT11_X(loc, target, _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOTREL_32_6_X:
- relocHexGOTRELSigned(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getGOTSymAddr(), 6);
+ relocHexGOTRELSigned(loc, reloc, target, ref.addend(),
+ _targetLayout.getGOTSymAddr(), 6);
break;
case R_HEX_GOTREL_16_X:
case R_HEX_GOTREL_11_X:
- relocHexGOTRELUnsigned(location, relocVAddress, targetVAddress,
- ref.addend(), _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOTRELUnsigned(loc, reloc, target, ref.addend(),
+ _targetLayout.getGOTSymAddr());
break;
default: