From 209ceed745253cfcf3d05c72b9bdc76b439bc1fb Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Sun, 21 Mar 2021 17:20:07 -0700 Subject: [PATCH] [JITLink][ELF/x86-64] Add Delta32, NegDelta32, NegDelta64 support. These were missing, but are used in eh-frame section support. --- llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h | 36 ++++++---- llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp | 76 +++++++++++++++++++--- 2 files changed, 92 insertions(+), 20 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h b/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h index 2503577..868a535 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h @@ -15,6 +15,8 @@ #include "llvm/ExecutionEngine/JITLink/JITLink.h" +#include + namespace llvm { namespace jitlink { namespace x86_64 { @@ -244,6 +246,17 @@ enum EdgeKind_x86_64 : Edge::Kind { /// only. const char *getEdgeKindName(Edge::Kind K); +/// Returns true if the given uint64_t value is in range for a uint32_t. +inline bool isInRangeForImmU32(uint64_t Value) { + return Value <= std::numeric_limits::max(); +} + +/// Returns true if the given int64_t value is in range for an int32_t. +inline bool isInRangeForImmS32(int64_t Value) { + return (Value >= std::numeric_limits::min() && + Value <= std::numeric_limits::max()); +} + /// Apply fixup expression for edge to block content. inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, char *BlockWorkingMem) { @@ -262,9 +275,10 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, case Pointer32: { uint64_t Value = E.getTarget().getAddress() + E.getAddend(); - if (Value > std::numeric_limits::max()) + if (LLVM_LIKELY(isInRangeForImmU32(Value))) + *(ulittle32_t *)FixupPtr = Value; + else return makeTargetOutOfRangeError(G, B, E); - *(ulittle32_t *)FixupPtr = Value; break; } @@ -275,10 +289,10 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, case PCRel32TLVPLoadRelaxable: { int64_t Value = E.getTarget().getAddress() - (FixupAddress + 4) + E.getAddend(); - if (Value < std::numeric_limits::min() || - Value > std::numeric_limits::max()) + if (LLVM_LIKELY(isInRangeForImmS32(Value))) + *(little32_t *)FixupPtr = Value; + else return makeTargetOutOfRangeError(G, B, E); - *(little32_t *)FixupPtr = Value; break; } @@ -290,10 +304,10 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, case Delta32: { int64_t Value = E.getTarget().getAddress() - FixupAddress + E.getAddend(); - if (Value < std::numeric_limits::min() || - Value > std::numeric_limits::max()) + if (LLVM_LIKELY(isInRangeForImmS32(Value))) + *(little32_t *)FixupPtr = Value; + else return makeTargetOutOfRangeError(G, B, E); - *(little32_t *)FixupPtr = Value; break; } @@ -305,10 +319,10 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, case NegDelta32: { int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend(); - if (Value < std::numeric_limits::min() || - Value > std::numeric_limits::max()) + if (LLVM_LIKELY(isInRangeForImmS32(Value))) + *(little32_t *)FixupPtr = Value; + else return makeTargetOutOfRangeError(G, B, E); - *(little32_t *)FixupPtr = Value; break; } diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp index 50d30c7..3532665 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp @@ -12,6 +12,7 @@ #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h" #include "llvm/ExecutionEngine/JITLink/JITLink.h" +#include "llvm/ExecutionEngine/JITLink/x86_64.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Endian.h" @@ -707,10 +708,10 @@ private: case ELFX86RelocationKind::PCRel32: case ELFX86RelocationKind::PCRel32GOTLoad: { int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; - if (Value < std::numeric_limits::min() || - Value > std::numeric_limits::max()) + if (LLVM_LIKELY(x86_64::isInRangeForImmS32(Value))) + *(little32_t *)FixupPtr = Value; + else return makeTargetOutOfRangeError(G, B, E); - *(little32_t *)FixupPtr = Value; break; } case ELFX86RelocationKind::Pointer64: { @@ -718,11 +719,38 @@ private: *(ulittle64_t *)FixupPtr = Value; break; } + case ELFX86RelocationKind::Delta32: { + int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; + if (LLVM_LIKELY(x86_64::isInRangeForImmS32(Value))) + *(little32_t *)FixupPtr = Value; + else + return makeTargetOutOfRangeError(G, B, E); + break; + } case ELFX86RelocationKind::Delta64: { int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; *(little64_t *)FixupPtr = Value; break; } + case ELFX86RelocationKind::NegDelta32: { + int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend(); + if (LLVM_LIKELY(x86_64::isInRangeForImmS32(Value))) + *(little32_t *)FixupPtr = Value; + else + return makeTargetOutOfRangeError(G, B, E); + break; + } + case ELFX86RelocationKind::NegDelta64: { + int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend(); + *(little64_t *)FixupPtr = Value; + break; + } + default: + LLVM_DEBUG({ + dbgs() << "Bad edge: " << getELFX86RelocationKindName(E.getKind()) + << "\n"; + }); + llvm_unreachable("Unsupported relocation"); } return Error::success(); } @@ -780,16 +808,46 @@ void link_ELF_x86_64(std::unique_ptr G, } const char *getELFX86RelocationKindName(Edge::Kind R) { switch (R) { - case PCRel32: - return "PCRel32"; - case Pointer64: - return "Pointer64"; - case PCRel32GOTLoad: - return "PCRel32GOTLoad"; case Branch32: return "Branch32"; case Branch32ToStub: return "Branch32ToStub"; + case Pointer32: + return "Pointer32"; + case Pointer64: + return "Pointer64"; + case Pointer64Anon: + return "Pointer64Anon"; + case PCRel32: + return "PCRel32"; + case PCRel32Minus1: + return "PCRel32Minus1"; + case PCRel32Minus2: + return "PCRel32Minus2"; + case PCRel32Minus4: + return "PCRel32Minus4"; + case PCRel32Anon: + return "PCRel32Anon"; + case PCRel32Minus1Anon: + return "PCRel32Minus1Anon"; + case PCRel32Minus2Anon: + return "PCRel32Minus2Anon"; + case PCRel32Minus4Anon: + return "PCRel32Minus4Anon"; + case PCRel32GOTLoad: + return "PCRel32GOTLoad"; + case PCRel32GOT: + return "PCRel32GOT"; + case PCRel32TLV: + return "PCRel32TLV"; + case Delta32: + return "Delta32"; + case Delta64: + return "Delta64"; + case NegDelta32: + return "NegDelta32"; + case NegDelta64: + return "NegDelta64"; } return getGenericEdgeKindName(static_cast(R)); } -- 2.7.4