diff options
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp')
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp | 687 |
1 files changed, 0 insertions, 687 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp deleted file mode 100644 index c55a7a4116e..00000000000 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp +++ /dev/null @@ -1,687 +0,0 @@ -//===- lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp ----------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "MipsLinkingContext.h" -#include "MipsRelocationHandler.h" -#include "MipsTargetLayout.h" -#include "llvm/Support/Format.h" - -using namespace lld; -using namespace elf; -using namespace llvm::ELF; -using namespace llvm::support; - -namespace { -enum class CrossJumpMode { - None, // Not a jump or non-isa-cross jump - ToRegular, // cross isa jump to regular symbol - ToMicro, // cross isa jump to microMips symbol - ToMicroJalr// cross isa jump to microMips symbol referenced by R_MIPS_JALR -}; - -typedef std::function<std::error_code(int64_t, bool)> OverflowChecker; - -static std::error_code dummyCheck(int64_t, bool) { - return std::error_code(); -} - -template <int BITS> static std::error_code signedCheck(int64_t res, bool) { - if (llvm::isInt<BITS>(res)) - return std::error_code(); - return make_out_of_range_reloc_error(); -} - -template <int BITS> -static std::error_code gpDispCheck(int64_t res, bool isGpDisp) { - if (!isGpDisp || llvm::isInt<BITS>(res)) - return std::error_code(); - return make_out_of_range_reloc_error(); -} - -struct MipsRelocationParams { - uint8_t _size; // Relocations's size in bytes - uint64_t _mask; // Read/write mask of relocation - uint8_t _shift; // Relocation's addendum left shift size - bool _shuffle; // Relocation's addendum/result needs to be shuffled - OverflowChecker _overflow; // Check the relocation result -}; - -template <class ELFT> class RelocationHandler : public TargetRelocationHandler { -public: - RelocationHandler(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout) - : _ctx(ctx), _targetLayout(layout) {} - - std::error_code applyRelocation(ELFWriter &writer, - llvm::FileOutputBuffer &buf, - const AtomLayout &atom, - const Reference &ref) const override; - -private: - MipsLinkingContext &_ctx; - MipsTargetLayout<ELFT> &_targetLayout; -}; -} - -static MipsRelocationParams getRelocationParams(uint32_t rType) { - switch (rType) { - case R_MIPS_NONE: - return {4, 0x0, 0, false, dummyCheck}; - case R_MIPS_64: - case R_MIPS_SUB: - return {8, 0xffffffffffffffffull, 0, false, dummyCheck}; - case R_MICROMIPS_SUB: - return {8, 0xffffffffffffffffull, 0, true, dummyCheck}; - case R_MIPS_32: - case R_MIPS_GPREL32: - case R_MIPS_REL32: - case R_MIPS_PC32: - case R_MIPS_EH: - return {4, 0xffffffff, 0, false, dummyCheck}; - case LLD_R_MIPS_32_HI16: - return {4, 0xffff0000, 0, false, dummyCheck}; - case LLD_R_MIPS_64_HI16: - return {8, 0xffffffffffff0000ull, 0, false, dummyCheck}; - case R_MIPS_26: - case LLD_R_MIPS_GLOBAL_26: - return {4, 0x3ffffff, 2, false, dummyCheck}; - case R_MIPS_PC16: - return {4, 0xffff, 2, false, signedCheck<18>}; - case R_MIPS_PC18_S3: - return {4, 0x3ffff, 3, false, signedCheck<21>}; - case R_MIPS_PC19_S2: - return {4, 0x7ffff, 2, false, signedCheck<21>}; - case R_MIPS_PC21_S2: - return {4, 0x1fffff, 2, false, signedCheck<23>}; - case R_MIPS_PC26_S2: - return {4, 0x3ffffff, 2, false, signedCheck<28>}; - case R_MIPS_HI16: - return {4, 0xffff, 0, false, gpDispCheck<16>}; - case R_MIPS_LO16: - case R_MIPS_HIGHER: - case R_MIPS_HIGHEST: - return {4, 0xffff, 0, false, dummyCheck}; - case R_MIPS_16: - case R_MIPS_PCHI16: - case R_MIPS_PCLO16: - case R_MIPS_GOT16: - case R_MIPS_CALL16: - case R_MIPS_GOT_DISP: - case R_MIPS_GOT_PAGE: - case R_MIPS_GOT_OFST: - case R_MIPS_GPREL16: - case R_MIPS_TLS_GD: - case R_MIPS_TLS_LDM: - case R_MIPS_TLS_GOTTPREL: - case R_MIPS_LITERAL: - return {4, 0xffff, 0, false, signedCheck<16>}; - case R_MIPS_GOT_HI16: - case R_MIPS_GOT_LO16: - case R_MIPS_CALL_HI16: - case R_MIPS_CALL_LO16: - case R_MIPS_TLS_DTPREL_HI16: - case R_MIPS_TLS_DTPREL_LO16: - case R_MIPS_TLS_TPREL_HI16: - case R_MIPS_TLS_TPREL_LO16: - return {4, 0xffff, 0, false, dummyCheck}; - case R_MICROMIPS_GPREL16: - case R_MICROMIPS_LITERAL: - return {4, 0xffff, 0, true, signedCheck<16>}; - case R_MICROMIPS_GPREL7_S2: - return {4, 0x7f, 2, false, signedCheck<9>}; - case R_MICROMIPS_GOT_HI16: - case R_MICROMIPS_GOT_LO16: - case R_MICROMIPS_CALL_HI16: - case R_MICROMIPS_CALL_LO16: - case R_MICROMIPS_TLS_DTPREL_HI16: - case R_MICROMIPS_TLS_DTPREL_LO16: - case R_MICROMIPS_TLS_TPREL_HI16: - case R_MICROMIPS_TLS_TPREL_LO16: - return {4, 0xffff, 0, true, dummyCheck}; - case R_MICROMIPS_26_S1: - case LLD_R_MICROMIPS_GLOBAL_26_S1: - return {4, 0x3ffffff, 1, true, dummyCheck}; - case R_MICROMIPS_HI16: - return {4, 0xffff, 0, true, gpDispCheck<16>}; - case R_MICROMIPS_LO16: - case R_MICROMIPS_HI0_LO16: - case R_MICROMIPS_HIGHER: - case R_MICROMIPS_HIGHEST: - return {4, 0xffff, 0, true, dummyCheck}; - case R_MICROMIPS_PC16_S1: - return {4, 0xffff, 1, true, signedCheck<17>}; - case R_MICROMIPS_PC7_S1: - return {4, 0x7f, 1, false, signedCheck<8>}; - case R_MICROMIPS_PC10_S1: - return {4, 0x3ff, 1, false, signedCheck<11>}; - case R_MICROMIPS_PC23_S2: - return {4, 0x7fffff, 2, true, signedCheck<25>}; - case R_MICROMIPS_PC18_S3: - return {4, 0x3ffff, 3, true, signedCheck<21>}; - case R_MICROMIPS_PC19_S2: - return {4, 0x7ffff, 2, true, signedCheck<21>}; - case R_MICROMIPS_PC21_S2: - return {4, 0x1fffff, 2, true, signedCheck<23>}; - case R_MICROMIPS_PC26_S2: - return {4, 0x3ffffff, 2, true, signedCheck<28>}; - case R_MICROMIPS_GOT16: - case R_MICROMIPS_CALL16: - case R_MICROMIPS_TLS_GD: - case R_MICROMIPS_TLS_LDM: - case R_MICROMIPS_TLS_GOTTPREL: - case R_MICROMIPS_GOT_DISP: - case R_MICROMIPS_GOT_PAGE: - case R_MICROMIPS_GOT_OFST: - return {4, 0xffff, 0, true, signedCheck<16>}; - case R_MIPS_JALR: - return {4, 0xffffffff, 0, false, dummyCheck}; - case R_MICROMIPS_JALR: - return {4, 0x0, 0, true, dummyCheck}; - case R_MIPS_JUMP_SLOT: - case R_MIPS_COPY: - case R_MIPS_TLS_DTPMOD32: - case R_MIPS_TLS_DTPREL32: - case R_MIPS_TLS_TPREL32: - return {4, 0xffffffff, 0, false, dummyCheck}; - case R_MIPS_TLS_DTPMOD64: - case R_MIPS_TLS_DTPREL64: - case R_MIPS_TLS_TPREL64: - return {8, 0xffffffffffffffffull, 0, false, dummyCheck}; - case LLD_R_MIPS_GLOBAL_GOT: - case LLD_R_MIPS_STO_PLT: - // Do nothing. - return {4, 0x0, 0, false, dummyCheck}; - default: - llvm_unreachable("Unknown relocation"); - } -} - -template <class ELFT> -static uint64_t relocRead(const MipsRelocationParams ¶ms, - const uint8_t *loc); - -static int64_t getHi16(int64_t value) { - return ((value + 0x8000) >> 16) & 0xffff; -} - -static int64_t getHigher16(int64_t value) { - return ((value + 0x80008000ull) >> 32) & 0xffff; -} - -static int64_t getHighest16(int64_t value) { - return ((value + 0x800080008000ull) >> 48) & 0xffff; -} - -static int64_t maskLow16(int64_t value) { - return (value + 0x8000) & ~0xffff; -} - -/// R_MIPS_GOT_OFST, R_MICROMIPS_GOT_OFST -/// rel16 offset of (S+A) from the page pointer (verify) -static int32_t relocGOTOfst(uint64_t S, int64_t A) { - int64_t page = maskLow16(S + A); - return S + A - page; -} - -/// \brief R_MIPS_PC16 -/// local/external: (S + A - P) >> 2 -static ErrorOr<int64_t> relocPc16(uint64_t P, uint64_t S, int64_t A) { - if ((S + A) & 3) - return make_unaligned_range_reloc_error(); - return S + A - P; -} - -/// \brief R_MIPS_PC18_S3, R_MICROMIPS_PC18_S3 -/// local/external: (S + A - P) >> 3 (P with cleared 3 less significant bits) -static ErrorOr<int64_t> relocPc18(uint64_t P, uint64_t S, int64_t A) { - if ((S + A) & 6) - return make_unaligned_range_reloc_error(); - return S + A - ((P | 7) ^ 7); -} - -/// \brief R_MIPS_PC19_S2, R_MICROMIPS_PC19_S2, R_MIPS_PC21_S2, -/// R_MICROMIPS_PC21_S2, R_MIPS_PC26_S2, R_MICROMIPS_PC26_S2 -/// local/external: (S + A - P) >> 2 -static ErrorOr<int64_t> relocPcS2(uint64_t P, uint64_t S, int64_t A) { - if ((S + A) & 2) - return make_unaligned_range_reloc_error(); - return S + A - P; -} - -template <class ELFT> -static ErrorOr<int64_t> relocJalr(uint64_t P, uint64_t S, bool isCrossJump, - uint8_t *location) { - uint64_t ins = relocRead<ELFT>(getRelocationParams(R_MIPS_JALR), location); - if (isCrossJump) - return ins; - int64_t off = S - P - 4; - if (!llvm::isInt<18>(off)) - return ins; - if (ins == 0x0320f809) // jalr t9 - return 0x04110000 | ((off >> 2) & 0xffff); - if (ins == 0x03200008) // jr t9 - return 0x10000000 | ((off >> 2) & 0xffff); - return ins; -} - -static int64_t relocRel32(uint64_t S, int64_t A, bool isLocal) { - // If output relocation format is REL and the input one is RELA, the only - // method to transfer the relocation addend from the input relocation - // to the output dynamic relocation is to save this addend to the location - // modified by R_MIPS_REL32. - return isLocal ? S + A : A; -} - -static std::error_code adjustJumpOpCode(uint64_t &ins, uint64_t tgt, - CrossJumpMode mode) { - if (mode == CrossJumpMode::None || mode == CrossJumpMode::ToMicroJalr) - return std::error_code(); - - bool toMicro = mode == CrossJumpMode::ToMicro; - uint32_t opNative = toMicro ? 0x03 : 0x3d; - uint32_t opCross = toMicro ? 0x1d : 0x3c; - - if ((tgt & 1) != toMicro) - return make_dynamic_error_code("Incorrect bit 0 for the jalx target"); - - if (tgt & 2) - return make_dynamic_error_code(Twine("The jalx target 0x") + - Twine::utohexstr(tgt) + - " is not word-aligned"); - uint8_t op = ins >> 26; - if (op != opNative && op != opCross) - return make_dynamic_error_code(Twine("Unsupported jump opcode (0x") + - Twine::utohexstr(op) + - ") for ISA modes cross call"); - - ins = (ins & ~(0x3f << 26)) | (opCross << 26); - return std::error_code(); -} - -static bool isMicroMipsAtom(const Atom *a) { - if (const auto *da = dyn_cast<DefinedAtom>(a)) - return da->codeModel() == DefinedAtom::codeMipsMicro || - da->codeModel() == DefinedAtom::codeMipsMicroPIC; - return false; -} - -static CrossJumpMode getCrossJumpMode(const Reference &ref) { - if (!isa<DefinedAtom>(ref.target())) - return CrossJumpMode::None; - bool isTgtMicro = isMicroMipsAtom(ref.target()); - switch (ref.kindValue()) { - case R_MIPS_JALR: - return isTgtMicro ? CrossJumpMode::ToMicroJalr : CrossJumpMode::None; - case R_MIPS_26: - case LLD_R_MIPS_GLOBAL_26: - return isTgtMicro ? CrossJumpMode::ToMicro : CrossJumpMode::None; - case R_MICROMIPS_26_S1: - case LLD_R_MICROMIPS_GLOBAL_26_S1: - return isTgtMicro ? CrossJumpMode::None : CrossJumpMode::ToRegular; - default: - return CrossJumpMode::None; - } -} - -template <class ELFT> -static ErrorOr<int64_t> -calculateRelocation(Reference::KindValue kind, Reference::Addend addend, - uint64_t tgtAddr, uint64_t relAddr, uint64_t gpAddr, - uint8_t *location, bool isGP, bool isCrossJump, - bool isDynamic, bool isLocalSym) { - switch (kind) { - case R_MIPS_NONE: - return 0; - case R_MIPS_16: - case R_MIPS_32: - case R_MIPS_64: - case R_MIPS_TLS_DTPREL_LO16: - case R_MIPS_TLS_TPREL_LO16: - case R_MICROMIPS_TLS_DTPREL_LO16: - case R_MICROMIPS_TLS_TPREL_LO16: - case LLD_R_MIPS_GLOBAL_26: - case LLD_R_MICROMIPS_GLOBAL_26_S1: - return tgtAddr + addend; - case R_MIPS_SUB: - case R_MICROMIPS_SUB: - return tgtAddr - addend; - case R_MIPS_26: - return tgtAddr + (addend | (relAddr & 0xf0000000)); - case R_MICROMIPS_26_S1: - return tgtAddr + (addend | (relAddr & 0xf8000000)); - case R_MIPS_HI16: - case R_MICROMIPS_HI16: - return getHi16(tgtAddr + addend - (isGP ? relAddr : 0)); - case R_MIPS_PCHI16: - return getHi16(tgtAddr + addend - relAddr); - case R_MIPS_LO16: - return tgtAddr + addend - (isGP ? relAddr - 4 : 0); - case R_MICROMIPS_LO16: - case R_MICROMIPS_HI0_LO16: - return tgtAddr + addend - (isGP ? relAddr - 3 : 0); - case R_MIPS_GOT_HI16: - case R_MIPS_CALL_HI16: - case R_MICROMIPS_GOT_HI16: - case R_MICROMIPS_CALL_HI16: - return getHi16(tgtAddr - gpAddr); - case R_MIPS_HIGHER: - case R_MICROMIPS_HIGHER: - return getHigher16(tgtAddr + addend); - case R_MIPS_HIGHEST: - case R_MICROMIPS_HIGHEST: - return getHighest16(tgtAddr + addend); - case R_MIPS_GOT_LO16: - case R_MIPS_CALL_LO16: - case R_MICROMIPS_GOT_LO16: - case R_MICROMIPS_CALL_LO16: - case R_MIPS_EH: - case R_MIPS_GOT16: - case R_MIPS_CALL16: - case R_MIPS_GOT_DISP: - case R_MIPS_GOT_PAGE: - case R_MICROMIPS_GOT_DISP: - case R_MICROMIPS_GOT_PAGE: - case R_MICROMIPS_GOT16: - case R_MICROMIPS_CALL16: - case R_MIPS_TLS_GD: - case R_MIPS_TLS_LDM: - case R_MIPS_TLS_GOTTPREL: - case R_MICROMIPS_TLS_GD: - case R_MICROMIPS_TLS_LDM: - case R_MICROMIPS_TLS_GOTTPREL: - return tgtAddr - gpAddr; - case R_MIPS_GPREL16: - case R_MIPS_GPREL32: - case R_MIPS_LITERAL: - case R_MICROMIPS_GPREL16: - case R_MICROMIPS_GPREL7_S2: - case R_MICROMIPS_LITERAL: - return tgtAddr + addend - gpAddr; - case R_MIPS_GOT_OFST: - case R_MICROMIPS_GOT_OFST: - return relocGOTOfst(tgtAddr, addend); - case R_MIPS_PC16: - return relocPc16(relAddr, tgtAddr, addend); - case R_MIPS_PC18_S3: - case R_MICROMIPS_PC18_S3: - return relocPc18(relAddr, tgtAddr, addend); - case R_MIPS_PC19_S2: - case R_MICROMIPS_PC19_S2: - case R_MIPS_PC21_S2: - case R_MICROMIPS_PC21_S2: - case R_MIPS_PC26_S2: - case R_MICROMIPS_PC26_S2: - return relocPcS2(relAddr, tgtAddr, addend); - case R_MIPS_PC32: - case R_MIPS_PCLO16: - case R_MICROMIPS_PC7_S1: - case R_MICROMIPS_PC10_S1: - case R_MICROMIPS_PC16_S1: - case R_MICROMIPS_PC23_S2: - return tgtAddr + addend - relAddr; - case R_MIPS_TLS_DTPREL_HI16: - case R_MIPS_TLS_TPREL_HI16: - case R_MICROMIPS_TLS_DTPREL_HI16: - case R_MICROMIPS_TLS_TPREL_HI16: - return getHi16(tgtAddr + addend); - case R_MIPS_JALR: - return relocJalr<ELFT>(relAddr, tgtAddr, isCrossJump, location); - case R_MICROMIPS_JALR: - // We do not do JALR optimization now. - return 0; - case R_MIPS_REL32: - return relocRel32(tgtAddr, addend, isLocalSym); - case R_MIPS_JUMP_SLOT: - case R_MIPS_COPY: - // Ignore runtime relocations. - return 0; - case R_MIPS_TLS_DTPMOD32: - case R_MIPS_TLS_DTPMOD64: - return isDynamic ? 0 : 1; - case R_MIPS_TLS_DTPREL32: - case R_MIPS_TLS_DTPREL64: - return isDynamic ? 0 : tgtAddr + addend - 0x8000; - case R_MIPS_TLS_TPREL32: - case R_MIPS_TLS_TPREL64: - return isDynamic ? 0 : tgtAddr + addend - 0x7000; - case LLD_R_MIPS_32_HI16: - case LLD_R_MIPS_64_HI16: - return maskLow16(tgtAddr + addend); - case LLD_R_MIPS_STO_PLT: - case LLD_R_MIPS_GLOBAL_GOT: - // Do nothing. - return 0; - default: - return make_unhandled_reloc_error(); - } -} - -template <class ELFT> -static uint64_t relocRead(const MipsRelocationParams ¶ms, - const uint8_t *loc) { - assert((params._size == 4 || params._size == 8) && "Unexpected size"); - uint64_t data = 0; - memcpy(&data, loc, params._size); - if (params._shuffle) { - using namespace endian; - auto p = reinterpret_cast<const uint8_t *>(&data); - uint32_t a = readNext<uint16_t, ELFT::TargetEndianness, unaligned>(p); - uint32_t b = read<uint16_t, ELFT::TargetEndianness, unaligned>(p); - write<uint32_t, ELFT::TargetEndianness, unaligned>(&data, a << 16 | b); - } - switch (params._size) { - case 4: - return endian::read<uint32_t, ELFT::TargetEndianness, unaligned>(&data); - case 8: - return endian::read<uint64_t, ELFT::TargetEndianness, unaligned>(&data); - default: - llvm_unreachable("Unexpected size"); - } -} - -template <class ELFT> -static void relocWrite(uint64_t data, const MipsRelocationParams ¶ms, - uint8_t *loc) { - switch (params._size) { - case 4: - endian::write<uint32_t, ELFT::TargetEndianness, unaligned>(loc, data); - break; - case 8: - endian::write<uint64_t, ELFT::TargetEndianness, unaligned>(loc, data); - break; - default: - llvm_unreachable("Unexpected size"); - } - if (params._shuffle) { - uint32_t v = endian::read<uint32_t, ELFT::TargetEndianness, unaligned>(loc); - uint16_t a = v >> 16; - uint16_t b = v & 0xffff; - endian::write<uint16_t, ELFT::TargetEndianness, unaligned>(loc, a); - endian::write<uint16_t, ELFT::TargetEndianness, unaligned>(loc + 2, b); - } -} - -static uint32_t getRelKind(const Reference &ref, size_t num) { - if (num == 0) - return ref.kindValue(); - if (num > 2) - return R_MIPS_NONE; - return (ref.tag() >> (8 * (num - 1))) & 0xff; -} - -static uint8_t getRelShift(Reference::KindValue kind, - const MipsRelocationParams ¶ms, - bool isCrossJump) { - uint8_t shift = params._shift; - if (isCrossJump && - (kind == R_MICROMIPS_26_S1 || kind == LLD_R_MICROMIPS_GLOBAL_26_S1)) - return 2; - return shift; -} - -static bool isLocalTarget(const Atom *a) { - if (auto *da = dyn_cast<DefinedAtom>(a)) - return da->scope() == Atom::scopeTranslationUnit; - return false; -} - -template <class ELFT> -std::error_code RelocationHandler<ELFT>::applyRelocation( - ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom, - const Reference &ref) const { - if (ref.kindNamespace() != Reference::KindNamespace::ELF) - return std::error_code(); - assert(ref.kindArch() == Reference::KindArch::Mips); - - uint64_t gpAddr = _targetLayout.getGPAddr(); - bool isGpDisp = ref.target()->name() == "_gp_disp"; - bool isLocalSym = isLocalTarget(ref.target()); - - uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset; - uint8_t *location = atomContent + ref.offsetInAtom(); - uint64_t tgtAddr = writer.addressOfAtom(ref.target()); - uint64_t relAddr = atom._virtualAddr + ref.offsetInAtom(); - - if (isMicroMipsAtom(ref.target())) - tgtAddr |= 1; - - CrossJumpMode jumpMode = getCrossJumpMode(ref); - bool isCrossJump = jumpMode != CrossJumpMode::None; - - uint64_t sym = tgtAddr; - ErrorOr<int64_t> res = ref.addend(); - Reference::KindValue lastRel = R_MIPS_NONE; - - for (size_t relNum = 0; relNum < 3; ++relNum) { - Reference::KindValue kind = getRelKind(ref, relNum); - if (kind == R_MIPS_NONE) - break; - auto params = getRelocationParams(kind); - res = calculateRelocation<ELFT>(kind, *res, sym, relAddr, gpAddr, location, - isGpDisp, isCrossJump, _ctx.isDynamic(), - isLocalSym); - if (auto ec = res.getError()) - return ec; - // Check result for the last relocation only. - if (getRelKind(ref, relNum + 1) == R_MIPS_NONE) { - if (auto ec = params._overflow(*res, isGpDisp)) - return ec; - } - res = *res >> getRelShift(kind, params, isCrossJump); - // FIXME (simon): Handle r_ssym value. - sym = 0; - isGpDisp = false; - isCrossJump = false; - lastRel = kind; - } - - auto params = getRelocationParams(lastRel); - uint64_t ins = relocRead<ELFT>(params, location); - if (auto ec = adjustJumpOpCode(ins, tgtAddr, jumpMode)) - return ec; - - ins = (ins & ~params._mask) | (*res & params._mask); - relocWrite<ELFT>(ins, params, location); - - return std::error_code(); -} - -namespace lld { -namespace elf { - -template <> -std::unique_ptr<TargetRelocationHandler> -createMipsRelocationHandler<ELF32BE>(MipsLinkingContext &ctx, - MipsTargetLayout<ELF32BE> &layout) { - return llvm::make_unique<RelocationHandler<ELF32BE>>(ctx, layout); -} - -template <> -std::unique_ptr<TargetRelocationHandler> -createMipsRelocationHandler<ELF32LE>(MipsLinkingContext &ctx, - MipsTargetLayout<ELF32LE> &layout) { - return llvm::make_unique<RelocationHandler<ELF32LE>>(ctx, layout); -} - -template <> -std::unique_ptr<TargetRelocationHandler> -createMipsRelocationHandler<ELF64BE>(MipsLinkingContext &ctx, - MipsTargetLayout<ELF64BE> &layout) { - return llvm::make_unique<RelocationHandler<ELF64BE>>(ctx, layout); -} - -template <> -std::unique_ptr<TargetRelocationHandler> -createMipsRelocationHandler<ELF64LE>(MipsLinkingContext &ctx, - MipsTargetLayout<ELF64LE> &layout) { - return llvm::make_unique<RelocationHandler<ELF64LE>>(ctx, layout); -} - -template <class ELFT> -Reference::Addend readMipsRelocAddend(Reference::KindValue kind, - const uint8_t *content) { - auto params = getRelocationParams(kind); - uint64_t ins = relocRead<ELFT>(params, content); - int64_t res = (ins & params._mask) << params._shift; - switch (kind) { - case R_MIPS_GPREL16: - case R_MICROMIPS_GPREL16: - case R_MIPS_PCLO16: - case R_MIPS_LITERAL: - case R_MICROMIPS_LITERAL: - return llvm::SignExtend32<16>(res); - case R_MIPS_PC16: - return llvm::SignExtend32<18>(res); - case R_MICROMIPS_GPREL7_S2: - return llvm::SignExtend32<9>(res); - case R_MICROMIPS_PC7_S1: - return llvm::SignExtend32<8>(res); - case R_MICROMIPS_PC10_S1: - return llvm::SignExtend32<11>(res); - case R_MIPS_16: - return llvm::SignExtend32<16>(res); - case R_MICROMIPS_PC16_S1: - return llvm::SignExtend32<17>(res); - case R_MIPS_PC18_S3: - case R_MIPS_PC19_S2: - case R_MICROMIPS_PC18_S3: - case R_MICROMIPS_PC19_S2: - return llvm::SignExtend32<21>(res); - case R_MIPS_PC21_S2: - case R_MICROMIPS_PC21_S2: - return llvm::SignExtend32<23>(res); - case R_MICROMIPS_PC23_S2: - return llvm::SignExtend32<25>(res); - case R_MICROMIPS_26_S1: - return llvm::SignExtend32<27>(res); - case R_MIPS_26: - case R_MIPS_PC26_S2: - case R_MICROMIPS_PC26_S2: - return llvm::SignExtend32<28>(res); - default: - // Nothing to do - break; - } - return res; -} - -template -Reference::Addend readMipsRelocAddend<ELF32BE>(Reference::KindValue kind, - const uint8_t *content); -template -Reference::Addend readMipsRelocAddend<ELF32LE>(Reference::KindValue kind, - const uint8_t *content); -template -Reference::Addend readMipsRelocAddend<ELF64BE>(Reference::KindValue kind, - const uint8_t *content); -template -Reference::Addend readMipsRelocAddend<ELF64LE>(Reference::KindValue kind, - const uint8_t *content); - -} // elf -} // lld |