diff options
Diffstat (limited to 'lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp')
-rw-r--r-- | lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp | 328 |
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: |