From e4a4547a394266c1b0c8e464b12ccc0b1cbaf091 Mon Sep 17 00:00:00 2001 From: anoopkg6 Date: Tue, 17 Jun 2025 15:00:13 +0200 Subject: [PATCH 01/14] Add initial llvm-jitlink support for SystemZ. --- .../ExecutionEngine/JITLink/ELF_systemz.h | 39 + .../llvm/ExecutionEngine/JITLink/systemz.h | 1089 +++++++++++++++++ .../ExecutionEngine/JITLink/CMakeLists.txt | 2 + llvm/lib/ExecutionEngine/JITLink/ELF.cpp | 6 + .../ExecutionEngine/JITLink/ELF_systemz.cpp | 437 +++++++ llvm/lib/ExecutionEngine/JITLink/JITLink.cpp | 6 + llvm/lib/ExecutionEngine/JITLink/systemz.cpp | 121 ++ .../JITLink/systemz/ELF_systemz_ehframe.s | 58 + .../JITLink/systemz/ELF_systemz_got.s | 78 ++ .../JITLink/systemz/ELF_systemz_reloc_abs16.s | 35 + .../JITLink/systemz/ELF_systemz_reloc_abs32.s | 32 + .../JITLink/systemz/ELF_systemz_reloc_abs64.s | 28 + .../JITLink/systemz/ELF_systemz_reloc_abs8.s | 38 + .../systemz/ELF_systemz_reloc_call_pic.s | 82 ++ .../systemz/ELF_systemz_reloc_disp12.s | 28 + .../systemz/ELF_systemz_reloc_disp20.s | 31 + .../JITLink/systemz/ELF_systemz_reloc_got.s | 244 ++++ .../systemz/ELF_systemz_reloc_gotrel.s | 68 + .../JITLink/systemz/ELF_systemz_reloc_pc.s | 20 + .../JITLink/systemz/ELF_systemz_reloc_pc16.s | 40 + .../JITLink/systemz/ELF_systemz_reloc_pc32.s | 40 + .../JITLink/systemz/ELF_systemz_reloc_pc64.s | 34 + .../JITLink/systemz/ELF_systemz_reloc_pcdbl.s | 84 ++ .../JITLink/systemz/ELF_systemz_reloc_plt.s | 71 ++ .../systemz/ELF_systemz_reloc_pltdbl.s | 51 + .../JITLink/systemz/lit.local.cfg | 2 + llvm/test/ExecutionEngine/lit.local.cfg | 2 +- 27 files changed, 2765 insertions(+), 1 deletion(-) create mode 100644 llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h create mode 100644 llvm/include/llvm/ExecutionEngine/JITLink/systemz.h create mode 100644 llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp create mode 100644 llvm/lib/ExecutionEngine/JITLink/systemz.cpp create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_ehframe.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_got.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs64.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_got.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_gotrel.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc16.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc32.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc64.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pcdbl.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_plt.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pltdbl.s create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/lit.local.cfg diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h new file mode 100644 index 0000000000000..c78bc7cc1f499 --- /dev/null +++ b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h @@ -0,0 +1,39 @@ +//===--- ELF_systemz.h - JIT link functions for ELF/systemz --*- C++ -*----===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// +// +// jit-link functions for ELF/systemz. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_JITLINK_ELF_SYSTEMZ_H +#define LLVM_EXECUTIONENGINE_JITLINK_ELF_SYSTEMZ_H + +#include "llvm/ExecutionEngine/JITLink/JITLink.h" + +namespace llvm { +namespace jitlink { + +/// Create a LinkGraph from an ELF/systemz relocatable object +/// +/// Note: The graph does not take ownership of the underlying buffer, nor copy +/// its contents. The caller is responsible for ensuring that the object buffer +/// outlives the graph. +Expected> +createLinkGraphFromELFObject_systemz(MemoryBufferRef ObjectBuffer); + +/// jit-link the given object buffer, which must be a ELF systemz relocatable +/// object file. +void link_ELF_systemz(std::unique_ptr G, + std::unique_ptr Ctx); + +} // end namespace jitlink +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_JITLINK_ELF_SYSTEMZ_H diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h new file mode 100644 index 0000000000000..e1498ff820fe6 --- /dev/null +++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h @@ -0,0 +1,1089 @@ +//=== systemz.h - Generic JITLink systemz edge kinds, utilities -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Generic utilities for graphs representing systemz objects. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_JITLINK_SYSTEMZ_H +#define LLVM_EXECUTIONENGINE_JITLINK_SYSTEMZ_H + +#include "TableManager.h" +#include "llvm/ExecutionEngine/JITLink/JITLink.h" + +using namespace llvm::support::endian; + +namespace llvm { +namespace jitlink { +namespace systemz { + +/// Represents systemz fixups and other systemz-specific edge kinds. +enum EdgeKind_systemz : Edge::Kind { + + /// A plain 64-bit pointer value relocation. + /// + /// Fixup expression: + /// Fixup <- Target + Addend : uint64 + /// + Pointer64 = Edge::FirstRelocation, + + /// A plain 32-bit pointer value relocation. + /// + /// Fixup expression: + /// Fixup <- Target + Addend : uint32 + /// + /// Errors: + /// - The target must reside in the low 32-bits of the address space, + /// otherwise an out-of-range error will be returned. + /// + Pointer32, + + /// A plain 20-bit pointer value relocation. + /// + /// Fixup expression: + /// Fixup <- Target + Addend : uint20 + /// + /// Errors: + /// - The target must reside in the mid 20-bits of the address space, + /// otherwise an out-of-range error will be returned. + /// + Pointer20, + + /// A plain 16-bit pointer value relocation. + /// + /// Fixup expression: + /// Fixup <- Target + Addend : uint16 + /// + /// Errors: + /// - The target must reside in the low 16-bits of the address space, + /// otherwise an out-of-range error will be returned. + /// + Pointer16, + + /// A plain 12-bit pointer value relocation. + /// + /// Fixup expression: + /// Fixup <- Target + Addend : uint12 + /// + /// Errors: + /// - The target must reside in the low 12-bits of the address space, + /// otherwise an out-of-range error will be returned. + /// + Pointer12, + + /// A plain 8-bit pointer value relocation. + /// + /// Fixup expression: + /// Fixup <- Target + Addend : uint8 + /// + /// Errors: + /// - The target must reside in the low 8-bits of the address space, + /// otherwise an out-of-range error will be returned. + /// + Pointer8, + + /// A 64-bit delta. + /// + /// Delta from the fixup to the target. + /// + /// Fixup expression: + /// Fixup <- Target - Fixup + Addend : int64 + /// + Delta64, + + /// A 32-bit delta. + /// + /// Delta from the fixup to the target. + /// + /// Fixup expression: + /// Fixup <- Target - Fixup + Addend : int32 + /// + /// Errors: + /// - The result of the fixup expression must fit into an int32, otherwise + /// an out-of-range error will be returned. + /// + Delta32, + + /// A 16-bit delta. + /// + /// Delta from the fixup to the target. + /// + /// Fixup expression: + /// Fixup <- Target - Fixup + Addend : int16 + /// + /// Errors: + /// - The result of the fixup expression must fit into an int16, otherwise + /// an out-of-range error will be returned. + /// + Delta16, + + /// A 32-bit delta. + /// + /// Delta from the fixup to the target. + /// + /// Fixup expression: + /// Fixup <- (Target - Fixup + Addend : int32) >> 1 + /// + /// Errors: + /// - The result of the fixup expression before shifting right by 1 must + /// fit into an int33, otherwise an out-of-range error will be returned. + /// - The result of the fixup expression before shifting right by 1 must + /// be multiple of 2, otherwise an alignment error will be returned. + /// + Delta32dbl, + + /// A 24-bit delta. + /// + /// Delta from the fixup to the target. + /// + /// Fixup expression: + /// Fixup <- (Target - Fixup + Addend : int24) >> 1 + /// + /// Errors: + /// - The result of the fixup expression before shifting right by 1 must + /// fit into an int25, otherwise an out-of-range error will be returned. + /// - The result of the fixup expression before shifting right by 1 must + /// be multiple of 2, otherwise an alignment error will be returned. + /// + Delta24dbl, + + /// A 16-bit delta. + /// + /// Delta from the fixup to the target. + /// + /// Fixup expression: + /// Fixup <- (Target - Fixup + Addend : int16) >> 1 + /// + /// Errors: + /// - The result of the fixup expression before shifting right by 1 must + /// fit into an int17, otherwise an out-of-range error will be returned. + /// - The result of the fixup expression before shifting right by 1 must + /// be multiple of 2, otherwise an alignment error will be returned. + /// + Delta16dbl, + + /// A 12-bit delta. + /// + /// Delta from the fixup to the target. + /// + /// Fixup expression: + /// Fixup <- (Target - Fixup + Addend : int12) >> 1 + /// + /// Errors: + /// - The result of the fixup expression before shifting right by 1 must + /// fit into an int13, otherwise an out-of-range error will be returned. + /// - The result of the fixup expression before shifting right by 1 must + /// be multiple of 2, otherwise an alignment error will be returned. + /// + Delta12dbl, + + /// A 64-bit negative delta. + /// + /// Delta from target back to the fixup. + /// + /// Fixup expression: + /// Fixup <- Fixup - Target + Addend : int64 + /// + NegDelta64, + + /// A 32-bit negative delta. + /// + /// Delta from the target back to the fixup. + /// + /// Fixup expression: + /// Fixup <- Fixup - Target + Addend : int32 + /// + /// Errors: + /// - The result of the fixup expression must fit into an int32, otherwise + /// an out-of-range error will be returned. + NegDelta32, + + /// A 64-bit GOT delta. + /// + /// Delta from the global offset table to the target + /// + /// Fixup expression: + /// Fixup <- Target - GOTSymbol + Addend : int64 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + Delta64FromGOT, + + /// A 32-bit GOT delta. + /// + /// Delta from the global offset table to the target + /// + /// Fixup expression: + /// Fixup <- Target - GOTSymbol + Addend : int32 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int32, otherwise + /// an out-of-range error will be returned. + Delta32FromGOT, + + /// A 16-bit GOT delta. + /// + /// Delta from the global offset table to the target + /// + /// Fixup expression: + /// Fixup <- Target - GOTSymbol + Addend : int16 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int16, otherwise + /// an out-of-range error will be returned. + Delta16FromGOT, + + /// A 32-bit PC-relative branch. + /// + /// Represents a PC-relative call or branch to a target. This can be used to + /// identify, record, and/or patch call sites. + /// + /// Fixup expression: + /// Fixup <- (Target - Fixup + Addend) >> 1 : int32 + /// + /// Errors: + /// - The result of the fixup expression before shifting right by 1 must + /// fit into an int33, otherwise an out-of-range error will be returned. + /// - The result of the fixup expression before shifting right by 1 must + /// be multiple of 2, otherwise an alignment error will be returned. + /// + BranchPCRelPLT32dbl, + + /// A 24-bit PC-relative branch. + /// + /// Fixup expression: + /// Fixup <- (Target - Fixup + Addend) >> 1 : int24 + /// + /// Errors: + /// - The result of the fixup expression before shifting right by 1 must + /// fit into an int25, otherwise an out-of-range error will be returned. + /// - The result of the fixup expression before shifting right by 1 must + /// be multiple of 2, otherwise an alignment error will be returned. + /// + BranchPCRelPLT24dbl, + + /// A 16-bit PC-relative branch. + /// + /// Fixup expression: + /// Fixup <- (Target - Fixup + Addend) >> 1 : int16 + /// + /// Errors: + /// - The result of the fixup expression before shifting right by 1 must + /// fit into an int17, otherwise an out-of-range error will be returned. + /// - The result of the fixup expression before shifting right by 1 must + /// be multiple of 2, otherwise an alignment error will be returned. + /// + BranchPCRelPLT16dbl, + + /// A 12-bit PC-relative branch. + /// + /// Fixup expression: + /// Fixup <- (Target - Fixup + Addend) >> 1 : int12 + /// + /// Errors: + /// - The result of the fixup expression before shifting right by 1 must + /// fit into an int13, otherwise an out-of-range error will be returned. + /// - The result of the fixup expression before shifting right by 1 must + /// be multiple of 2, otherwise an alignment error will be returned. + /// + BranchPCRelPLT12dbl, + + /// A 64-bit PC-relative PLT address. + /// + /// Fixup expression: + /// Fixup <- Target - Fixup + Addend : int64 + /// + BranchPCRelPLT64, + + /// A 32-bit PC-relative PLT address. + /// + /// Fixup expression: + /// Fixup <- Target - Fixup + Addend : int32 + /// + /// Errors: + /// - The result of the fixup expression must fit into an int32, otherwise + /// an out-of-range error will be returned. + /// + BranchPCRelPLT32, + + /// A 32-bit PC-relative branch to a pointer jump stub. + /// Create a jump stub block that jumps via the pointer at the given symbol. + /// + /// Stub Content: + /// larl %r1, ptr + /// lg %r1, 0(%r1) + /// j %r1 + /// + /// Fixup expression at offset 2 of branch Instruction: + /// Fixup <- (Target - Fixup + Addend) >> 1 : int32 + /// + /// Errors: + /// - The result of the fixup expression before shifting right by 1 must + /// fit into an int33, otherwise an out-of-range error will be returned. + /// an out-of-range error will be returned. + /// + Branch32dblToStub, + + /// A 64-bit offset from GOT to PLT. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int64 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// + DeltaPLT64FromGOT, + + /// A 32-bit offset from GOT to PLT. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int32 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int32, otherwise + /// an out-of-range error will be returned. + /// + DeltaPLT32FromGOT, + + /// A 16-bit offset from GOT to PLT. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int16 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int16, otherwise + /// an out-of-range error will be returned. + /// + DeltaPLT16FromGOT, + + /// A 64-bit GOT offset. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int64 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// + Delta64GOT, + + /// A 32-bit GOT offset. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int32 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int32, otherwise + /// an out-of-range error will be returned. + /// + Delta32GOT, + + /// A 20-bit GOT offset. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int20 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int20, otherwise + /// an out-of-range error will be returned. + /// + Delta20GOT, + + /// A 16-bit GOT offset. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int16 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int16, otherwise + /// an out-of-range error will be returned. + /// + Delta16GOT, + + /// A 12-bit GOT offset. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int12 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int12, otherwise + /// an out-of-range error will be returned. + /// + Delta12GOT, + + /// A 32-bit PC rel. offset to GOT. + /// + /// Fixup expression: + /// Fixup <- GOTBase - Fixup + Addend : int32 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int32, otherwise + /// an out-of-range error will be returned. + /// + DeltaPCRelGOT, + + /// A 32-bit PC rel. offset to GOT shifted by 1. + /// + /// Fixup expression: + /// Fixup <- (GOTBase - Fixup + Addend) >> 1 : int32 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression before shifting right by 1 must + /// fit into an int33, otherwise an out-of-range error will be returned. + /// - The result of the fixup expression before shifting right by 1 must + /// be multiple of 2, otherwise an alignment error will be returned. + /// + DeltaPCRelGOTdbl, + + /// A 64-bit offset to Jump Slot. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int64 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// + Delta64JumpSlot, + + /// A 32-bit offset to Jump Slot. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int32 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int32, otherwise + /// an out-of-range error will be returned. + /// + Delta32JumpSlot, + + /// A 20-bit offset to Jump Slot. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int20 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int20, otherwise + /// an out-of-range error will be returned. + /// + Delta20JumpSlot, + + /// A 16-bit offset to Jump Slot. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int16 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int16, otherwise + /// an out-of-range error will be returned. + /// + Delta16JumpSlot, + + /// A 12-bit offset to Jump Slot. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int12 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int12, otherwise + /// an out-of-range error will be returned. + /// + Delta12JumpSlot, + + /// A 32-bit PC rel. offset to Jump Slot. + /// + /// Fixup expression: + /// Fixup <- (Target - Fixup + Addend) >> 1 : int32 + /// + /// Errors: + /// - The result of the fixup expression before shifting right by 1 must + /// fit into an int33, otherwise an out-of-range error will be returned. + /// - The result of the fixup expression before shifting right by 1 must + /// be multiple of 2, otherwise an alignment error will be returned. + /// + PCRel32JumpSlot, + + /// A 32-bit PC rel. to GOT entry >> 1. + /// + /// Fixup expression: + /// Fixup <- (Target - Fixup + Addend) >> 1 : int32 + /// + /// Errors: + /// - The result of the fixup expression before shifting right by 1 must + /// fit into an int33, otherwise an out-of-range error will be returned. + /// - The result of the fixup expression before shifting right by 1 must + /// be multiple of 2, otherwise an alignment error will be returned. + /// + PCRel32GOTEntry, + +}; + +/// Returns a string name for the given systemz edge. For debugging purposes +/// only +const char *getEdgeKindName(Edge::Kind K); + +/// Apply fixup expression for edge to block content. +inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, + const Symbol *GOTSymbol) { + using namespace support; + + char *BlockWorkingMem = B.getAlreadyMutableContent().data(); + char *FixupPtr = BlockWorkingMem + E.getOffset(); + orc::ExecutorAddr FixupAddress = B.getAddress() + E.getOffset(); + int64_t S = E.getTarget().getAddress().getValue(); + int64_t A = E.getAddend(); + int64_t P = FixupAddress.getValue(); + int64_t GOTBase = GOTSymbol ? GOTSymbol->getAddress().getValue() : 0; + Edge::Kind K = E.getKind(); + + DEBUG_WITH_TYPE("jitlink", { + dbgs() << " Applying fixup on " << G.getEdgeKindName(K) + << " edge, (S, A, P, .GOT.) = (" << formatv("{0:x}", S) << ", " + << formatv("{0:x}", A) << ", " << formatv("{0:x}", P) << ", " + << formatv("{0:x}", GOTBase) << ")\n"; + }); + + const auto isAlignmentCorrect = [](uint64_t Value, int N) { + return (Value & (N - 1)) ? false : true; + }; + + switch (K) { + case Pointer64: { + uint64_t Value = S + A; + write64be(FixupPtr, Value); + break; + } + case Pointer32: { + uint64_t Value = S + A; + if (!LLVM_UNLIKELY(isUInt<32>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(ubig32_t *)FixupPtr = Value; + break; + } + case Pointer20: { + uint64_t Value = S + A; + if (!LLVM_UNLIKELY(isInt<20>(Value))) + return makeTargetOutOfRangeError(G, B, E); + write32be(FixupPtr, (read32be(FixupPtr) & 0xF00000FF) | + ((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4)); + break; + } + case Pointer16: { + uint64_t Value = S + A; + if (!LLVM_UNLIKELY(isUInt<16>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(ubig16_t *)FixupPtr = Value; + break; + } + case Pointer12: { + uint64_t Value = S + A; + if (!LLVM_UNLIKELY(isUInt<12>(Value))) + return makeTargetOutOfRangeError(G, B, E); + write16be(FixupPtr, (read16be(FixupPtr) & 0xF000) | Value); + break; + } + case Pointer8: { + uint64_t Value = S + A; + if (!LLVM_UNLIKELY(isUInt<8>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(uint8_t *)FixupPtr = Value; + break; + } + case Delta64: { + int64_t Value = S + A - P; + *(big64_t *)FixupPtr = Value; + break; + } + case Delta32: { + int64_t Value = S + A - P; + if (!LLVM_UNLIKELY(isInt<32>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(big32_t *)FixupPtr = Value; + break; + } + case Delta16: { + int64_t Value = S + A - P; + if (!LLVM_UNLIKELY(isInt<16>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(big16_t *)FixupPtr = Value; + break; + } + case NegDelta32: { + int64_t Value = P + A - S; + if (!LLVM_UNLIKELY(isInt<32>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(big32_t *)FixupPtr = Value; + break; + } + case Delta32dbl: { + int64_t Value = (S + A - P); + if (!LLVM_UNLIKELY(isInt<33>(Value))) + return makeTargetOutOfRangeError(G, B, E); + if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) + return makeAlignmentError(FixupAddress, Value, 2, E); + write32be(FixupPtr, Value >> 1); + break; + } + case Delta24dbl: { + int64_t Value = (S + A - P); + if (!LLVM_UNLIKELY(isInt<25>(Value))) + return makeTargetOutOfRangeError(G, B, E); + if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) + return makeAlignmentError(FixupAddress, Value, 2, E); + FixupPtr[0] = Value >> 17; + FixupPtr[1] = Value >> 9; + FixupPtr[2] = Value >> 1; + break; + } + case Delta16dbl: { + int64_t Value = (S + A - P); + if (!LLVM_UNLIKELY(isInt<17>(Value))) + return makeTargetOutOfRangeError(G, B, E); + if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) + return makeAlignmentError(FixupAddress, Value, 2, E); + write16be(FixupPtr, Value >> 1); + break; + } + case Delta12dbl: { + int64_t Value = (S + A - P); + if (!LLVM_UNLIKELY(isInt<13>(Value))) + return makeTargetOutOfRangeError(G, B, E); + if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) + return makeAlignmentError(FixupAddress, Value, 2, E); + write16be(FixupPtr, + (read16be(FixupPtr) & 0xF000) | ((Value >> 1) & 0x0FFF)); + break; + } + case Delta64FromGOT: { + assert(GOTSymbol && "No GOT section symbol"); + int64_t Value = S - GOTBase + A; + *(big64_t *)FixupPtr = Value; + break; + } + case Delta32FromGOT: { + assert(GOTSymbol && "No GOT section symbol"); + int64_t Value = S - GOTBase + A; + if (!LLVM_UNLIKELY(isInt<32>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(big32_t *)FixupPtr = Value; + break; + } + case Delta16FromGOT: { + assert(GOTSymbol && "No GOT section symbol"); + int64_t Value = S - GOTBase + A; + if (!LLVM_UNLIKELY(isInt<16>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(big16_t *)FixupPtr = Value; + break; + } + case DeltaPCRelGOT: { + assert(GOTSymbol && "No GOT section symbol"); + int64_t Value = GOTBase + A - P; + *(big32_t *)FixupPtr = Value; + break; + } + case DeltaPCRelGOTdbl: { + assert(GOTSymbol && "No GOT section symbol"); + int64_t Value = (GOTBase + A - P); + if (!LLVM_UNLIKELY(isInt<33>(Value))) + return makeTargetOutOfRangeError(G, B, E); + if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) + return makeAlignmentError(FixupAddress, Value, 2, E); + write32be(FixupPtr, Value >> 1); + break; + } + case BranchPCRelPLT32dbl: { + int64_t Value = (S + A - P); + if (!LLVM_UNLIKELY(isInt<33>(Value))) + return makeTargetOutOfRangeError(G, B, E); + if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) + return makeAlignmentError(FixupAddress, Value, 2, E); + write32be(FixupPtr, Value >> 1); + break; + } + case BranchPCRelPLT24dbl: { + int64_t Value = (S + A - P); + if (!LLVM_UNLIKELY(isInt<25>(Value))) + return makeTargetOutOfRangeError(G, B, E); + FixupPtr[0] = Value >> 17; + FixupPtr[1] = Value >> 9; + FixupPtr[2] = Value >> 1; + break; + } + case BranchPCRelPLT16dbl: { + int64_t Value = (S + A - P); + if (!LLVM_UNLIKELY(isInt<17>(Value))) + return makeTargetOutOfRangeError(G, B, E); + if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) + return makeAlignmentError(FixupAddress, Value, 2, E); + write16be(FixupPtr, Value >> 1); + break; + } + case BranchPCRelPLT12dbl: { + int64_t Value = (S + A - P); + if (!LLVM_UNLIKELY(isInt<13>(Value))) + return makeTargetOutOfRangeError(G, B, E); + if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) + return makeAlignmentError(FixupAddress, Value, 2, E); + write16be(FixupPtr, + (read16be(FixupPtr) & 0xF000) | ((Value >> 1) & 0x0FFF)); + break; + } + case BranchPCRelPLT64: { + int64_t Value = (S + A - P); + *(big64_t *)FixupPtr = Value; + break; + } + case BranchPCRelPLT32: { + int64_t Value = (S + A - P); + if (!LLVM_UNLIKELY(isInt<32>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(big32_t *)FixupPtr = Value; + break; + } + case DeltaPLT64FromGOT: { + assert(GOTSymbol && "No GOT section symbol"); + int64_t Value = (S + A - GOTBase); + *(big64_t *)FixupPtr = Value; + break; + } + case DeltaPLT32FromGOT: { + assert(GOTSymbol && "No GOT section symbol"); + int64_t Value = (S + A - GOTBase); + if (!LLVM_UNLIKELY(isInt<32>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(big32_t *)FixupPtr = Value; + break; + } + case DeltaPLT16FromGOT: { + assert(GOTSymbol && "No GOT section symbol"); + int64_t Value = (S + A - GOTBase); + if (!LLVM_UNLIKELY(isInt<16>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(big16_t *)FixupPtr = Value; + break; + } + case Branch32dblToStub: { + int64_t Value = (S + A - P); + if (!LLVM_UNLIKELY(isInt<33>(Value))) + return makeTargetOutOfRangeError(G, B, E); + char *AddrToPatch = FixupPtr + 2; + *(big32_t *)AddrToPatch = (Value >> 1); + break; + } + case PCRel32GOTEntry: { + int64_t Value = (S + A - P); + if (!LLVM_UNLIKELY(isInt<33>(Value))) + return makeTargetOutOfRangeError(G, B, E); + if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) + return makeAlignmentError(FixupAddress, Value, 2, E); + write32be(FixupPtr, Value >> 1); + break; + } + case Delta64GOT: { + assert(GOTSymbol && "No GOT section symbol"); + int64_t Value = S - GOTBase + A; + *(big64_t *)FixupPtr = Value; + break; + } + case Delta32GOT: { + assert(GOTSymbol && "No GOT section symbol"); + uint64_t Value = S - GOTBase + A; + if (!LLVM_UNLIKELY(isUInt<32>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(big32_t *)FixupPtr = Value; + break; + } + case Delta20GOT: { + assert(GOTSymbol && "No GOT section symbol"); + uint64_t Value = S - GOTBase + A; + if (!LLVM_UNLIKELY(isInt<20>(Value))) + return makeTargetOutOfRangeError(G, B, E); + write32be(FixupPtr, (read32be(FixupPtr) & 0xF00000FF) | + ((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4)); + break; + } + case Delta16GOT: { + assert(GOTSymbol && "No GOT section symbol"); + uint64_t Value = S - GOTBase + A; + if (!LLVM_UNLIKELY(isUInt<16>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(big16_t *)FixupPtr = Value; + break; + } + case Delta12GOT: { + assert(GOTSymbol && "No GOT section symbol"); + uint64_t Value = S - GOTBase + A; + if (!LLVM_UNLIKELY(isUInt<12>(Value))) + return makeTargetOutOfRangeError(G, B, E); + write16be(FixupPtr, (read16be(FixupPtr) & 0xF000) | Value); + break; + } + case Delta64JumpSlot: { + assert(GOTSymbol && "No GOT section symbol"); + uint64_t Value = S - GOTBase + A; + *(big64_t *)FixupPtr = Value; + break; + } + case Delta32JumpSlot: { + assert(GOTSymbol && "No GOT section symbol"); + uint64_t Value = S - GOTBase + A; + if (!LLVM_UNLIKELY(isUInt<32>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(big32_t *)FixupPtr = Value; + break; + } + case Delta20JumpSlot: { + assert(GOTSymbol && "No GOT section symbol"); + int64_t Value = S - GOTBase + A; + if (!LLVM_UNLIKELY(isInt<20>(Value))) + return makeTargetOutOfRangeError(G, B, E); + write32be(FixupPtr, (read32be(FixupPtr) & 0xF00000FF) | + ((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4)); + break; + } + case Delta16JumpSlot: { + assert(GOTSymbol && "No GOT section symbol"); + uint64_t Value = S - GOTBase + A; + if (!LLVM_UNLIKELY(isUInt<16>(Value))) + return makeTargetOutOfRangeError(G, B, E); + *(big16_t *)FixupPtr = Value; + break; + } + case Delta12JumpSlot: { + assert(GOTSymbol && "No GOT section symbol"); + uint64_t Value = S - GOTBase + A; + if (!LLVM_UNLIKELY(isUInt<13>(Value))) + return makeTargetOutOfRangeError(G, B, E); + write16be(FixupPtr, (read16be(FixupPtr) & 0xF000) | Value); + break; + } + case PCRel32JumpSlot: { + int64_t Value = S + A - P; + if (!LLVM_UNLIKELY(isInt<33>(Value))) + return makeTargetOutOfRangeError(G, B, E); + if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) + return makeAlignmentError(FixupAddress, Value, 2, E); + write32be(FixupPtr, Value >> 1); + break; + } + default: + return make_error( + "In graph " + G.getName() + ", section " + B.getSection().getName() + + " unsupported edge kind " + getEdgeKindName(E.getKind())); + } + + return Error::success(); +} + +/// SystemZ null pointer content. +extern const char NullPointerContent[8]; +inline ArrayRef getGOTEntryBlockContent(LinkGraph &G) { + return {reinterpret_cast(NullPointerContent), + G.getPointerSize()}; +} + +/// SystemZ pointer jump stub content. +/// +/// Contains the instruction sequence for an indirect jump via an in-memory +/// pointer: +/// larl %r1, ptr +/// lg %r1, 0(%r1) +/// j %r1 +constexpr size_t StubEntrySize = 14; +extern const char Pointer64JumpStubContent[StubEntrySize]; +inline ArrayRef getStubBlockContent(LinkGraph &G) { + auto StubContent = Pointer64JumpStubContent; + return {reinterpret_cast(StubContent), StubEntrySize}; +} + +/// Creates a new pointer block in the given section and returns an +/// Anonymous symbol pointing to it. +/// +/// If InitialTarget is given then an Pointer64 relocation will be added to the +/// block pointing at InitialTarget. +inline Symbol &createAnonymousPointer(LinkGraph &G, Section &PointerSection, + Symbol *InitialTarget = nullptr, + uint64_t InitialAddend = 0) { + auto &B = G.createContentBlock(PointerSection, getGOTEntryBlockContent(G), + orc::ExecutorAddr(), G.getPointerSize(), 0); + if (InitialTarget) + B.addEdge(Pointer64, 0, *InitialTarget, InitialAddend); + return G.addAnonymousSymbol(B, 0, G.getPointerSize(), false, false); +} + +/// Create a jump stub block that jumps via the pointer at the given symbol. +/// +/// The stub block will have the following default values: +/// alignment: 8-bit +/// alignment-offset: 0 +inline Block &createPointerJumpStubBlock(LinkGraph &G, Section &StubSection, + Symbol &PointerSymbol) { + auto &B = G.createContentBlock(StubSection, getStubBlockContent(G), + orc::ExecutorAddr(), 8, 0); + B.addEdge(Branch32dblToStub, 0, PointerSymbol, 0); + return B; +} + +/// Create a jump stub that jumps via the pointer at the given symbol and +/// an anonymous symbol pointing to it. Return the anonymous symbol. +/// +/// The stub block will be created by createPointerJumpStubBlock. +inline Symbol &createAnonymousPointerJumpStub(LinkGraph &G, + Section &StubSection, + Symbol &PointerSymbol) { + return G.addAnonymousSymbol( + createPointerJumpStubBlock(G, StubSection, PointerSymbol), 0, + StubEntrySize, true, false); +} + +/// Global Offset Table Builder. +class GOTTableManager : public TableManager { +public: + static StringRef getSectionName() { return "$__GOT"; } + + bool visitEdge(LinkGraph &G, Block *B, Edge &E) { + if (E.getTarget().isDefined()) + return false; + Edge::Kind KindToSet = Edge::Invalid; + switch (E.getKind()) { + case systemz::Delta12GOT: + case systemz::Delta16GOT: + case systemz::Delta20GOT: + case systemz::Delta32GOT: + case systemz::Delta64GOT: + case systemz::Delta16FromGOT: + case systemz::Delta32FromGOT: + case systemz::Delta64FromGOT: + case systemz::Delta12JumpSlot: + case systemz::Delta16JumpSlot: + case systemz::Delta32JumpSlot: + case systemz::Delta64JumpSlot: + case systemz::Delta20JumpSlot: { + case systemz::DeltaPCRelGOT: + case systemz::DeltaPCRelGOTdbl: + case systemz::PCRel32GOTEntry: + case systemz::PCRel32JumpSlot: + KindToSet = E.getKind(); + break; + } + default: + return false; + } + assert(KindToSet != Edge::Invalid && + "Fell through switch, but no new kind to set"); + DEBUG_WITH_TYPE("jitlink", { + dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at " + << B->getFixupAddress(E) << " (" << B->getAddress() << " + " + << formatv("{0:x}", E.getOffset()) << ")\n"; + }); + E.setTarget(getEntryForTarget(G, E.getTarget())); + return true; + } + + Symbol &createEntry(LinkGraph &G, Symbol &Target) { + return createAnonymousPointer(G, getGOTSection(G), &Target); + } + +private: + Section &getGOTSection(LinkGraph &G) { + if (!GOTSection) + GOTSection = &G.createSection(getSectionName(), + orc::MemProt::Read | orc::MemProt::Exec); + return *GOTSection; + } + + Section *GOTSection = nullptr; +}; + +/// Procedure Linkage Table Builder. +class PLTTableManager : public TableManager { +public: + PLTTableManager(GOTTableManager &GOT) : GOT(GOT) {} + + static StringRef getSectionName() { return "$__STUBS"; } + + bool visitEdge(LinkGraph &G, Block *B, Edge &E) { + if (E.getTarget().isDefined()) + return false; + + switch (E.getKind()) { + case systemz::BranchPCRelPLT32: + case systemz::BranchPCRelPLT64: + case systemz::BranchPCRelPLT12dbl: + case systemz::BranchPCRelPLT16dbl: + case systemz::BranchPCRelPLT24dbl: + case systemz::BranchPCRelPLT32dbl: + case systemz::DeltaPLT16FromGOT: + case systemz::DeltaPLT32FromGOT: + case systemz::DeltaPLT64FromGOT: + break; + default: + return false; + } + DEBUG_WITH_TYPE("jitlink", { + dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at " + << B->getFixupAddress(E) << " (" << B->getAddress() << " + " + << formatv("{0:x}", E.getOffset()) << ")\n"; + }); + E.setTarget(getEntryForTarget(G, E.getTarget())); + return true; + } + + Symbol &createEntry(LinkGraph &G, Symbol &Target) { + return createAnonymousPointerJumpStub(G, getStubsSection(G), + GOT.getEntryForTarget(G, Target)); + } + +public: + Section &getStubsSection(LinkGraph &G) { + if (!StubsSection) + StubsSection = &G.createSection(getSectionName(), + orc::MemProt::Read | orc::MemProt::Exec); + return *StubsSection; + } + + GOTTableManager &GOT; + Section *StubsSection = nullptr; +}; + +} // namespace systemz +} // namespace jitlink +} // namespace llvm + +#endif // LLVM_EXECUTIONENGINE_JITLINK_SYSTEMZ_H diff --git a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt index e5f5a99c39bc0..bd78150407830 100644 --- a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt +++ b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt @@ -26,6 +26,7 @@ add_llvm_component_library(LLVMJITLink ELF_loongarch.cpp ELF_ppc64.cpp ELF_riscv.cpp + ELF_systemz.cpp ELF_x86_64.cpp # COFF @@ -41,6 +42,7 @@ add_llvm_component_library(LLVMJITLink loongarch.cpp ppc64.cpp riscv.cpp + systemz.cpp x86_64.cpp ADDITIONAL_HEADER_DIRS diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp index fdcce20cd2d10..374982d9e2b1d 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp @@ -19,6 +19,7 @@ #include "llvm/ExecutionEngine/JITLink/ELF_loongarch.h" #include "llvm/ExecutionEngine/JITLink/ELF_ppc64.h" #include "llvm/ExecutionEngine/JITLink/ELF_riscv.h" +#include "llvm/ExecutionEngine/JITLink/ELF_systemz.h" #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h" #include "llvm/Object/ELF.h" #include "llvm/Support/Format.h" @@ -99,6 +100,8 @@ createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) { } case ELF::EM_RISCV: return createLinkGraphFromELFObject_riscv(ObjectBuffer); + case ELF::EM_S390: + return createLinkGraphFromELFObject_systemz(ObjectBuffer); case ELF::EM_X86_64: return createLinkGraphFromELFObject_x86_64(ObjectBuffer); case ELF::EM_386: @@ -136,6 +139,9 @@ void link_ELF(std::unique_ptr G, case Triple::riscv64: link_ELF_riscv(std::move(G), std::move(Ctx)); return; + case Triple::systemz: + link_ELF_systemz(std::move(G), std::move(Ctx)); + return; case Triple::x86_64: link_ELF_x86_64(std::move(G), std::move(Ctx)); return; diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp new file mode 100644 index 0000000000000..6d598d62b1fc2 --- /dev/null +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp @@ -0,0 +1,437 @@ +//===----- ELF_systemz.cpp - JIT linker implementation for ELF/systemz ----===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// ELF/systemz jit-link implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" +#include "llvm/ExecutionEngine/JITLink/systemz.h" +#include "llvm/Object/ELFObjectFile.h" + +#include "DefineExternalSectionStartAndEndSymbols.h" +#include "EHFrameSupportImpl.h" +#include "ELFLinkGraphBuilder.h" +#include "JITLinkGeneric.h" + +#define DEBUG_TYPE "jitlink" + +using namespace llvm; +using namespace llvm::jitlink; + +namespace { + +constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_"; + +Error buildTables_ELF_systemz(LinkGraph &G) { + LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); + systemz::GOTTableManager GOT; + systemz::PLTTableManager PLT(GOT); + visitExistingEdges(G, GOT, PLT); + return Error::success(); +} + +} // namespace + +namespace llvm { +namespace jitlink { +class ELFJITLinker_systemz : public JITLinker { + friend class JITLinker; + +public: + ELFJITLinker_systemz(std::unique_ptr Ctx, + std::unique_ptr G, + PassConfiguration PassConfig) + : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) { + if (shouldAddDefaultTargetPasses(getGraph().getTargetTriple())) + getPassConfig().PostAllocationPasses.push_back( + [this](LinkGraph &G) { return getOrCreateGOTSymbol(G); }); + } + +private: + Symbol *GOTSymbol = nullptr; + + Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { + return systemz::applyFixup(G, B, E, GOTSymbol); + } + + Error getOrCreateGOTSymbol(LinkGraph &G) { + auto DefineExternalGOTSymbolIfPresent = + createDefineExternalSectionStartAndEndSymbolsPass( + [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc { + if (Sym.getName() == ELFGOTSymbolName) + if (auto *GOTSection = G.findSectionByName( + systemz::GOTTableManager::getSectionName())) { + GOTSymbol = &Sym; + return {*GOTSection, true}; + } + return {}; + }); + + // Try to attach _GLOBAL_OFFSET_TABLE_ to the GOT if it's defined as an + // external. + if (auto Err = DefineExternalGOTSymbolIfPresent(G)) + return Err; + + // If we succeeded then we're done. + if (GOTSymbol) + return Error::success(); + + // Otherwise look for a GOT section: If it already has a start symbol we'll + // record it, otherwise we'll create our own. + // If there's a GOT section but we didn't find an external GOT symbol... + if (auto *GOTSection = + G.findSectionByName(systemz::GOTTableManager::getSectionName())) { + + // Check for an existing defined symbol. + for (auto *Sym : GOTSection->symbols()) + if (Sym->getName() == ELFGOTSymbolName) { + GOTSymbol = Sym; + return Error::success(); + } + + // If there's no defined symbol then create one. + SectionRange SR(*GOTSection); + if (SR.empty()) + GOTSymbol = + &G.addAbsoluteSymbol(ELFGOTSymbolName, orc::ExecutorAddr(), 0, + Linkage::Strong, Scope::Local, true); + else + GOTSymbol = + &G.addDefinedSymbol(*SR.getFirstBlock(), 0, ELFGOTSymbolName, 0, + Linkage::Strong, Scope::Local, false, true); + } + + // If we still haven't found a GOT symbol then double check the externals. + // We may have a GOT-relative reference but no GOT section, in which case + // we just need to point the GOT symbol at some address in this graph. + if (!GOTSymbol) { + for (auto *Sym : G.external_symbols()) { + if (Sym->getName() == ELFGOTSymbolName) { + auto Blocks = G.blocks(); + if (!Blocks.empty()) { + G.makeAbsolute(*Sym, (*Blocks.begin())->getAddress()); + GOTSymbol = Sym; + break; + } + } + } + } + + return Error::success(); + } +}; + +class ELFLinkGraphBuilder_systemz + : public ELFLinkGraphBuilder { +private: + using ELFT = object::ELF64BE; + using Base = ELFLinkGraphBuilder; + using Base::G; // Use LinkGraph pointer from base class. + + Error addRelocations() override { + LLVM_DEBUG(dbgs() << "Processing relocations:\n"); + + using Base = ELFLinkGraphBuilder; + using Self = ELFLinkGraphBuilder_systemz; + for (const auto &RelSect : Base::Sections) { + if (RelSect.sh_type == ELF::SHT_REL) + // Validate the section to read relocation entries from. + return make_error("No SHT_REL in valid " + + G->getTargetTriple().getArchName() + + " ELF object files", + inconvertibleErrorCode()); + + if (Error Err = Base::forEachRelaRelocation(RelSect, this, + &Self::addSingleRelocation)) + return Err; + } + + return Error::success(); + } + + Error addSingleRelocation(const typename ELFT::Rela &Rel, + const typename ELFT::Shdr &FixupSect, + Block &BlockToFix) { + using support::big32_t; + using Base = ELFLinkGraphBuilder; + auto ELFReloc = Rel.getType(false); + + // No reloc. + if (LLVM_UNLIKELY(ELFReloc == ELF::R_390_NONE)) + return Error::success(); + + uint32_t SymbolIndex = Rel.getSymbol(false); + auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); + if (!ObjSymbol) + return ObjSymbol.takeError(); + + Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); + if (!GraphSymbol) + return make_error( + formatv("Could not find symbol at given index, did you add it to " + "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", + SymbolIndex, (*ObjSymbol)->st_shndx, + Base::GraphSymbols.size()), + inconvertibleErrorCode()); + + // Validate the relocation kind. + int64_t Addend = Rel.r_addend; + Edge::Kind Kind = Edge::Invalid; + + switch (ELFReloc) { + case ELF::R_390_PC64: { + Kind = systemz::Delta64; + break; + } + case ELF::R_390_PC32: { + Kind = systemz::Delta32; + break; + } + case ELF::R_390_PC16: { + Kind = systemz::Delta16; + break; + } + case ELF::R_390_PC32DBL: { + Kind = systemz::Delta32dbl; + break; + } + case ELF::R_390_PC24DBL: { + Kind = systemz::Delta24dbl; + break; + } + case ELF::R_390_PC16DBL: { + Kind = systemz::Delta16dbl; + break; + } + case ELF::R_390_PC12DBL: { + Kind = systemz::Delta12dbl; + break; + } + case ELF::R_390_64: { + Kind = systemz::Pointer64; + break; + } + case ELF::R_390_32: { + Kind = systemz::Pointer32; + break; + } + case ELF::R_390_20: { + Kind = systemz::Pointer20; + break; + } + case ELF::R_390_16: { + Kind = systemz::Pointer16; + break; + } + case ELF::R_390_12: { + Kind = systemz::Pointer12; + break; + } + case ELF::R_390_8: { + Kind = systemz::Pointer8; + break; + } + // Relocations targeting the PLT associated with the symbol. + case ELF::R_390_PLT64: { + Kind = systemz::BranchPCRelPLT64; + break; + } + case ELF::R_390_PLT32: { + Kind = systemz::BranchPCRelPLT32; + break; + } + case ELF::R_390_PLT32DBL: { + Kind = systemz::BranchPCRelPLT32dbl; + break; + } + case ELF::R_390_PLT24DBL: { + Kind = systemz::BranchPCRelPLT24dbl; + break; + } + case ELF::R_390_PLT16DBL: { + Kind = systemz::BranchPCRelPLT16dbl; + break; + } + case ELF::R_390_PLT12DBL: { + Kind = systemz::BranchPCRelPLT12dbl; + break; + } + case ELF::R_390_PLTOFF64: { + Kind = systemz::DeltaPLT64FromGOT; + break; + } + case ELF::R_390_PLTOFF32: { + Kind = systemz::DeltaPLT32FromGOT; + break; + } + case ELF::R_390_PLTOFF16: { + Kind = systemz::DeltaPLT16FromGOT; + break; + } + // Relocations targeting the GOT entry associated with the symbol. + case ELF::R_390_GOTOFF64: { + Kind = systemz::Delta64FromGOT; + break; + } + // Seems loke ‘R_390_GOTOFF32’. + case ELF::R_390_GOTOFF: { + Kind = systemz::Delta32FromGOT; + break; + } + case ELF::R_390_GOTOFF16: { + Kind = systemz::Delta16FromGOT; + break; + } + case ELF::R_390_GOT64: { + Kind = systemz::Delta64GOT; + break; + } + case ELF::R_390_GOT32: { + Kind = systemz::Delta32GOT; + break; + } + case ELF::R_390_GOT20: { + Kind = systemz::Delta20GOT; + break; + } + case ELF::R_390_GOT16: { + Kind = systemz::Delta16GOT; + break; + } + case ELF::R_390_GOT12: { + Kind = systemz::Delta12GOT; + break; + } + case ELF::R_390_GOTPC: { + Kind = systemz::DeltaPCRelGOT; + break; + } + case ELF::R_390_GOTPCDBL: { + Kind = systemz::DeltaPCRelGOTdbl; + break; + } + case ELF::R_390_GOTPLT64: { + Kind = systemz::Delta64JumpSlot; + break; + } + case ELF::R_390_GOTPLT32: { + Kind = systemz::Delta32JumpSlot; + break; + } + case ELF::R_390_GOTPLT20: { + Kind = systemz::Delta20JumpSlot; + break; + } + case ELF::R_390_GOTPLT16: { + Kind = systemz::Delta16JumpSlot; + break; + } + case ELF::R_390_GOTPLT12: { + Kind = systemz::Delta12JumpSlot; + break; + } + case ELF::R_390_GOTPLTENT: { + Kind = systemz::PCRel32JumpSlot; + break; + } + case ELF::R_390_GOTENT: { + Kind = systemz::PCRel32GOTEntry; + break; + } + default: + return make_error( + "In " + G->getName() + ": Unsupported systemz relocation type " + + object::getELFRelocationTypeName(ELF::EM_S390, ELFReloc)); + } + auto FixupAddress = orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset; + Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress(); + Edge GE(Kind, Offset, *GraphSymbol, Addend); + LLVM_DEBUG({ + dbgs() << " "; + printEdge(dbgs(), BlockToFix, GE, systemz::getEdgeKindName(Kind)); + dbgs() << "\n"; + }); + + BlockToFix.addEdge(std::move(GE)); + + return Error::success(); + } + +public: + ELFLinkGraphBuilder_systemz(StringRef FileName, + const object::ELFFile &Obj, Triple TT, + SubtargetFeatures Features) + : ELFLinkGraphBuilder(Obj, std::move(TT), std::move(Features), + FileName, systemz::getEdgeKindName) {} +}; + +Expected> +createLinkGraphFromELFObject_systemz(MemoryBufferRef ObjectBuffer) { + LLVM_DEBUG({ + dbgs() << "Building jitlink graph for new input " + << ObjectBuffer.getBufferIdentifier() << "...\n"; + }); + + auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer); + if (!ELFObj) + return ELFObj.takeError(); + + auto Features = (*ELFObj)->getFeatures(); + if (!Features) + return Features.takeError(); + + assert((*ELFObj)->getArch() == Triple::systemz && + "Only SystemZ (big endian) is supported for now"); + + auto &ELFObjFile = cast>(**ELFObj); + return ELFLinkGraphBuilder_systemz( + (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), + (*ELFObj)->makeTriple(), std::move(*Features)) + .buildGraph(); +} + +void link_ELF_systemz(std::unique_ptr G, + std::unique_ptr Ctx) { + PassConfiguration Config; + const Triple &TT = G->getTargetTriple(); + if (Ctx->shouldAddDefaultTargetPasses(TT)) { + // Add eh-frame passes. + Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame")); + Config.PrePrunePasses.push_back( + EHFrameEdgeFixer(".eh_frame", G->getPointerSize(), systemz::Pointer32, + systemz::Pointer64, systemz::Delta32, systemz::Delta64, + systemz::NegDelta32)); + Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame")); + + // Add a mark-live pass. + if (auto MarkLive = Ctx->getMarkLivePass(TT)) + Config.PrePrunePasses.push_back(std::move(MarkLive)); + else + Config.PrePrunePasses.push_back(markAllSymbolsLive); + + // Add an in-place GOT/Stubs build pass. + Config.PostPrunePasses.push_back(buildTables_ELF_systemz); + + // Resolve any external section start / end symbols. + Config.PostAllocationPasses.push_back( + createDefineExternalSectionStartAndEndSymbolsPass( + identifyELFSectionStartAndEndSymbols)); + + // TODO: Add GOT/Stubs optimizer pass. + // Config.PreFixupPasses.push_back(systemz::optimizeGOTAndStubAccesses); + } + + if (auto Err = Ctx->modifyPassConfig(*G, Config)) + return Ctx->notifyFailed(std::move(Err)); + + ELFJITLinker_systemz::link(std::move(Ctx), std::move(G), std::move(Config)); +} + +} // namespace jitlink +} // namespace llvm diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp index ef382c3ce695a..453c26cca8eae 100644 --- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp @@ -16,6 +16,7 @@ #include "llvm/ExecutionEngine/JITLink/aarch64.h" #include "llvm/ExecutionEngine/JITLink/i386.h" #include "llvm/ExecutionEngine/JITLink/loongarch.h" +#include "llvm/ExecutionEngine/JITLink/systemz.h" #include "llvm/ExecutionEngine/JITLink/x86_64.h" #include "llvm/Support/Format.h" #include "llvm/Support/MemoryBuffer.h" @@ -459,6 +460,8 @@ AnonymousPointerCreator getAnonymousPointerCreator(const Triple &TT) { case Triple::loongarch32: case Triple::loongarch64: return loongarch::createAnonymousPointer; + case Triple::systemz: + return systemz::createAnonymousPointer; default: return nullptr; } @@ -475,6 +478,8 @@ PointerJumpStubCreator getPointerJumpStubCreator(const Triple &TT) { case Triple::loongarch32: case Triple::loongarch64: return loongarch::createAnonymousPointerJumpStub; + case Triple::systemz: + return systemz::createAnonymousPointerJumpStub; default: return nullptr; } @@ -503,6 +508,7 @@ std::unique_ptr absoluteSymbolsLinkGraph(const Triple &TT, switch (TT.getArch()) { case Triple::aarch64: case llvm::Triple::riscv64: + case Triple::systemz: case Triple::x86_64: PointerSize = 8; break; diff --git a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp new file mode 100644 index 0000000000000..36ba857d8f5c4 --- /dev/null +++ b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp @@ -0,0 +1,121 @@ +//===---- systemz.cpp - Generic JITLink systemz edge kinds, utilities -----===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Generic utilities for graphs representing systemz objects. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/JITLink/systemz.h" + +#define DEBUG_TYPE "jitlink" + +namespace llvm { +namespace jitlink { +namespace systemz { + +const char NullPointerContent[8] = {0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +const char Pointer64JumpStubContent[14] = { + static_cast(0xC0), 0x10, 0x00, 0x00, 0x00, 0x00, // larl r1 + static_cast(0xE3), 0x10, 0x10, 0x00, 0x00, 0x04, // LG 1, 0(1) + static_cast(0x07), 0xF1, // BCR 15, 1 +}; + +const char *getEdgeKindName(Edge::Kind R) { + switch (R) { + case Pointer64: + return "Pointer64"; + case Pointer32: + return "Pointer32"; + case Pointer20: + return "Pointer20"; + case Pointer16: + return "Pointer16"; + case Pointer12: + return "Pointer12"; + case Pointer8: + return "Pointer8"; + case Delta64: + return "Delta64"; + case Delta32: + return "Delta32"; + case Delta16: + return "Delta16"; + case Delta32dbl: + return "Delta32dbl"; + case Delta24dbl: + return "Delta24dbl"; + case Delta16dbl: + return "Delta16dbl"; + case Delta12dbl: + return "Delta12dbl"; + case NegDelta64: + return "NegDelta64"; + case NegDelta32: + return "NegDelta32"; + case Delta64FromGOT: + return "Delta64FromGOT"; + case Delta32FromGOT: + return "Delta32FromGOT"; + case Delta16FromGOT: + return "Delta16FromGOT"; + case BranchPCRelPLT32dbl: + return "BranchPCRelPLT32dbl"; + case BranchPCRelPLT24dbl: + return "BranchPCRelPLT24dbl"; + case BranchPCRelPLT16dbl: + return "BranchPCRelPLT16dbl"; + case BranchPCRelPLT12dbl: + return "BranchPCRelPLT12dbl"; + case PCRel32GOTEntry: + return "PCRel32GOTENTRY"; + case BranchPCRelPLT64: + return "BranchPCRelPLT64"; + case BranchPCRelPLT32: + return "BranchPCRelPLT32"; + case DeltaPLT64FromGOT: + return "DeltaPLT64FromGOT"; + case DeltaPLT32FromGOT: + return "DeltaPLT32FromGOT"; + case DeltaPLT16FromGOT: + return "DeltaPLT16FromGOT"; + case Delta64GOT: + return "Delta64GOT"; + case Delta32GOT: + return "Delta32GOT"; + case Delta20GOT: + return "Delta20GOT"; + case Delta16GOT: + return "Delta16GOT"; + case Delta12GOT: + return "Delta12GOT"; + case DeltaPCRelGOT: + return "DeltaPCRelGOT"; + case DeltaPCRelGOTdbl: + return "DeltaPCRelGOTdbl"; + case Delta64JumpSlot: + return "Delta64JumpSlot"; + case Delta32JumpSlot: + return "Delta32JumpSlot"; + case Delta20JumpSlot: + return "Delta20JumpSlot"; + case Delta16JumpSlot: + return "Delta16JumpSlot"; + case Delta12JumpSlot: + return "Delta12JumpSlot"; + case PCRel32JumpSlot: + return "PCRel32JumpSlot"; + default: + return getGenericEdgeKindName(static_cast(R)); + } +} + +} // namespace systemz +} // namespace jitlink +} // namespace llvm diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_ehframe.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_ehframe.s new file mode 100644 index 0000000000000..fca8345ff207c --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_ehframe.s @@ -0,0 +1,58 @@ +# REQUIRES: asserts +# REQUIRES: system-linux +# RUN: llvm-mc -triple=systemz-unknown-linux-gnu -filetype=obj -o %t %s +# RUN: llvm-jitlink -noexec -phony-externals -debug-only=jitlink %t 2>&1 | \ +# RUN: FileCheck %s +# +# Check that splitting of eh-frame sections works. +# +# CHECK: DWARFRecordSectionSplitter: Processing .eh_frame... +# CHECK: Processing block at +# CHECK: Processing CFI record at +# CHECK: Processing CFI record at +# CHECK: EHFrameEdgeFixer: Processing .eh_frame in "{{.*}}"... +# CHECK: Processing block at +# CHECK: Record is CIE +# CHECK: Processing block at +# CHECK: Record is FDE +# CHECK: Adding edge at {{.*}} to CIE at: {{.*}} +# CHECK: Processing PC-begin at +# CHECK: Existing edge at {{.*}} to PC begin at {{.*}} +# CHECK: Adding keep-alive edge from target at {{.*}} to FDE at {{.*}} + + .text + .file "exceptions.cpp" + # Start of file scope inline assembly + .globl _ZSt21ios_base_library_initv + + # End of file scope inline assembly + .globl main # -- Begin function main + .p2align 4 + .type main,@function +main: # @main + .cfi_startproc +# %bb.0: # %entry + stmg %r11, %r15, 88(%r15) + .cfi_offset %r11, -72 + .cfi_offset %r14, -48 + .cfi_offset %r15, -40 + aghi %r15, -168 + .cfi_def_cfa_offset 328 + lgr %r11, %r15 + .cfi_def_cfa_register %r11 + mvhi 164(%r11), 0 + lghi %r2, 4 + brasl %r14, __cxa_allocate_exception@PLT + mvhi 0(%r2), 1 + lgrl %r3, _ZTIi@GOT + lghi %r4, 0 + brasl %r14, __cxa_throw@PLT +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .section ".note.GNU-stack","",@progbits + .addrsig + .addrsig_sym __cxa_allocate_exception + .addrsig_sym __cxa_throw + .addrsig_sym _ZTIi diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_got.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_got.s new file mode 100644 index 0000000000000..00b111d5d59f1 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_got.s @@ -0,0 +1,78 @@ +# REQUIRES: system-linux +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -filetype=obj -o %t/elf_reloc.o %s +# +# RUN: llvm-jitlink -noexec \ +# RUN: -slab-allocate 100Kb -slab-address 0x6ff00000 -slab-page-size 4096 \ +# RUN: -abs foo=0x6ff04040 \ +# RUN: -abs bar=0x6ff04048 \ +# RUN: %t/elf_reloc.o +# +# Check R_390_GOT* handling. + + .text + .globl main + .type main,@function +main: + larl %r12, _GLOBAL_OFFSET_TABLE_ + .reloc .+2, R_390_GOTENT, foo+2 + larl %r1, 0 + .reloc .+2, R_390_GOTENT, bar+2 + larl %r1, 0 + .reloc .+2, R_390_GOTPLTENT, foo+2 + larl %r1, 0 + .reloc .+2, R_390_GOTPLTENT, bar+2 + larl %r1, 0 + .reloc .+2, R_390_GOT12, foo + l %r1, 0(%r12) + .reloc .+2, R_390_GOT12, bar + l %r1, 0(%r12) + .reloc .+2, R_390_GOTPLT12, foo + l %r1, 0(%r12) + .reloc .+2, R_390_GOTPLT12, bar + l %r1, 0(%r12) + .reloc .+2, R_390_GOT20, foo + lg %r1, 0(%r12) + .reloc .+2, R_390_GOT20, bar + lg %r1, 0(%r12) + .reloc .+2, R_390_GOTPLT20, foo + lg %r1, 0(%r12) + .reloc .+2, R_390_GOTPLT20, bar + lg %r1, 0(%r12) + br %r14 + .size main, .-main + + .data + .reloc ., R_390_GOT16, foo + .space 2 + .reloc ., R_390_GOT16, bar + .space 2 + .reloc ., R_390_GOTPLT16, foo + .space 2 + .reloc ., R_390_GOTPLT16, bar + .space 2 + .reloc ., R_390_GOT32, foo + .space 4 + .reloc ., R_390_GOT32, bar + .space 4 + .reloc ., R_390_GOTPLT32, foo + .space 4 + .reloc ., R_390_GOTPLT32, bar + .space 4 + .reloc ., R_390_GOT64, foo + .space 8 + .reloc ., R_390_GOT64, bar + .space 8 + .reloc ., R_390_GOTPLT64, foo + .space 8 + .reloc ., R_390_GOTPLT64, bar + .space 8 + .reloc ., R_390_GOTPC, foo + .space 4 + .reloc ., R_390_GOTPC, bar + .space 4 + .reloc ., R_390_GOTPCDBL, foo + .space 4 + .reloc ., R_390_GOTPCDBL, bar + .space 4 diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s new file mode 100644 index 0000000000000..3d1484acaf9ae --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s @@ -0,0 +1,35 @@ +# REQUIRES: system-linux +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -filetype=obj -o %t.o %s +# RUN: llvm-jitlink -noexec -abs X=0xFFFF -check=%s %t.o + +# RUN: not llvm-jitlink -noexec -abs X=0x10000 %t.o 2>&1 | \ +# RUN: FileCheck -check-prefix=CHECK-ERROR %s +# +# Check success and failure cases of R_390_16 handling. + +# jitlink-check: *{8}P = X + +# CHECK-ERROR: relocation target "X" {{.*}} is out of range of Pointer16 fixup + + .text + .section .text.main + .globl main + .p2align 4 + .type main,@function +main: + br %r14 +.Lfunc_end0: + .size main, .Lfunc_end0-main + + .type P,@object + .data + .globl P + .p2align 1 +P: + .short 0 + .short 0 + .short 0 + .short X # Using byte here generates R_390_16. + .size P, 8 + diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s new file mode 100644 index 0000000000000..2b3122b91ff5e --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s @@ -0,0 +1,32 @@ +# REQUIRES: system-linux +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -filetype=obj -o %t.o %s +# RUN: llvm-jitlink -noexec -abs X=0x12345678 -check=%s %t.o +# +# RUN: not llvm-jitlink -noexec -abs X=0x123456789 %t.o 2>&1 | \ +# RUN: FileCheck -check-prefix=CHECK-ERROR %s +# +# Check success and failure cases of R_390_32 handling. + +# jitlink-check: *{8}P = X + +# CHECK-ERROR: relocation target "X" {{.*}} is out of range of Pointer32 fixup + + .text + .section .text.main + .globl main + .p2align 4 + .type main,@function +main: + br %r14 +.Lfunc_end0: + .size main, .Lfunc_end0-main + + .type P,@object + .data + .globl P + .p2align 2 +P: + .long 0 + .long X # Using long here generates R_390_32. + .size P, 8 diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs64.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs64.s new file mode 100644 index 0000000000000..63d2a1a539aeb --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs64.s @@ -0,0 +1,28 @@ +# REQUIRES: system-linux +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -filetype=obj -o %t.o %s +# RUN: llvm-jitlink -noexec -abs X=0xffffffffffffffff -check=%s %t.o +# +# Check success and failure cases of R_390_64 handling. + +# jitlink-check: *{8}P = X + +# CHECK-ERROR: relocation target "X" {{.*}} is out of range of Pointer64 fixup + + .text + .section .text.main + .globl main + .p2align 4 + .type main,@function +main: + br %r14 +.Lfunc_end0: + .size main, .Lfunc_end0-main + + .type P,@object + .data + .globl P + .p2align 4 +P: + .quad X # Using quad here generates R_390_64. + .size P, 8 diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s new file mode 100644 index 0000000000000..6b9d9503035f5 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s @@ -0,0 +1,38 @@ +# REQUIRES: system-linux +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -filetype=obj -o %t.o %s +# RUN: llvm-jitlink -noexec -abs X=0xFF -check=%s %t.o + +# RUN: not llvm-jitlink -noexec -abs X=0x100 %t.o 2>&1 | \ +# RUN: FileCheck -check-prefix=CHECK-ERROR %s +# +# Check success and failure cases of R_390_8 handling. + +# jitlink-check: *{8}P = X + +# CHECK-ERROR: relocation target "X" {{.*}} is out of range of Pointer8 fixup + + .text + .section .text.main + .globl main + .p2align 4 + .type main,@function +main: + br %r14 +.Lfunc_end0: + .size main, .Lfunc_end0-main + + .type P,@object + .data + .globl P +P: + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte X # Using byte here generates R_390_8. + .size P, 8 + diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s new file mode 100644 index 0000000000000..2b4c3d2102231 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s @@ -0,0 +1,82 @@ +# REQUIRES: system-linux +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -filetype=obj -o %t/elf_pic_reloc.o %s +# +# RUN: llvm-jitlink -noexec \ +# RUN: -slab-allocate 100Kb -slab-address 0xfff00000 -slab-page-size 4096 \ +# RUN: -abs external_data=0x1 \ +# RUN: -abs extern_out_of_range32=0x7fff00000000 \ +# RUN: -abs extern_in_range32=0xffe00000 \ +# RUN: -check %s %t/elf_pic_reloc.o + + .text + .section .text.main + .globl main + .p2align 4 + .type main,@function +main: + br %r14 + .size main, .-main + + .globl named_func + .p2align 4 + .type named_func,@function +named_func: + br %r14 + .size named_func, .-named_func + +# Check R_390_PLT32DBL handling with a call to a local function in the text +# section. This produces a Branch32 edge that is resolved like a regular +# BranchPCRelPLT32dbl(no PLT entry created). +# +# jitlink-check: decode_operand(test_call_local, 1) = \ +# jitlink-check: named_func - test_call_local + .globl test_call_local + .p2align 4 + .type test_call_local,@function +test_call_local: + brasl %r14, named_func@PLT + + .size test_call_local, .-test_call_local + +# Check R_390_PLT32dbl(BranchPCRelPLT32dbl) handling with a call to an +# external via PLT. This produces a Branch32ToStub edge, because externals are +# not defined locally. As the target is out-of-range from the callsite, +# the edge keeps using its PLT entry. +# +# jitlink-check: decode_operand(test_call_extern_plt, 1) = \ +# jitlink-check: stub_addr(elf_pic_reloc.o, extern_out_of_range32) - \ +# jitlink-check: test_call_extern_plt +# jitlink-check: *{8}(got_addr(elf_pic_reloc.o, extern_out_of_range32)) = \ +# jitlink-check: extern_out_of_range32 + .globl test_call_extern_plt + .p2align 4 + .type test_call_extern_plt,@function +test_call_extern_plt: + brasl %r14, extern_out_of_range32@plt + + .size test_call_extern_plt, .-test_call_extern_plt + +# Check R_390_PLT32(BranchPCRelPLT32dbl) handling with a call to an external. +# This produces a Branch32ToStub edge, because externals are not defined +# locally. During resolution, the target turns out to be in-range from the +# callsite. +### TODO: edge can be relaxed in post-allocation optimization, it will then +### require: +### jitlink-check: decode_operand(test_call_extern, 1) = \ +### jitlink-check: extern_in_range32 - test_call_extern +# +# Same as test_call_extern_plt(no-optimization) +# jitlink-check: decode_operand(test_call_extern, 1) = \ +# jitlink-check: stub_addr(elf_pic_reloc.o, extern_in_range32) - \ +# jitlink-check: test_call_extern +# jitlink-check: *{8}(got_addr(elf_pic_reloc.o, extern_in_range32)) = \ +# jitlink-check: extern_in_range32 + .globl test_call_extern + .p2align 4 + .type test_call_extern,@function +test_call_extern: + brasl %r14, extern_in_range32@plt + .size test_call_extern, .-test_call_extern + diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s new file mode 100644 index 0000000000000..3a5ebf9f3ba70 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s @@ -0,0 +1,28 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -filetype=obj -o %t.o %s +# +# RUN: llvm-jitlink -noexec -abs DISP=0xFFF -check=%s %t.o + +# RUN: not llvm-jitlink -noexec -abs DISP=0x1000 %t.o 2>&1 | \ +# RUN: FileCheck -check-prefix=CHECK-ERROR %s +# +# Check success and failure cases of R_390_12 handling. + +# CHECK-ERROR: relocation target "DISP" {{.*}} is out of range of +# CHECK-ERROR: Pointer12 fixup + +# jitlink-check: decode_operand(main, 2) = DISP + .text + .section .text.main + .globl main + .p2align 4 + .type main,@function +main: + .reloc .+2, R_390_12, DISP + l %r6, 0(%r7,%r8) + br %r14 +.Lfunc_end0: + .size main, .Lfunc_end0-main + diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s new file mode 100644 index 0000000000000..e6d22aff78f50 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s @@ -0,0 +1,31 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -filetype=obj -o %t.o %s +# +# RUN: llvm-jitlink -noexec -abs DISP=0x7FFFF -check=%s %t.o + +# RUN: not llvm-jitlink -noexec -abs DISP=0x80000 %t.o 2>&1 | \ +# RUN: FileCheck -check-prefix=CHECK-ERROR %s + +# RUN: not llvm-jitlink -noexec -abs DISP=0xFFFFF %t.o 2>&1 | \ +# RUN: FileCheck -check-prefix=CHECK-ERROR %s +# +# Check success and failure cases of R_390_20 handling. + +# CHECK-ERROR: relocation target "DISP" {{.*}} is out of range of +# CHECK-ERROR: Pointer20 fixup + +# jitlink-check: decode_operand(main, 2) = DISP + .text + .section .text.main + .globl main + .p2align 4 + .type main,@function +main: + .reloc .+2, R_390_20, DISP + lg %r6, 0(%r7,%r8) + br %r14 +.Lfunc_end0: + .size main, .Lfunc_end0-main + diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_got.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_got.s new file mode 100644 index 0000000000000..7da48cfa704e2 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_got.s @@ -0,0 +1,244 @@ +# REQUIRES: system-linux +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -filetype=obj -o %t/elf_reloc.o %s +# +# RUN: llvm-jitlink -noexec \ +# RUN: -slab-allocate 100Kb -slab-address 0x6ff00000 -slab-page-size 4096 \ +# RUN: -abs foo=0x6ff04040 \ +# RUN: -abs bar=0x6ff04048 \ +# RUN: %t/elf_reloc.o -check %s + +# Verifying GOT related relocations. + + .text + .globl main + .type main,@function +main: +# jitlink-check: decode_operand(main, 1) = _GLOBAL_OFFSET_TABLE_ - main + larl %r12, _GLOBAL_OFFSET_TABLE_ + .globl test_gotent_foo +test_gotent_foo: +# jitlink-check: decode_operand(test_gotent_foo, 1) = \ +# jitlink-check: (got_addr(elf_reloc.o, foo) - test_gotent_foo) + .reloc .+2, R_390_GOTENT, foo+2 + larl %r1, 0 + .size test_gotent_foo, .-test_gotent_foo + + .globl test_gotent_bar +test_gotent_bar: +# jitlink-check: decode_operand(test_gotent_bar, 1) = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - test_gotent_bar) + .reloc .+2, R_390_GOTENT, bar+2 + larl %r1, 0 + .size test_gotent_bar, .-test_gotent_bar + + .globl test_gotpltent_foo +test_gotpltent_foo: +# jitlink-check: decode_operand(test_gotpltent_foo, 1) = \ +# jitlink-check: (got_addr(elf_reloc.o, foo) - test_gotpltent_foo) + .reloc .+2, R_390_GOTPLTENT, foo+2 + larl %r1, 0 + .size test_gotpltent_foo, .-test_gotpltent_foo + + .globl test_gotpltent_bar +test_gotpltent_bar: +# jitlink-check: decode_operand(test_gotpltent_bar, 1) = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - test_gotpltent_bar) + .reloc .+2, R_390_GOTPLTENT, bar+2 + larl %r1, 0 + .size test_gotpltent_bar, .-test_gotpltent_bar + + .globl test_got12_foo +test_got12_foo: +# jitlink-check: decode_operand(test_got12_foo, 2) = \ +# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) + .reloc .+2, R_390_GOT12, foo + l %r1, 0(%r12) + .size test_got12_foo, .-test_got12_foo + + .globl test_got12_bar +test_got12_bar: +# jitlink-check: decode_operand(test_got12_bar, 2) = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) + .reloc .+2, R_390_GOT12, bar + l %r1, 0(%r12) + .size test_got12_bar, .-test_got12_bar + + .globl test_gotplt12_foo +test_gotplt12_foo: +# jitlink-check: decode_operand(test_gotplt12_foo, 2) = \ +# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) + .reloc .+2, R_390_GOTPLT12, foo + l %r1, 0(%r12) + .size test_gotplt12_foo, .-test_gotplt12_foo + + .globl test_gotplt12_bar +test_gotplt12_bar: +# jitlink-check: decode_operand(test_gotplt12_bar, 2) = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) + .reloc .+2, R_390_GOTPLT12, bar + l %r1, 0(%r12) + .size test_gotplt12_bar, .-test_gotplt12_bar + + .globl test_got20_foo +test_got20_foo: +# jitlink-check: decode_operand(test_got20_foo, 2) = \ +# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) + .reloc .+2, R_390_GOT20, foo + lg %r1, 0(%r12) + .size test_got20_foo, .-test_got20_foo + + .globl test_got20_bar +test_got20_bar: +# jitlink-check: decode_operand(test_got20_bar, 2) = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) + .reloc .+2, R_390_GOT20, bar + lg %r1, 0(%r12) + .size test_got20_bar, .-test_got20_bar + + .globl test_gotplt20_foo +test_gotplt20_foo: +# jitlink-check: decode_operand(test_gotplt20_foo, 2) = \ +# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) + .reloc .+2, R_390_GOTPLT20, foo + lg %r1, 0(%r12) + .size test_gotplt20_foo, .-test_gotplt20_foo + + .globl test_gotplt20_bar +test_gotplt20_bar: +# jitlink-check: decode_operand(test_gotplt20_bar, 2) = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) + .reloc .+2, R_390_GOTPLT20, bar + lg %r1, 0(%r12) + .size test_gotplt20_bar, .-test_gotplt20_bar + br %r14 + .size main, .-main + + .data + .globl test_got16_foo +# jitlink-check: *{2}test_got16_foo = \ +# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) +test_got16_foo: + .reloc ., R_390_GOT16, foo + .space 2 + .size test_got16_foo, .-test_got16_foo + + .globl test_got16_bar +# jitlink-check: *{2}test_got16_bar = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) +test_got16_bar: + .reloc ., R_390_GOT16, bar + .space 2 + .size test_got16_bar, .-test_got16_bar + + .globl test_gotplt16_foo +# jitlink-check: *{2}test_gotplt16_foo = \ +# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) +test_gotplt16_foo: + .reloc ., R_390_GOTPLT16, foo + .space 2 + .size test_gotplt16_foo, .-test_gotplt16_foo + + .globl test_gotplt16_bar +# jitlink-check: *{2}test_gotplt16_bar = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) +test_gotplt16_bar: + .reloc ., R_390_GOTPLT16, bar + .space 2 + .size test_gotplt16_bar, .-test_gotplt16_bar + + .globl test_got32_foo +# jitlink-check: *{4}test_got32_foo = \ +# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) +test_got32_foo: + .reloc ., R_390_GOT32, foo + .space 4 + .size test_got32_foo, .-test_got32_foo + + .globl test_got32_bar +# jitlink-check: *{4}test_got32_bar = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) +test_got32_bar: + .reloc ., R_390_GOT32, bar + .space 4 + .size test_got32_bar, .-test_got32_bar + + .globl test_gotplt32_foo +# jitlink-check: *{4}test_gotplt32_foo = \ +# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) +test_gotplt32_foo: + .reloc ., R_390_GOTPLT32, foo + .space 4 + .size test_gotplt32_foo, .-test_gotplt32_foo + + .globl test_gotplt32_bar +# jitlink-check: *{4}test_gotplt32_bar = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) +test_gotplt32_bar: + .reloc ., R_390_GOTPLT32, bar + .space 4 + .size test_gotplt32_bar, .-test_gotplt32_bar + + .globl test_got64_foo +# jitlink-check: *{8}test_got64_foo = \ +# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) +test_got64_foo: + .reloc ., R_390_GOT64, foo + .space 8 + .size test_got64_foo, .-test_got64_foo + + .globl test_got64_bar +# jitlink-check: *{8}test_got64_bar = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) +test_got64_bar: + .reloc ., R_390_GOT64, bar + .space 8 + .size test_got64_bar, .-test_got64_bar + + .globl test_gotplt64_foo +# jitlink-check: *{8}test_gotplt64_foo = \ +# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) +test_gotplt64_foo: + .reloc ., R_390_GOTPLT64, foo + .space 8 + .size test_gotplt64_foo, .-test_gotplt64_foo + + .globl test_gotplt64_bar +# jitlink-check: *{8}test_gotplt64_bar = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) +test_gotplt64_bar: + .reloc ., R_390_GOTPLT64, bar + .space 8 + .size test_gotplt64_bar, .-test_gotplt64_bar + + .globl test_gotpc_foo +# jitlink-check: *{4}test_gotpc_foo = _GLOBAL_OFFSET_TABLE_ - test_gotpc_foo +test_gotpc_foo: + .reloc ., R_390_GOTPC, foo + .space 4 + .size test_gotpc_foo, .-test_gotpc_foo + + .globl test_gotpc_bar +# jitlink-check: *{4}test_gotpc_bar = _GLOBAL_OFFSET_TABLE_ - test_gotpc_bar +test_gotpc_bar: + .reloc ., R_390_GOTPC, bar + .space 4 + .size test_gotpc_bar, .-test_gotpc_bar + + .globl test_gotpcdbl_foo +# jitlink-check: *{4}test_gotpcdbl_foo = \ +# jitlink-check: (_GLOBAL_OFFSET_TABLE_ - test_gotpcdbl_foo) >> 1 +test_gotpcdbl_foo: + .reloc ., R_390_GOTPCDBL, foo + .space 4 + .size test_gotpcdbl_foo, .-test_gotpcdbl_foo + + .globl test_gotpcdbl_bar +# jitlink-check: *{4}test_gotpcdbl_bar = \ +# jitlink-check: (_GLOBAL_OFFSET_TABLE_ - test_gotpcdbl_bar) >> 1 +test_gotpcdbl_bar: + .reloc ., R_390_GOTPCDBL, bar + .space 4 + .size test_gotpcdbl_bar, .-test_gotpcdbl_bar + diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_gotrel.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_gotrel.s new file mode 100644 index 0000000000000..bb1220d3780bb --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_gotrel.s @@ -0,0 +1,68 @@ +# REQUIRES: system-linux +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -filetype=obj -o %t/elf_reloc.o %s +# +# RUN: llvm-jitlink -noexec \ +# RUN: -slab-allocate 100Kb -slab-address 0x6ff00000 -slab-page-size 4096 \ +# RUN: -abs foo=0x6ff04080 \ +# RUN: -abs bar=0x6ff04040 \ +# RUN: %t/elf_reloc.o -check %s + + .text + .globl main + .type main,@function +main: + br %r14 + .size main, .-main + + .data + .globl test_gotoff16_bar +# jitlink-check: *{2}test_gotoff16_bar = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) +test_gotoff16_bar: + .reloc ., R_390_GOTOFF16, bar + .space 2 + .size test_gotoff16_bar, .-test_gotoff16_bar + + .globl test_pltoff16_foo +# jitlink-check: *{2}test_pltoff16_foo = \ +# jitlink-check: (stub_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) +test_pltoff16_foo: + .reloc ., R_390_PLTOFF16, foo + .space 2 + .size test_pltoff16_foo, .-test_pltoff16_foo + + + .globl test_gotoff32_bar +# jitlink-check: *{4}test_gotoff32_bar = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) +test_gotoff32_bar: + .reloc ., R_390_GOTOFF, bar + .space 4 + .size test_gotoff32_bar, .-test_gotoff32_bar + + .globl test_pltoff32_foo +# jitlink-check: *{4}test_pltoff32_foo = \ +# jitlink-check: (stub_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) +test_pltoff32_foo: + .reloc ., R_390_PLTOFF32, foo + .space 4 + .size test_pltoff32_foo, .-test_pltoff32_foo + + .globl test_gotoff64_bar +# jitlink-check: *{8}test_gotoff64_bar = \ +# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) +test_gotoff64_bar: + .reloc ., R_390_GOTOFF64, bar + .space 8 + .size test_gotoff64_bar, .-test_gotoff64_bar + + .globl test_pltoff64_foo +# jitlink-check: *{8}test_pltoff64_foo = \ +# jitlink-check: (stub_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) +test_pltoff64_foo: + .reloc ., R_390_PLTOFF64, foo + .space 8 + .size test_pltoff64_foo, .-test_pltoff64_foo + diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc.s new file mode 100644 index 0000000000000..4b3a65e53ab93 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc.s @@ -0,0 +1,20 @@ +# REQUIRES: system-linux +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -filetype=obj -o %t.o %s +# +# RUN: llvm-jitlink -noexec %t.o +# +# Check R_390_PC* handling. + + .text + .globl main + .type main,@function +main: + br %r14 + .size main, .-main + + .rodata + .short main-. # Generate R_390_PC16 relocation. + .long main-. # Generate R_390_PC32 relocation. + .quad main-. # Generate R_390_PC64 relocation. + diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc16.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc16.s new file mode 100644 index 0000000000000..47a7262902fd9 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc16.s @@ -0,0 +1,40 @@ +# REQUIRES: system-linux +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -defsym OFFSET=0x8000 -filetype=obj -o %t.o %s +# RUN: llvm-jitlink -noexec -abs OFFSET=0x8000 -check=%s %t.o +# +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -defsym OFFSET=0xFFFF -filetype=obj -o %t.o %s +# RUN: not llvm-jitlink -noexec -abs OFFSET=0xFFFF %t.o 2>&1 | \ +# RUN: FileCheck -check-prefix=CHECK-ERROR %s +# +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -defsym OFFSET=0x8001 -filetype=obj -o %t.o %s +# RUN: not llvm-jitlink -noexec -abs OFFSET=0x8001 %t.o 2>&1 | \ +# RUN: FileCheck -check-prefix=CHECK-ERROR %s +# +# jitlink-check: *{2}test_pc16 = OFFSET + +# CHECK-ERROR: {{.*}} is out of range of Delta16 fixup + + .text + .section .text.main + .globl main + .p2align 4 + .type main,@function +main: + br %r14 + .size main, .-main + + .globl test_pc16 +test_pc16: + .reloc test_pc16, R_390_PC16, .-OFFSET + .space 2 + .size test_pc16, .-test_pc16 + + .globl test_pc16dbl +test_pc16dbl: + .reloc test_pc16dbl, R_390_PC16DBL, .-(OFFSET + OFFSET) + .space 2 + .size test_pc16dbl, .-test_pc16dbl + diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc32.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc32.s new file mode 100644 index 0000000000000..cda90dbe5a316 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc32.s @@ -0,0 +1,40 @@ +# REQUIRES: system-linux +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -defsym OFFSET=0x80000000 -filetype=obj -o %t.o %s +# RUN: llvm-jitlink -noexec -abs OFFSET=0x80000000 -check=%s %t.o +# +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -defsym OFFSET=0xFFFFFFFF -filetype=obj -o %t.o %s +# RUN: not llvm-jitlink -noexec -abs OFFSET=0xFFFFFFFF %t.o 2>&1 | \ +# RUN: FileCheck -check-prefix=CHECK-ERROR %s +# +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -defsym OFFSET=0x80000001 -filetype=obj -o %t.o %s +# RUN: not llvm-jitlink -noexec -abs OFFSET=0x80000001 %t.o 2>&1 | \ +# RUN: FileCheck -check-prefix=CHECK-ERROR %s +# +# jitlink-check: *{4}test_pc32 = OFFSET + +# CHECK-ERROR: {{.*}} is out of range of Delta32 fixup + + .text + .section .text.main + .globl main + .p2align 4 + .type main,@function +main: + br %r14 + .size main, .-main + + .globl test_pc32 +test_pc32: + .reloc test_pc32, R_390_PC32, .-OFFSET + .space 4 + .size test_pc32, .-test_pc32 + + .globl test_pc32dbl +test_pc32dbl: + .reloc test_pc32dbl, R_390_PC32DBL, .-(OFFSET + OFFSET) + .space 4 + .size test_pc32dbl, .-test_pc32dbl + diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc64.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc64.s new file mode 100644 index 0000000000000..0d33ae2976de5 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc64.s @@ -0,0 +1,34 @@ +# REQUIRES: system-linux +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -filetype=obj -o %t/elf_reloc.o %s +# +# RUN: llvm-jitlink -noexec \ +# RUN: -slab-allocate 100Kb -slab-address 0xffff0000 -slab-page-size 4096 \ +# RUN: -abs external_data=0x1 \ +# RUN: -abs foo=0x6ff04040 \ +# RUN: -abs bar=0x6ff04048 \ +# RUN: -check %s %t/elf_reloc.o + + .text + .section .text.main + .globl main + .p2align 4 + .type main,@function +main: + br %r14 + .size main, .-main + + .globl test_pc64_foo +# jitlink-check: *{8}test_pc64_foo = foo - test_pc64_foo +test_pc64_foo: + .reloc ., R_390_PC64, foo + .space 8 + .size test_pc64_foo, .-test_pc64_foo + + .globl test_pc64_bar +# jitlink-check: *{8}test_pc64_bar = bar - test_pc64_bar +test_pc64_bar: + .reloc ., R_390_PC64, bar + .space 8 + .size test_pc64_bar, .-test_pc64_bar diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pcdbl.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pcdbl.s new file mode 100644 index 0000000000000..efe8357e76bef --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pcdbl.s @@ -0,0 +1,84 @@ +# REQUIRES: system-linux +# RUN: llvm-mc -triple=systemz-unknown-linux -mcpu=z16 -position-independent \ +# RUN: -defsym OFF12=0xffe -defsym OFF16=4 -defsym OFF24=6 \ +# RUN: -defsym OFF32=6 -filetype=obj -o %t.o %s +# +# RUN: llvm-jitlink -noexec -abs OFF12=0xffe -abs OFF16=4 -abs OFF24=6 \ +# RUN: -abs OFF32=6 -check=%s %t.o +# +# RUN: llvm-mc -triple=systemz-unknown-linux -mcpu=z16 -position-independent \ +# RUN: -defsym OFF12=6 -defsym OFF16=0xfffe -defsym OFF24=6 \ +# RUN: -defsym OFF32=6 -filetype=obj -o %t.o %s +# +# RUN: llvm-jitlink -noexec -abs OFF12=6 -abs OFF16=0xfffe -abs OFF24=6 \ +# RUN: -abs OFF32=6 -check=%s %t.o +# +# RUN: llvm-mc -triple=systemz-unknown-linux -mcpu=z16 -position-independent \ +# RUN: -defsym OFF12=6 -defsym OFF16=4 -defsym OFF24=0xfffffe \ +# RUN: -defsym OFF32=6 -filetype=obj -o %t.o %s +# +# RUN: llvm-jitlink -noexec -abs OFF12=6 -abs OFF16=4 -abs OFF24=0xfffffe \ +# RUN: -abs OFF32=6 -check=%s %t.o +# +# RUN: llvm-mc -triple=systemz-unknown-linux -mcpu=z16 -position-independent \ +# RUN: -defsym OFF12=6 -defsym OFF16=4 -defsym OFF24=6 \ +# RUN: -defsym OFF32=0xffffffc8 -filetype=obj -o %t.o %s +# +# RUN: llvm-jitlink -noexec -abs OFF12=6 -abs OFF16=4 -abs OFF24=6 \ +# RUN: -abs OFF32=0xffffffc8 -check=%s %t.o + +# Check R_390_PC*dbl relocations. + + .text + .section .text.main + .globl main + .p2align 4 + .type main,@function +main: + br %r14 + .size main, .-main + +# R_390_PC16DBL +# jitlink-check: *{2}(test_pc16dbl + 2) = (OFF16 >> 1) + .globl test_pc16dbl + .p2align 3 +test_pc16dbl: + je .Lpc16dbl + .space OFF16 - 4 +.Lpc16dbl: + jne test_pc16dbl + .size test_pc16dbl,.-test_pc16dbl + +# R_390_PC32DBL +# jitlink-check: *{4}(test_pc32dbl + 2) = (OFF32 >> 1) + .globl test_pc32dbl + .p2align 3 +test_pc32dbl: + jge .Lpc32dbl + .space OFF32 - 6 +.Lpc32dbl: + jgne test_pc32dbl + .size test_pc32dbl,.-test_pc32dbl + +# R_390_PC12DBL +# jitlink-check: ((*{2} (test_pc12dbl + 1)) & 0x0fff) = (OFF12 >> 1) + .globl test_pc12dbl + .p2align 4 +test_pc12dbl: + bprp 0, .Lpc12dbl, 0 + .space OFF12 - 6 +.Lpc12dbl: + bprp 0, test_pc12dbl, 0 + .size test_pc12dbl,.-test_pc12dbl + +# R_390_PC24DBL +# jitlink-check: ((*{4} (test_pc24dbl + 2)) & 0x0ffffff) = (OFF24 >> 1) + .globl test_pc24dbl + .p2align 4 +test_pc24dbl: + bprp 0, 0, .Lpc24dbl + .space OFF24 - 6 +.Lpc24dbl: + bprp 0, 0, test_pc24dbl + .size test_pc24dbl,.-test_pc24dbl + diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_plt.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_plt.s new file mode 100644 index 0000000000000..47f064b45816a --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_plt.s @@ -0,0 +1,71 @@ +# REQUIRES: system-linux +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -filetype=obj -o %t/elf_reloc.o %s +# +# RUN: llvm-jitlink -noexec \ +# RUN: -slab-allocate 100Kb -slab-address 0xffff0000 -slab-page-size 4096 \ +# RUN: -abs external_data=0x1 \ +# RUN: -abs foo=0x6ff04040 \ +# RUN: -abs bar=0x6ff04048 \ +# RUN: -check %s %t/elf_reloc.o + +# Check R_390_PLT32/64 relocations. + + .text + .section .text.main + .globl main + .p2align 4 + .type main,@function +main: + br %r14 + .size main, .-main + + .globl test_plt32_foo +# jitlink-check: *{4}test_plt32_foo = \ +# jitlink-check: stub_addr(elf_reloc.o, foo) - test_plt32_foo +test_plt32_foo: + .reloc ., R_390_PLT32, foo + .space 4 + .size test_plt32_foo, .-test_plt32_foo + + .globl test_plt32_bar +# jitlink-check: *{4}test_plt32_bar = \ +# jitlink-check: stub_addr(elf_reloc.o, bar) - test_plt32_bar +test_plt32_bar: + .reloc ., R_390_PLT32, bar + .space 4 + .size test_plt32_bar, .-test_plt32_bar + + .globl test_plt64_foo +# jitlink-check: *{8}test_plt64_foo = \ +# jitlink-check: stub_addr(elf_reloc.o, foo) - test_plt64_foo +test_plt64_foo: + .reloc ., R_390_PLT64, foo + .space 8 + .size test_plt64_foo, .-test_plt64_foo + + .globl test_plt64_bar +# jitlink-check: *{8}test_plt64_bar = \ +# jitlink-check: stub_addr(elf_reloc.o, bar) - test_plt64_bar +test_plt64_bar: + .reloc ., R_390_PLT64, bar + .space 8 + .size test_plt64_bar, .-test_plt64_bar + + .globl test_plt32dbl_foo +# jitlink-check: *{4}test_plt32dbl_foo = \ +# jitlink-check: (stub_addr(elf_reloc.o, foo) - test_plt32dbl_foo) >> 1 +test_plt32dbl_foo: + .reloc ., R_390_PLT32DBL, foo + .space 4 + .size test_plt32dbl_foo, .-test_plt32dbl_foo + + .globl test_plt32dbl_bar +# jitlink-check: *{4}test_plt32dbl_bar = \ +# jitlink-check: (stub_addr(elf_reloc.o, bar) - test_plt32dbl_bar) >> 1 +test_plt32dbl_bar: + .reloc ., R_390_PLT32DBL, bar + .space 4 + .size test_plt32dbl_bar, .-test_plt32dbl_bar + diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pltdbl.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pltdbl.s new file mode 100644 index 0000000000000..c36a77684008a --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pltdbl.s @@ -0,0 +1,51 @@ +# REQUIRES: system-linux +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ +# RUN: -mcpu=z16 -filetype=obj -o %t/elf_reloc.o %s + +# RUN: llvm-jitlink -noexec \ +# RUN: -abs external_addr12=0xffe \ +# RUN: -abs external_addr16=0xfffe \ +# RUN: -abs external_addr24=0xffffe \ +# RUN: %t/elf_reloc.o -check %s + + + .text + .section .text.main + .globl main + .p2align 4 + .type main,@function +main: + br %r14 + .size main, .-main + +# R_390_PLT16DBL +# jitlink-check: *{2}(test_plt16dbl + 4) = \ +# jitlink-check: (stub_addr(elf_reloc.o, external_addr16) - \ +# jitlink-check: test_plt16dbl) >> 1 + .globl test_plt16dbl + .p2align 4 +test_plt16dbl: + bpp 0, external_addr16@plt, 0 + .size test_plt16dbl,.-test_plt16dbl + +# R_390_PLT12DBL +# jitlink-check: ((*{2}(test_plt12dbl + 1)) & 0x0fff) = \ +# jitlink-check: (stub_addr(elf_reloc.o, external_addr12) - \ +# jitlink-check: test_plt12dbl) >> 1 + .globl test_plt12dbl + .p2align 4 +test_plt12dbl: + bprp 0, external_addr12@plt, 0 + .size test_plt12dbl,.-test_plt12dbl + +# R_390_PLT24DBL +# jitlink-check: ((*{4}(test_plt24dbl + 2)) & 0x0ffffff) = \ +# jitlink-check: (stub_addr(elf_reloc.o, external_addr24) - \ +# jitlink-check: test_plt24dbl) >> 1 + .globl test_plt24dbl + .p2align 4 +test_plt24dbl: + bprp 0, 0, external_addr24@plt + .size test_plt24dbl,.-test_plt24dbl + diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/lit.local.cfg b/llvm/test/ExecutionEngine/JITLink/systemz/lit.local.cfg new file mode 100644 index 0000000000000..caf81b69c06fd --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/systemz/lit.local.cfg @@ -0,0 +1,2 @@ +if not "SystemZ" in config.root.targets: + config.unsupported = True diff --git a/llvm/test/ExecutionEngine/lit.local.cfg b/llvm/test/ExecutionEngine/lit.local.cfg index c748de14c8409..840ee60d2cf1d 100644 --- a/llvm/test/ExecutionEngine/lit.local.cfg +++ b/llvm/test/ExecutionEngine/lit.local.cfg @@ -1,4 +1,4 @@ -if config.root.native_target in ['Sparc', 'SystemZ', 'Hexagon', 'RISCV']: +if config.root.native_target in ['Sparc', 'Hexagon', 'RISCV']: config.unsupported = True # ExecutionEngine tests are not expected to pass in a cross-compilation setup. From 04235320662f8292fc81e0d8577701c3585686e8 Mon Sep 17 00:00:00 2001 From: anoopkg6 Date: Tue, 17 Jun 2025 20:16:37 +0200 Subject: [PATCH 02/14] Resolve issues with conflicts --- .../ExecutionEngine/JITLink/ELF_systemz.h | 4 ++-- .../ExecutionEngine/JITLink/ELF_systemz.cpp | 23 +++++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h index c78bc7cc1f499..a996dfd9543df 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h @@ -25,8 +25,8 @@ namespace jitlink { /// Note: The graph does not take ownership of the underlying buffer, nor copy /// its contents. The caller is responsible for ensuring that the object buffer /// outlives the graph. -Expected> -createLinkGraphFromELFObject_systemz(MemoryBufferRef ObjectBuffer); +Expected> createLinkGraphFromELFObject_systemz( + MemoryBufferRef ObjectBuffer, std::shared_ptr SSP); /// jit-link the given object buffer, which must be a ELF systemz relocatable /// object file. diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp index 6d598d62b1fc2..47d2d4651f881 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp @@ -64,7 +64,8 @@ class ELFJITLinker_systemz : public JITLinker { auto DefineExternalGOTSymbolIfPresent = createDefineExternalSectionStartAndEndSymbolsPass( [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc { - if (Sym.getName() == ELFGOTSymbolName) + if (Sym.getName() != nullptr && + *Sym.getName() == ELFGOTSymbolName) if (auto *GOTSection = G.findSectionByName( systemz::GOTTableManager::getSectionName())) { GOTSymbol = &Sym; @@ -90,7 +91,7 @@ class ELFJITLinker_systemz : public JITLinker { // Check for an existing defined symbol. for (auto *Sym : GOTSection->symbols()) - if (Sym->getName() == ELFGOTSymbolName) { + if (Sym->getName() != nullptr && *Sym->getName() == ELFGOTSymbolName) { GOTSymbol = Sym; return Error::success(); } @@ -112,7 +113,7 @@ class ELFJITLinker_systemz : public JITLinker { // we just need to point the GOT symbol at some address in this graph. if (!GOTSymbol) { for (auto *Sym : G.external_symbols()) { - if (Sym->getName() == ELFGOTSymbolName) { + if (Sym->getName() != nullptr && *Sym->getName() == ELFGOTSymbolName) { auto Blocks = G.blocks(); if (!Blocks.empty()) { G.makeAbsolute(*Sym, (*Blocks.begin())->getAddress()); @@ -365,14 +366,16 @@ class ELFLinkGraphBuilder_systemz public: ELFLinkGraphBuilder_systemz(StringRef FileName, - const object::ELFFile &Obj, Triple TT, - SubtargetFeatures Features) - : ELFLinkGraphBuilder(Obj, std::move(TT), std::move(Features), - FileName, systemz::getEdgeKindName) {} + const object::ELFFile &Obj, + std::shared_ptr SSP, + Triple TT, SubtargetFeatures Features) + : ELFLinkGraphBuilder(Obj, std::move(SSP), std::move(TT), + std::move(Features), FileName, + systemz::getEdgeKindName) {} }; -Expected> -createLinkGraphFromELFObject_systemz(MemoryBufferRef ObjectBuffer) { +Expected> createLinkGraphFromELFObject_systemz( + MemoryBufferRef ObjectBuffer, std::shared_ptr SSP) { LLVM_DEBUG({ dbgs() << "Building jitlink graph for new input " << ObjectBuffer.getBufferIdentifier() << "...\n"; @@ -391,7 +394,7 @@ createLinkGraphFromELFObject_systemz(MemoryBufferRef ObjectBuffer) { auto &ELFObjFile = cast>(**ELFObj); return ELFLinkGraphBuilder_systemz( - (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), + (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), std::move(SSP), (*ELFObj)->makeTriple(), std::move(*Features)) .buildGraph(); } From 72ff4e38533f1a9101365408590d6d5ccefb31fc Mon Sep 17 00:00:00 2001 From: anoopkg6 Date: Tue, 17 Jun 2025 21:26:26 +0200 Subject: [PATCH 03/14] Fix build error --- .../llvm/ExecutionEngine/JITLink/systemz.h | 3 +-- llvm/lib/ExecutionEngine/JITLink/systemz.cpp | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h index e1498ff820fe6..d63446f35fffd 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h @@ -992,16 +992,15 @@ class GOTTableManager : public TableManager { case systemz::Delta64FromGOT: case systemz::Delta12JumpSlot: case systemz::Delta16JumpSlot: + case systemz::Delta20JumpSlot: case systemz::Delta32JumpSlot: case systemz::Delta64JumpSlot: - case systemz::Delta20JumpSlot: { case systemz::DeltaPCRelGOT: case systemz::DeltaPCRelGOTdbl: case systemz::PCRel32GOTEntry: case systemz::PCRel32JumpSlot: KindToSet = E.getKind(); break; - } default: return false; } diff --git a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp index 36ba857d8f5c4..c9276bedafe99 100644 --- a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp @@ -22,9 +22,20 @@ const char NullPointerContent[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const char Pointer64JumpStubContent[14] = { - static_cast(0xC0), 0x10, 0x00, 0x00, 0x00, 0x00, // larl r1 - static_cast(0xE3), 0x10, 0x10, 0x00, 0x00, 0x04, // LG 1, 0(1) - static_cast(0x07), 0xF1, // BCR 15, 1 + static_cast(0xC0u), + 0x10, + 0x00, + 0x00, + 0x00, + 0x00, // larl r1 + static_cast(0xE3u), + 0x10, + 0x10, + 0x00, + 0x00, + 0x04, // LG 1, 0(1) + static_cast(0x07u), + static_cast(0xF1u), // BCR 15, 1 }; const char *getEdgeKindName(Edge::Kind R) { From 7ec023ed49010ec23682fde7927fadc53b644f98 Mon Sep 17 00:00:00 2001 From: anoopkg6 Date: Thu, 17 Jul 2025 00:53:54 +0200 Subject: [PATCH 04/14] Fixed jitlink-check: CHECK-ERROR - error message format changed. --- .../ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s | 2 +- .../ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s | 2 +- .../ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s | 2 +- .../ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s | 2 +- .../ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s index 3d1484acaf9ae..04e828685c040 100644 --- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s @@ -10,7 +10,7 @@ # jitlink-check: *{8}P = X -# CHECK-ERROR: relocation target "X" {{.*}} is out of range of Pointer16 fixup +# CHECK-ERROR: relocation target {{.*}} (X) is out of range of Pointer16 fixup .text .section .text.main diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s index 2b3122b91ff5e..1a63acdb63d57 100644 --- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s @@ -10,7 +10,7 @@ # jitlink-check: *{8}P = X -# CHECK-ERROR: relocation target "X" {{.*}} is out of range of Pointer32 fixup +# CHECK-ERROR: relocation target {{.*}} (X) is out of range of Pointer32 fixup .text .section .text.main diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s index 6b9d9503035f5..5f23f289140a6 100644 --- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s @@ -10,7 +10,7 @@ # jitlink-check: *{8}P = X -# CHECK-ERROR: relocation target "X" {{.*}} is out of range of Pointer8 fixup +# CHECK-ERROR: relocation target {{.*}} (X) is out of range of Pointer8 fixup .text .section .text.main diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s index 3a5ebf9f3ba70..cf12cdc987ce3 100644 --- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s @@ -10,7 +10,7 @@ # # Check success and failure cases of R_390_12 handling. -# CHECK-ERROR: relocation target "DISP" {{.*}} is out of range of +# CHECK-ERROR: relocation target {{.*}} (DISP) is out of range of # CHECK-ERROR: Pointer12 fixup # jitlink-check: decode_operand(main, 2) = DISP diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s index e6d22aff78f50..5c7de535cf8b4 100644 --- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s @@ -13,7 +13,7 @@ # # Check success and failure cases of R_390_20 handling. -# CHECK-ERROR: relocation target "DISP" {{.*}} is out of range of +# CHECK-ERROR: relocation target {{.*}} (DISP) is out of range of # CHECK-ERROR: Pointer20 fixup # jitlink-check: decode_operand(main, 2) = DISP From a52657a9153ddb483452916cbf75b01fc47f9781 Mon Sep 17 00:00:00 2001 From: anoopkg6 Date: Sat, 1 Nov 2025 21:22:52 +0100 Subject: [PATCH 05/14] Incorporate code review feedback --- .../llvm/ExecutionEngine/JITLink/systemz.h | 278 +++++------------- .../ExecutionEngine/JITLink/ELF_systemz.cpp | 77 ++--- llvm/lib/ExecutionEngine/JITLink/systemz.cpp | 92 +++--- 3 files changed, 140 insertions(+), 307 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h index d63446f35fffd..3f692e0ecc383 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h @@ -213,7 +213,7 @@ enum EdgeKind_systemz : Edge::Kind { /// Errors: /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section /// symbol was not been defined. - Delta64FromGOT, + RequestGOTAndTransformToDelta64FromGOT, /// A 32-bit GOT delta. /// @@ -227,7 +227,7 @@ enum EdgeKind_systemz : Edge::Kind { /// symbol was not been defined. /// - The result of the fixup expression must fit into an int32, otherwise /// an out-of-range error will be returned. - Delta32FromGOT, + RequestGOTAndTransformToDelta32FromGOT, /// A 16-bit GOT delta. /// @@ -241,7 +241,7 @@ enum EdgeKind_systemz : Edge::Kind { /// symbol was not been defined. /// - The result of the fixup expression must fit into an int16, otherwise /// an out-of-range error will be returned. - Delta16FromGOT, + RequestGOTAndTransformToDelta16FromGOT, /// A 32-bit PC-relative branch. /// @@ -257,7 +257,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression before shifting right by 1 must /// be multiple of 2, otherwise an alignment error will be returned. /// - BranchPCRelPLT32dbl, + DeltaPLT32dbl, /// A 24-bit PC-relative branch. /// @@ -270,7 +270,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression before shifting right by 1 must /// be multiple of 2, otherwise an alignment error will be returned. /// - BranchPCRelPLT24dbl, + DeltaPLT24dbl, /// A 16-bit PC-relative branch. /// @@ -283,7 +283,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression before shifting right by 1 must /// be multiple of 2, otherwise an alignment error will be returned. /// - BranchPCRelPLT16dbl, + DeltaPLT16dbl, /// A 12-bit PC-relative branch. /// @@ -296,14 +296,14 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression before shifting right by 1 must /// be multiple of 2, otherwise an alignment error will be returned. /// - BranchPCRelPLT12dbl, + DeltaPLT12dbl, /// A 64-bit PC-relative PLT address. /// /// Fixup expression: /// Fixup <- Target - Fixup + Addend : int64 /// - BranchPCRelPLT64, + DeltaPLT64, /// A 32-bit PC-relative PLT address. /// @@ -314,14 +314,13 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression must fit into an int32, otherwise /// an out-of-range error will be returned. /// - BranchPCRelPLT32, + DeltaPLT32, /// A 32-bit PC-relative branch to a pointer jump stub. /// Create a jump stub block that jumps via the pointer at the given symbol. /// /// Stub Content: - /// larl %r1, ptr - /// lg %r1, 0(%r1) + /// lgrl %r1, ptr /// j %r1 /// /// Fixup expression at offset 2 of branch Instruction: @@ -380,7 +379,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section /// symbol was not been defined. /// - Delta64GOT, + RequestGOTAndTransformToDelta64, /// A 32-bit GOT offset. /// @@ -393,7 +392,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression must fit into an int32, otherwise /// an out-of-range error will be returned. /// - Delta32GOT, + RequestGOTAndTransformToDelta32, /// A 20-bit GOT offset. /// @@ -406,7 +405,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression must fit into an int20, otherwise /// an out-of-range error will be returned. /// - Delta20GOT, + RequestGOTAndTransformToDelta20, /// A 16-bit GOT offset. /// @@ -419,7 +418,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression must fit into an int16, otherwise /// an out-of-range error will be returned. /// - Delta16GOT, + RequestGOTAndTransformToDelta16, /// A 12-bit GOT offset. /// @@ -432,7 +431,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression must fit into an int12, otherwise /// an out-of-range error will be returned. /// - Delta12GOT, + RequestGOTAndTransformToDelta12, /// A 32-bit PC rel. offset to GOT. /// @@ -445,7 +444,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression must fit into an int32, otherwise /// an out-of-range error will be returned. /// - DeltaPCRelGOT, + RequestGOTAndTransformToDelta32GOTBase, /// A 32-bit PC rel. offset to GOT shifted by 1. /// @@ -460,83 +459,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression before shifting right by 1 must /// be multiple of 2, otherwise an alignment error will be returned. /// - DeltaPCRelGOTdbl, - - /// A 64-bit offset to Jump Slot. - /// - /// Fixup expression: - /// Fixup <- Target - GOTBase + Addend : int64 - /// - /// Errors: - /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section - /// symbol was not been defined. - /// - Delta64JumpSlot, - - /// A 32-bit offset to Jump Slot. - /// - /// Fixup expression: - /// Fixup <- Target - GOTBase + Addend : int32 - /// - /// Errors: - /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section - /// symbol was not been defined. - /// - The result of the fixup expression must fit into an int32, otherwise - /// an out-of-range error will be returned. - /// - Delta32JumpSlot, - - /// A 20-bit offset to Jump Slot. - /// - /// Fixup expression: - /// Fixup <- Target - GOTBase + Addend : int20 - /// - /// Errors: - /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section - /// symbol was not been defined. - /// - The result of the fixup expression must fit into an int20, otherwise - /// an out-of-range error will be returned. - /// - Delta20JumpSlot, - - /// A 16-bit offset to Jump Slot. - /// - /// Fixup expression: - /// Fixup <- Target - GOTBase + Addend : int16 - /// - /// Errors: - /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section - /// symbol was not been defined. - /// - The result of the fixup expression must fit into an int16, otherwise - /// an out-of-range error will be returned. - /// - Delta16JumpSlot, - - /// A 12-bit offset to Jump Slot. - /// - /// Fixup expression: - /// Fixup <- Target - GOTBase + Addend : int12 - /// - /// Errors: - /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section - /// symbol was not been defined. - /// - The result of the fixup expression must fit into an int12, otherwise - /// an out-of-range error will be returned. - /// - Delta12JumpSlot, - - /// A 32-bit PC rel. offset to Jump Slot. - /// - /// Fixup expression: - /// Fixup <- (Target - Fixup + Addend) >> 1 : int32 - /// - /// Errors: - /// - The result of the fixup expression before shifting right by 1 must - /// fit into an int33, otherwise an out-of-range error will be returned. - /// - The result of the fixup expression before shifting right by 1 must - /// be multiple of 2, otherwise an alignment error will be returned. - /// - PCRel32JumpSlot, + RequestGOTAndTransformToDelta32GOTBasedbl, /// A 32-bit PC rel. to GOT entry >> 1. /// @@ -549,7 +472,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression before shifting right by 1 must /// be multiple of 2, otherwise an alignment error will be returned. /// - PCRel32GOTEntry, + RequestGOTAndTransformToDelta32dbl, }; @@ -592,7 +515,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, uint64_t Value = S + A; if (!LLVM_UNLIKELY(isUInt<32>(Value))) return makeTargetOutOfRangeError(G, B, E); - *(ubig32_t *)FixupPtr = Value; + write32be(FixupPtr, Value); break; } case Pointer20: { @@ -607,7 +530,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, uint64_t Value = S + A; if (!LLVM_UNLIKELY(isUInt<16>(Value))) return makeTargetOutOfRangeError(G, B, E); - *(ubig16_t *)FixupPtr = Value; + write16be(FixupPtr, Value); break; } case Pointer12: { @@ -626,28 +549,28 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, } case Delta64: { int64_t Value = S + A - P; - *(big64_t *)FixupPtr = Value; + write64be(FixupPtr, Value); break; } case Delta32: { int64_t Value = S + A - P; if (!LLVM_UNLIKELY(isInt<32>(Value))) return makeTargetOutOfRangeError(G, B, E); - *(big32_t *)FixupPtr = Value; + write32be(FixupPtr, Value); break; } case Delta16: { int64_t Value = S + A - P; if (!LLVM_UNLIKELY(isInt<16>(Value))) return makeTargetOutOfRangeError(G, B, E); - *(big16_t *)FixupPtr = Value; + write16be(FixupPtr, Value); break; } case NegDelta32: { int64_t Value = P + A - S; if (!LLVM_UNLIKELY(isInt<32>(Value))) return makeTargetOutOfRangeError(G, B, E); - *(big32_t *)FixupPtr = Value; + write32be(FixupPtr, Value); break; } case Delta32dbl: { @@ -689,35 +612,37 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, (read16be(FixupPtr) & 0xF000) | ((Value >> 1) & 0x0FFF)); break; } - case Delta64FromGOT: { + case RequestGOTAndTransformToDelta64FromGOT: { assert(GOTSymbol && "No GOT section symbol"); int64_t Value = S - GOTBase + A; - *(big64_t *)FixupPtr = Value; + write64be(FixupPtr, Value); break; } - case Delta32FromGOT: { + case RequestGOTAndTransformToDelta32FromGOT: { assert(GOTSymbol && "No GOT section symbol"); int64_t Value = S - GOTBase + A; if (!LLVM_UNLIKELY(isInt<32>(Value))) return makeTargetOutOfRangeError(G, B, E); - *(big32_t *)FixupPtr = Value; + write32be(FixupPtr, Value); break; } - case Delta16FromGOT: { + case RequestGOTAndTransformToDelta16FromGOT: { assert(GOTSymbol && "No GOT section symbol"); int64_t Value = S - GOTBase + A; if (!LLVM_UNLIKELY(isInt<16>(Value))) return makeTargetOutOfRangeError(G, B, E); - *(big16_t *)FixupPtr = Value; + write16be(FixupPtr, Value); break; } - case DeltaPCRelGOT: { + case RequestGOTAndTransformToDelta32GOTBase: { assert(GOTSymbol && "No GOT section symbol"); int64_t Value = GOTBase + A - P; - *(big32_t *)FixupPtr = Value; + if (!LLVM_UNLIKELY(isInt<32>(Value))) + return makeTargetOutOfRangeError(G, B, E); + write32be(FixupPtr, Value); break; } - case DeltaPCRelGOTdbl: { + case RequestGOTAndTransformToDelta32GOTBasedbl: { assert(GOTSymbol && "No GOT section symbol"); int64_t Value = (GOTBase + A - P); if (!LLVM_UNLIKELY(isInt<33>(Value))) @@ -727,7 +652,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, write32be(FixupPtr, Value >> 1); break; } - case BranchPCRelPLT32dbl: { + case DeltaPLT32dbl: { int64_t Value = (S + A - P); if (!LLVM_UNLIKELY(isInt<33>(Value))) return makeTargetOutOfRangeError(G, B, E); @@ -736,7 +661,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, write32be(FixupPtr, Value >> 1); break; } - case BranchPCRelPLT24dbl: { + case DeltaPLT24dbl: { int64_t Value = (S + A - P); if (!LLVM_UNLIKELY(isInt<25>(Value))) return makeTargetOutOfRangeError(G, B, E); @@ -745,7 +670,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, FixupPtr[2] = Value >> 1; break; } - case BranchPCRelPLT16dbl: { + case DeltaPLT16dbl: { int64_t Value = (S + A - P); if (!LLVM_UNLIKELY(isInt<17>(Value))) return makeTargetOutOfRangeError(G, B, E); @@ -754,7 +679,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, write16be(FixupPtr, Value >> 1); break; } - case BranchPCRelPLT12dbl: { + case DeltaPLT12dbl: { int64_t Value = (S + A - P); if (!LLVM_UNLIKELY(isInt<13>(Value))) return makeTargetOutOfRangeError(G, B, E); @@ -764,22 +689,22 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, (read16be(FixupPtr) & 0xF000) | ((Value >> 1) & 0x0FFF)); break; } - case BranchPCRelPLT64: { + case DeltaPLT64: { int64_t Value = (S + A - P); - *(big64_t *)FixupPtr = Value; + write64be(FixupPtr, Value); break; } - case BranchPCRelPLT32: { + case DeltaPLT32: { int64_t Value = (S + A - P); if (!LLVM_UNLIKELY(isInt<32>(Value))) return makeTargetOutOfRangeError(G, B, E); - *(big32_t *)FixupPtr = Value; + write32be(FixupPtr, Value); break; } case DeltaPLT64FromGOT: { assert(GOTSymbol && "No GOT section symbol"); int64_t Value = (S + A - GOTBase); - *(big64_t *)FixupPtr = Value; + write64be(FixupPtr, Value); break; } case DeltaPLT32FromGOT: { @@ -787,7 +712,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, int64_t Value = (S + A - GOTBase); if (!LLVM_UNLIKELY(isInt<32>(Value))) return makeTargetOutOfRangeError(G, B, E); - *(big32_t *)FixupPtr = Value; + write32be(FixupPtr, Value); break; } case DeltaPLT16FromGOT: { @@ -795,7 +720,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, int64_t Value = (S + A - GOTBase); if (!LLVM_UNLIKELY(isInt<16>(Value))) return makeTargetOutOfRangeError(G, B, E); - *(big16_t *)FixupPtr = Value; + write16be(FixupPtr, Value); break; } case Branch32dblToStub: { @@ -803,10 +728,10 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, if (!LLVM_UNLIKELY(isInt<33>(Value))) return makeTargetOutOfRangeError(G, B, E); char *AddrToPatch = FixupPtr + 2; - *(big32_t *)AddrToPatch = (Value >> 1); + write32be(AddrToPatch, Value >> 1); break; } - case PCRel32GOTEntry: { + case RequestGOTAndTransformToDelta32dbl: { int64_t Value = (S + A - P); if (!LLVM_UNLIKELY(isInt<33>(Value))) return makeTargetOutOfRangeError(G, B, E); @@ -815,21 +740,21 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, write32be(FixupPtr, Value >> 1); break; } - case Delta64GOT: { + case RequestGOTAndTransformToDelta64: { assert(GOTSymbol && "No GOT section symbol"); int64_t Value = S - GOTBase + A; - *(big64_t *)FixupPtr = Value; + write64be(FixupPtr, Value); break; } - case Delta32GOT: { + case RequestGOTAndTransformToDelta32: { assert(GOTSymbol && "No GOT section symbol"); uint64_t Value = S - GOTBase + A; if (!LLVM_UNLIKELY(isUInt<32>(Value))) return makeTargetOutOfRangeError(G, B, E); - *(big32_t *)FixupPtr = Value; + write32be(FixupPtr, Value); break; } - case Delta20GOT: { + case RequestGOTAndTransformToDelta20: { assert(GOTSymbol && "No GOT section symbol"); uint64_t Value = S - GOTBase + A; if (!LLVM_UNLIKELY(isInt<20>(Value))) @@ -838,15 +763,15 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, ((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4)); break; } - case Delta16GOT: { + case RequestGOTAndTransformToDelta16: { assert(GOTSymbol && "No GOT section symbol"); uint64_t Value = S - GOTBase + A; if (!LLVM_UNLIKELY(isUInt<16>(Value))) return makeTargetOutOfRangeError(G, B, E); - *(big16_t *)FixupPtr = Value; + write16be(FixupPtr, Value); break; } - case Delta12GOT: { + case RequestGOTAndTransformToDelta12: { assert(GOTSymbol && "No GOT section symbol"); uint64_t Value = S - GOTBase + A; if (!LLVM_UNLIKELY(isUInt<12>(Value))) @@ -854,54 +779,6 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, write16be(FixupPtr, (read16be(FixupPtr) & 0xF000) | Value); break; } - case Delta64JumpSlot: { - assert(GOTSymbol && "No GOT section symbol"); - uint64_t Value = S - GOTBase + A; - *(big64_t *)FixupPtr = Value; - break; - } - case Delta32JumpSlot: { - assert(GOTSymbol && "No GOT section symbol"); - uint64_t Value = S - GOTBase + A; - if (!LLVM_UNLIKELY(isUInt<32>(Value))) - return makeTargetOutOfRangeError(G, B, E); - *(big32_t *)FixupPtr = Value; - break; - } - case Delta20JumpSlot: { - assert(GOTSymbol && "No GOT section symbol"); - int64_t Value = S - GOTBase + A; - if (!LLVM_UNLIKELY(isInt<20>(Value))) - return makeTargetOutOfRangeError(G, B, E); - write32be(FixupPtr, (read32be(FixupPtr) & 0xF00000FF) | - ((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4)); - break; - } - case Delta16JumpSlot: { - assert(GOTSymbol && "No GOT section symbol"); - uint64_t Value = S - GOTBase + A; - if (!LLVM_UNLIKELY(isUInt<16>(Value))) - return makeTargetOutOfRangeError(G, B, E); - *(big16_t *)FixupPtr = Value; - break; - } - case Delta12JumpSlot: { - assert(GOTSymbol && "No GOT section symbol"); - uint64_t Value = S - GOTBase + A; - if (!LLVM_UNLIKELY(isUInt<13>(Value))) - return makeTargetOutOfRangeError(G, B, E); - write16be(FixupPtr, (read16be(FixupPtr) & 0xF000) | Value); - break; - } - case PCRel32JumpSlot: { - int64_t Value = S + A - P; - if (!LLVM_UNLIKELY(isInt<33>(Value))) - return makeTargetOutOfRangeError(G, B, E); - if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) - return makeAlignmentError(FixupAddress, Value, 2, E); - write32be(FixupPtr, Value >> 1); - break; - } default: return make_error( "In graph " + G.getName() + ", section " + B.getSection().getName() + @@ -922,8 +799,7 @@ inline ArrayRef getGOTEntryBlockContent(LinkGraph &G) { /// /// Contains the instruction sequence for an indirect jump via an in-memory /// pointer: -/// larl %r1, ptr -/// lg %r1, 0(%r1) +/// lgrl %r1, ptr /// j %r1 constexpr size_t StubEntrySize = 14; extern const char Pointer64JumpStubContent[StubEntrySize]; @@ -982,23 +858,17 @@ class GOTTableManager : public TableManager { return false; Edge::Kind KindToSet = Edge::Invalid; switch (E.getKind()) { - case systemz::Delta12GOT: - case systemz::Delta16GOT: - case systemz::Delta20GOT: - case systemz::Delta32GOT: - case systemz::Delta64GOT: - case systemz::Delta16FromGOT: - case systemz::Delta32FromGOT: - case systemz::Delta64FromGOT: - case systemz::Delta12JumpSlot: - case systemz::Delta16JumpSlot: - case systemz::Delta20JumpSlot: - case systemz::Delta32JumpSlot: - case systemz::Delta64JumpSlot: - case systemz::DeltaPCRelGOT: - case systemz::DeltaPCRelGOTdbl: - case systemz::PCRel32GOTEntry: - case systemz::PCRel32JumpSlot: + case systemz::RequestGOTAndTransformToDelta12: + case systemz::RequestGOTAndTransformToDelta16: + case systemz::RequestGOTAndTransformToDelta20: + case systemz::RequestGOTAndTransformToDelta32: + case systemz::RequestGOTAndTransformToDelta64: + case systemz::RequestGOTAndTransformToDelta16FromGOT: + case systemz::RequestGOTAndTransformToDelta32FromGOT: + case systemz::RequestGOTAndTransformToDelta64FromGOT: + case systemz::RequestGOTAndTransformToDelta32GOTBase: + case systemz::RequestGOTAndTransformToDelta32GOTBasedbl: + case systemz::RequestGOTAndTransformToDelta32dbl: KindToSet = E.getKind(); break; default: @@ -1042,12 +912,12 @@ class PLTTableManager : public TableManager { return false; switch (E.getKind()) { - case systemz::BranchPCRelPLT32: - case systemz::BranchPCRelPLT64: - case systemz::BranchPCRelPLT12dbl: - case systemz::BranchPCRelPLT16dbl: - case systemz::BranchPCRelPLT24dbl: - case systemz::BranchPCRelPLT32dbl: + case systemz::DeltaPLT32: + case systemz::DeltaPLT64: + case systemz::DeltaPLT12dbl: + case systemz::DeltaPLT16dbl: + case systemz::DeltaPLT24dbl: + case systemz::DeltaPLT32dbl: case systemz::DeltaPLT16FromGOT: case systemz::DeltaPLT32FromGOT: case systemz::DeltaPLT64FromGOT: diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp index 47d2d4651f881..630736d3d1ad4 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp @@ -240,27 +240,27 @@ class ELFLinkGraphBuilder_systemz } // Relocations targeting the PLT associated with the symbol. case ELF::R_390_PLT64: { - Kind = systemz::BranchPCRelPLT64; + Kind = systemz::DeltaPLT64; break; } case ELF::R_390_PLT32: { - Kind = systemz::BranchPCRelPLT32; + Kind = systemz::DeltaPLT32; break; } case ELF::R_390_PLT32DBL: { - Kind = systemz::BranchPCRelPLT32dbl; + Kind = systemz::DeltaPLT32dbl; break; } case ELF::R_390_PLT24DBL: { - Kind = systemz::BranchPCRelPLT24dbl; + Kind = systemz::DeltaPLT24dbl; break; } case ELF::R_390_PLT16DBL: { - Kind = systemz::BranchPCRelPLT16dbl; + Kind = systemz::DeltaPLT16dbl; break; } case ELF::R_390_PLT12DBL: { - Kind = systemz::BranchPCRelPLT12dbl; + Kind = systemz::DeltaPLT12dbl; break; } case ELF::R_390_PLTOFF64: { @@ -277,72 +277,53 @@ class ELFLinkGraphBuilder_systemz } // Relocations targeting the GOT entry associated with the symbol. case ELF::R_390_GOTOFF64: { - Kind = systemz::Delta64FromGOT; + Kind = systemz::RequestGOTAndTransformToDelta64FromGOT; break; } - // Seems loke ‘R_390_GOTOFF32’. case ELF::R_390_GOTOFF: { - Kind = systemz::Delta32FromGOT; + Kind = systemz::RequestGOTAndTransformToDelta32FromGOT; break; } case ELF::R_390_GOTOFF16: { - Kind = systemz::Delta16FromGOT; - break; - } - case ELF::R_390_GOT64: { - Kind = systemz::Delta64GOT; - break; - } - case ELF::R_390_GOT32: { - Kind = systemz::Delta32GOT; - break; - } - case ELF::R_390_GOT20: { - Kind = systemz::Delta20GOT; - break; - } - case ELF::R_390_GOT16: { - Kind = systemz::Delta16GOT; - break; - } - case ELF::R_390_GOT12: { - Kind = systemz::Delta12GOT; - break; - } - case ELF::R_390_GOTPC: { - Kind = systemz::DeltaPCRelGOT; - break; - } - case ELF::R_390_GOTPCDBL: { - Kind = systemz::DeltaPCRelGOTdbl; + Kind = systemz::RequestGOTAndTransformToDelta16FromGOT; break; } + case ELF::R_390_GOT64: case ELF::R_390_GOTPLT64: { - Kind = systemz::Delta64JumpSlot; + Kind = systemz::RequestGOTAndTransformToDelta64; break; } + case ELF::R_390_GOT32: case ELF::R_390_GOTPLT32: { - Kind = systemz::Delta32JumpSlot; + Kind = systemz::RequestGOTAndTransformToDelta32; break; } + case ELF::R_390_GOT20: case ELF::R_390_GOTPLT20: { - Kind = systemz::Delta20JumpSlot; + Kind = systemz::RequestGOTAndTransformToDelta20; break; } + case ELF::R_390_GOT16: case ELF::R_390_GOTPLT16: { - Kind = systemz::Delta16JumpSlot; + Kind = systemz::RequestGOTAndTransformToDelta16; break; } + case ELF::R_390_GOT12: case ELF::R_390_GOTPLT12: { - Kind = systemz::Delta12JumpSlot; + Kind = systemz::RequestGOTAndTransformToDelta12; break; } - case ELF::R_390_GOTPLTENT: { - Kind = systemz::PCRel32JumpSlot; + case ELF::R_390_GOTPC: { + Kind = systemz::RequestGOTAndTransformToDelta32GOTBase; break; } - case ELF::R_390_GOTENT: { - Kind = systemz::PCRel32GOTEntry; + case ELF::R_390_GOTPCDBL: { + Kind = systemz::RequestGOTAndTransformToDelta32GOTBasedbl; + break; + } + case ELF::R_390_GOTENT: + case ELF::R_390_GOTPLTENT: { + Kind = systemz::RequestGOTAndTransformToDelta32dbl; break; } default: @@ -390,7 +371,7 @@ Expected> createLinkGraphFromELFObject_systemz( return Features.takeError(); assert((*ELFObj)->getArch() == Triple::systemz && - "Only SystemZ (big endian) is supported for now"); + "Only SystemZ is supported"); auto &ELFObjFile = cast>(**ELFObj); return ELFLinkGraphBuilder_systemz( diff --git a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp index c9276bedafe99..273f3345f10d6 100644 --- a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp @@ -22,18 +22,12 @@ const char NullPointerContent[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const char Pointer64JumpStubContent[14] = { - static_cast(0xC0u), - 0x10, + static_cast(0xC4u), + 0x18, 0x00, 0x00, 0x00, - 0x00, // larl r1 - static_cast(0xE3u), - 0x10, - 0x10, - 0x00, - 0x00, - 0x04, // LG 1, 0(1) + 0x00, // lgrl r1 static_cast(0x07u), static_cast(0xF1u), // BCR 15, 1 }; @@ -70,58 +64,46 @@ const char *getEdgeKindName(Edge::Kind R) { return "NegDelta64"; case NegDelta32: return "NegDelta32"; - case Delta64FromGOT: - return "Delta64FromGOT"; - case Delta32FromGOT: - return "Delta32FromGOT"; - case Delta16FromGOT: - return "Delta16FromGOT"; - case BranchPCRelPLT32dbl: - return "BranchPCRelPLT32dbl"; - case BranchPCRelPLT24dbl: - return "BranchPCRelPLT24dbl"; - case BranchPCRelPLT16dbl: - return "BranchPCRelPLT16dbl"; - case BranchPCRelPLT12dbl: - return "BranchPCRelPLT12dbl"; - case PCRel32GOTEntry: - return "PCRel32GOTENTRY"; - case BranchPCRelPLT64: - return "BranchPCRelPLT64"; - case BranchPCRelPLT32: - return "BranchPCRelPLT32"; + case RequestGOTAndTransformToDelta64FromGOT: + return "RequestGOTAndTransformToDelta64FromGOT"; + case RequestGOTAndTransformToDelta32FromGOT: + return "RequestGOTAndTransformToDelta32FromGOT"; + case RequestGOTAndTransformToDelta16FromGOT: + return "RequestGOTAndTransformToDelta16FromGOT"; + case DeltaPLT32dbl: + return "DeltaPLT32dbl"; + case DeltaPLT24dbl: + return "DeltaPLT24dbl"; + case DeltaPLT16dbl: + return "DeltaPLT16dbl"; + case DeltaPLT12dbl: + return "DeltaPLT12dbl"; + case RequestGOTAndTransformToDelta32dbl: + return "RequestGOTAndTransformToDelta32dbl"; + case DeltaPLT64: + return "DeltaPLT64"; + case DeltaPLT32: + return "DeltaPLT32"; case DeltaPLT64FromGOT: return "DeltaPLT64FromGOT"; case DeltaPLT32FromGOT: return "DeltaPLT32FromGOT"; case DeltaPLT16FromGOT: return "DeltaPLT16FromGOT"; - case Delta64GOT: - return "Delta64GOT"; - case Delta32GOT: - return "Delta32GOT"; - case Delta20GOT: - return "Delta20GOT"; - case Delta16GOT: - return "Delta16GOT"; - case Delta12GOT: - return "Delta12GOT"; - case DeltaPCRelGOT: - return "DeltaPCRelGOT"; - case DeltaPCRelGOTdbl: - return "DeltaPCRelGOTdbl"; - case Delta64JumpSlot: - return "Delta64JumpSlot"; - case Delta32JumpSlot: - return "Delta32JumpSlot"; - case Delta20JumpSlot: - return "Delta20JumpSlot"; - case Delta16JumpSlot: - return "Delta16JumpSlot"; - case Delta12JumpSlot: - return "Delta12JumpSlot"; - case PCRel32JumpSlot: - return "PCRel32JumpSlot"; + case RequestGOTAndTransformToDelta64: + return "RequestGOTAndTransformToDelta64"; + case RequestGOTAndTransformToDelta32: + return "RequestGOTAndTransformToDelta32"; + case RequestGOTAndTransformToDelta20: + return "RequestGOTAndTransformToDelta20"; + case RequestGOTAndTransformToDelta16: + return "RequestGOTAndTransformToDelta16"; + case RequestGOTAndTransformToDelta12: + return "RequestGOTAndTransformToDelta12"; + case RequestGOTAndTransformToDelta32GOTBase: + return "RequestGOTAndTransformToDelta32GOTBase"; + case RequestGOTAndTransformToDelta32GOTBasedbl: + return "RequestGOTAndTransformToDelta32GOTBasedbl"; default: return getGenericEdgeKindName(static_cast(R)); } From c0cc3db1c4546c03495aea6468087a68f724bfa2 Mon Sep 17 00:00:00 2001 From: anoopkg6 Date: Tue, 4 Nov 2025 05:54:11 +0100 Subject: [PATCH 06/14] Incorporate code review feedback --- .../llvm/ExecutionEngine/JITLink/systemz.h | 362 +++++++++--------- .../ExecutionEngine/JITLink/ELF_systemz.cpp | 4 +- llvm/lib/ExecutionEngine/JITLink/systemz.cpp | 8 +- 3 files changed, 177 insertions(+), 197 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h index 3f692e0ecc383..ebb0d7042d430 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h @@ -243,10 +243,10 @@ enum EdgeKind_systemz : Edge::Kind { /// an out-of-range error will be returned. RequestGOTAndTransformToDelta16FromGOT, - /// A 32-bit PC-relative branch. + /// A 32-bit PC rel. PLT shifted by 1. /// - /// Represents a PC-relative call or branch to a target. This can be used to - /// identify, record, and/or patch call sites. + /// Delta from the fixup to the target. This will lead to creation of a + /// PLT stub. /// /// Fixup expression: /// Fixup <- (Target - Fixup + Addend) >> 1 : int32 @@ -259,7 +259,10 @@ enum EdgeKind_systemz : Edge::Kind { /// DeltaPLT32dbl, - /// A 24-bit PC-relative branch. + /// A 24-bit PC rel. PLT shifted by 1. + /// + /// Delta from the fixup to the target. This will lead to creation of a + /// PLT stub. /// /// Fixup expression: /// Fixup <- (Target - Fixup + Addend) >> 1 : int24 @@ -272,7 +275,10 @@ enum EdgeKind_systemz : Edge::Kind { /// DeltaPLT24dbl, - /// A 16-bit PC-relative branch. + /// A 16-bit PC rel. PLT shifted by 1. + /// + /// Delta from the fixup to the target. This will lead to creation of a + /// PLT stub. /// /// Fixup expression: /// Fixup <- (Target - Fixup + Addend) >> 1 : int16 @@ -285,7 +291,10 @@ enum EdgeKind_systemz : Edge::Kind { /// DeltaPLT16dbl, - /// A 12-bit PC-relative branch. + /// A 12-bit PC rel. PLT shifted by 1. + /// + /// Delta from the fixup to the target. This will lead to creation of a + /// PLT stub. /// /// Fixup expression: /// Fixup <- (Target - Fixup + Addend) >> 1 : int12 @@ -298,14 +307,20 @@ enum EdgeKind_systemz : Edge::Kind { /// DeltaPLT12dbl, - /// A 64-bit PC-relative PLT address. + /// A 64-bit PC rel. PLT address. + /// + /// Delta from the fixup to the target. This will lead to creation of a + /// PLT stub. /// /// Fixup expression: /// Fixup <- Target - Fixup + Addend : int64 /// DeltaPLT64, - /// A 32-bit PC-relative PLT address. + /// A 32-bit PC rel. PLT address. + /// + /// Delta from the fixup to the target. This will lead to creation of a + /// PLT stub. /// /// Fixup expression: /// Fixup <- Target - Fixup + Addend : int32 @@ -316,25 +331,11 @@ enum EdgeKind_systemz : Edge::Kind { /// DeltaPLT32, - /// A 32-bit PC-relative branch to a pointer jump stub. - /// Create a jump stub block that jumps via the pointer at the given symbol. - /// - /// Stub Content: - /// lgrl %r1, ptr - /// j %r1 - /// - /// Fixup expression at offset 2 of branch Instruction: - /// Fixup <- (Target - Fixup + Addend) >> 1 : int32 - /// - /// Errors: - /// - The result of the fixup expression before shifting right by 1 must - /// fit into an int33, otherwise an out-of-range error will be returned. - /// an out-of-range error will be returned. - /// - Branch32dblToStub, - /// A 64-bit offset from GOT to PLT. /// + /// Delta from the fixup to the target. This will lead to creation of a + /// PLT stub. + /// /// Fixup expression: /// Fixup <- Target - GOTBase + Addend : int64 /// @@ -357,6 +358,19 @@ enum EdgeKind_systemz : Edge::Kind { /// DeltaPLT32FromGOT, + /// A 20-bit offset from GOT to PLT. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int20 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int16, otherwise + /// an out-of-range error will be returned. + /// + DeltaPLT20FromGOT, + /// A 16-bit offset from GOT to PLT. /// /// Fixup expression: @@ -370,69 +384,139 @@ enum EdgeKind_systemz : Edge::Kind { /// DeltaPLT16FromGOT, - /// A 64-bit GOT offset. + /// A 12-bit offset from GOT to PLT. /// /// Fixup expression: - /// Fixup <- Target - GOTBase + Addend : int64 + /// Fixup <- Target - GOTBase + Addend : int12 /// /// Errors: /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int16, otherwise + /// an out-of-range error will be returned. + /// + DeltaPLT12FromGOT, + + /// A GOT entry getter/constructor, transformed to Delta64 pointing at the GOT + /// entry for the original target. + /// + /// Indicates that this edge should be transformed into a Delta32 targeting + /// the GOT entry for the edge's current target, maintaining the same addend. + /// A GOT entry for the target should be created if one does not already + /// exist. + /// + /// Edges of this kind are usually handled by a GOT builder pass inserted by + /// default. + /// + /// Fixup expression: + /// NONE + /// + /// Errors: + /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup + /// phase will result in an assert/unreachable during the fixup phase. /// RequestGOTAndTransformToDelta64, - /// A 32-bit GOT offset. + /// A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT + /// entry for the original target. + /// + /// Indicates that this edge should be transformed into a Delta32 targeting + /// the GOT entry for the edge's current target, maintaining the same addend. + /// A GOT entry for the target should be created if one does not already + /// exist. + /// + /// Edges of this kind are usually handled by a GOT builder pass inserted by + /// default. /// /// Fixup expression: - /// Fixup <- Target - GOTBase + Addend : int32 + /// NONE /// /// Errors: - /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section - /// symbol was not been defined. - /// - The result of the fixup expression must fit into an int32, otherwise - /// an out-of-range error will be returned. + /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup + /// phase will result in an assert/unreachable during the fixup phase. /// RequestGOTAndTransformToDelta32, - /// A 20-bit GOT offset. + /// A GOT entry getter/constructor, transformed to Delta20 pointing at the GOT + /// entry for the original target. + /// + /// Indicates that this edge should be transformed into a Delta32 targeting + /// the GOT entry for the edge's current target, maintaining the same addend. + /// A GOT entry for the target should be created if one does not already + /// exist. + /// + /// Edges of this kind are usually handled by a GOT builder pass inserted by + /// default. /// /// Fixup expression: - /// Fixup <- Target - GOTBase + Addend : int20 + /// NONE /// /// Errors: - /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section - /// symbol was not been defined. - /// - The result of the fixup expression must fit into an int20, otherwise - /// an out-of-range error will be returned. + /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup + /// phase will result in an assert/unreachable during the fixup phase. /// RequestGOTAndTransformToDelta20, - /// A 16-bit GOT offset. + /// A GOT entry getter/constructor, transformed to Delta16 pointing at the GOT + /// entry for the original target. + /// + /// Indicates that this edge should be transformed into a Delta32 targeting + /// the GOT entry for the edge's current target, maintaining the same addend. + /// A GOT entry for the target should be created if one does not already + /// exist. + /// + /// Edges of this kind are usually handled by a GOT builder pass inserted by + /// default. /// /// Fixup expression: - /// Fixup <- Target - GOTBase + Addend : int16 + /// NONE /// /// Errors: - /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section - /// symbol was not been defined. - /// - The result of the fixup expression must fit into an int16, otherwise - /// an out-of-range error will be returned. + /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup + /// phase will result in an assert/unreachable during the fixup phase. /// RequestGOTAndTransformToDelta16, - /// A 12-bit GOT offset. + /// A GOT entry getter/constructor, transformed to Delta12 pointing at the GOT + /// entry for the original target. + /// + /// Indicates that this edge should be transformed into a Delta32 targeting + /// the GOT entry for the edge's current target, maintaining the same addend. + /// A GOT entry for the target should be created if one does not already + /// exist. + /// + /// Edges of this kind are usually handled by a GOT builder pass inserted by + /// default. /// /// Fixup expression: - /// Fixup <- Target - GOTBase + Addend : int12 + /// NONE /// /// Errors: - /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section - /// symbol was not been defined. - /// - The result of the fixup expression must fit into an int12, otherwise - /// an out-of-range error will be returned. + /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup + /// phase will result in an assert/unreachable during the fixup phase. /// RequestGOTAndTransformToDelta12, + /// A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT + /// entry for the original target. + /// + /// Indicates that this edge should be transformed into a Delta32 targeting + /// the GOT entry for the edge's current target, maintaining the same addend. + /// A GOT entry for the target should be created if one does not already + /// exist. + /// + /// Edges of this kind are usually handled by a GOT builder pass inserted by + /// default. + /// + /// Fixup expression: + /// NONE + /// + /// Errors: + /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup + /// phase will result in an assert/unreachable during the fixup phase. + /// + RequestGOTAndTransformToDelta32dbl, + /// A 32-bit PC rel. offset to GOT. /// /// Fixup expression: @@ -444,7 +528,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression must fit into an int32, otherwise /// an out-of-range error will be returned. /// - RequestGOTAndTransformToDelta32GOTBase, + Delta32GOTBase, /// A 32-bit PC rel. offset to GOT shifted by 1. /// @@ -459,20 +543,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression before shifting right by 1 must /// be multiple of 2, otherwise an alignment error will be returned. /// - RequestGOTAndTransformToDelta32GOTBasedbl, - - /// A 32-bit PC rel. to GOT entry >> 1. - /// - /// Fixup expression: - /// Fixup <- (Target - Fixup + Addend) >> 1 : int32 - /// - /// Errors: - /// - The result of the fixup expression before shifting right by 1 must - /// fit into an int33, otherwise an out-of-range error will be returned. - /// - The result of the fixup expression before shifting right by 1 must - /// be multiple of 2, otherwise an alignment error will be returned. - /// - RequestGOTAndTransformToDelta32dbl, + Delta32dblGOTBase, }; @@ -547,12 +618,14 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, *(uint8_t *)FixupPtr = Value; break; } - case Delta64: { + case Delta64: + case DeltaPLT64: { int64_t Value = S + A - P; write64be(FixupPtr, Value); break; } - case Delta32: { + case Delta32: + case DeltaPLT32: { int64_t Value = S + A - P; if (!LLVM_UNLIKELY(isInt<32>(Value))) return makeTargetOutOfRangeError(G, B, E); @@ -573,7 +646,8 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, write32be(FixupPtr, Value); break; } - case Delta32dbl: { + case Delta32dbl: + case DeltaPLT32dbl: { int64_t Value = (S + A - P); if (!LLVM_UNLIKELY(isInt<33>(Value))) return makeTargetOutOfRangeError(G, B, E); @@ -582,7 +656,8 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, write32be(FixupPtr, Value >> 1); break; } - case Delta24dbl: { + case Delta24dbl: + case DeltaPLT24dbl: { int64_t Value = (S + A - P); if (!LLVM_UNLIKELY(isInt<25>(Value))) return makeTargetOutOfRangeError(G, B, E); @@ -593,7 +668,8 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, FixupPtr[2] = Value >> 1; break; } - case Delta16dbl: { + case Delta16dbl: + case DeltaPLT16dbl: { int64_t Value = (S + A - P); if (!LLVM_UNLIKELY(isInt<17>(Value))) return makeTargetOutOfRangeError(G, B, E); @@ -602,7 +678,8 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, write16be(FixupPtr, Value >> 1); break; } - case Delta12dbl: { + case Delta12dbl: + case DeltaPLT12dbl: { int64_t Value = (S + A - P); if (!LLVM_UNLIKELY(isInt<13>(Value))) return makeTargetOutOfRangeError(G, B, E); @@ -612,29 +689,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, (read16be(FixupPtr) & 0xF000) | ((Value >> 1) & 0x0FFF)); break; } - case RequestGOTAndTransformToDelta64FromGOT: { - assert(GOTSymbol && "No GOT section symbol"); - int64_t Value = S - GOTBase + A; - write64be(FixupPtr, Value); - break; - } - case RequestGOTAndTransformToDelta32FromGOT: { - assert(GOTSymbol && "No GOT section symbol"); - int64_t Value = S - GOTBase + A; - if (!LLVM_UNLIKELY(isInt<32>(Value))) - return makeTargetOutOfRangeError(G, B, E); - write32be(FixupPtr, Value); - break; - } - case RequestGOTAndTransformToDelta16FromGOT: { - assert(GOTSymbol && "No GOT section symbol"); - int64_t Value = S - GOTBase + A; - if (!LLVM_UNLIKELY(isInt<16>(Value))) - return makeTargetOutOfRangeError(G, B, E); - write16be(FixupPtr, Value); - break; - } - case RequestGOTAndTransformToDelta32GOTBase: { + case Delta32GOTBase: { assert(GOTSymbol && "No GOT section symbol"); int64_t Value = GOTBase + A - P; if (!LLVM_UNLIKELY(isInt<32>(Value))) @@ -642,7 +697,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, write32be(FixupPtr, Value); break; } - case RequestGOTAndTransformToDelta32GOTBasedbl: { + case Delta32dblGOTBase: { assert(GOTSymbol && "No GOT section symbol"); int64_t Value = (GOTBase + A - P); if (!LLVM_UNLIKELY(isInt<33>(Value))) @@ -652,55 +707,6 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, write32be(FixupPtr, Value >> 1); break; } - case DeltaPLT32dbl: { - int64_t Value = (S + A - P); - if (!LLVM_UNLIKELY(isInt<33>(Value))) - return makeTargetOutOfRangeError(G, B, E); - if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) - return makeAlignmentError(FixupAddress, Value, 2, E); - write32be(FixupPtr, Value >> 1); - break; - } - case DeltaPLT24dbl: { - int64_t Value = (S + A - P); - if (!LLVM_UNLIKELY(isInt<25>(Value))) - return makeTargetOutOfRangeError(G, B, E); - FixupPtr[0] = Value >> 17; - FixupPtr[1] = Value >> 9; - FixupPtr[2] = Value >> 1; - break; - } - case DeltaPLT16dbl: { - int64_t Value = (S + A - P); - if (!LLVM_UNLIKELY(isInt<17>(Value))) - return makeTargetOutOfRangeError(G, B, E); - if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) - return makeAlignmentError(FixupAddress, Value, 2, E); - write16be(FixupPtr, Value >> 1); - break; - } - case DeltaPLT12dbl: { - int64_t Value = (S + A - P); - if (!LLVM_UNLIKELY(isInt<13>(Value))) - return makeTargetOutOfRangeError(G, B, E); - if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) - return makeAlignmentError(FixupAddress, Value, 2, E); - write16be(FixupPtr, - (read16be(FixupPtr) & 0xF000) | ((Value >> 1) & 0x0FFF)); - break; - } - case DeltaPLT64: { - int64_t Value = (S + A - P); - write64be(FixupPtr, Value); - break; - } - case DeltaPLT32: { - int64_t Value = (S + A - P); - if (!LLVM_UNLIKELY(isInt<32>(Value))) - return makeTargetOutOfRangeError(G, B, E); - write32be(FixupPtr, Value); - break; - } case DeltaPLT64FromGOT: { assert(GOTSymbol && "No GOT section symbol"); int64_t Value = (S + A - GOTBase); @@ -723,38 +729,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, write16be(FixupPtr, Value); break; } - case Branch32dblToStub: { - int64_t Value = (S + A - P); - if (!LLVM_UNLIKELY(isInt<33>(Value))) - return makeTargetOutOfRangeError(G, B, E); - char *AddrToPatch = FixupPtr + 2; - write32be(AddrToPatch, Value >> 1); - break; - } - case RequestGOTAndTransformToDelta32dbl: { - int64_t Value = (S + A - P); - if (!LLVM_UNLIKELY(isInt<33>(Value))) - return makeTargetOutOfRangeError(G, B, E); - if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) - return makeAlignmentError(FixupAddress, Value, 2, E); - write32be(FixupPtr, Value >> 1); - break; - } - case RequestGOTAndTransformToDelta64: { - assert(GOTSymbol && "No GOT section symbol"); - int64_t Value = S - GOTBase + A; - write64be(FixupPtr, Value); - break; - } - case RequestGOTAndTransformToDelta32: { - assert(GOTSymbol && "No GOT section symbol"); - uint64_t Value = S - GOTBase + A; - if (!LLVM_UNLIKELY(isUInt<32>(Value))) - return makeTargetOutOfRangeError(G, B, E); - write32be(FixupPtr, Value); - break; - } - case RequestGOTAndTransformToDelta20: { + case DeltaPLT20FromGOT: { assert(GOTSymbol && "No GOT section symbol"); uint64_t Value = S - GOTBase + A; if (!LLVM_UNLIKELY(isInt<20>(Value))) @@ -763,15 +738,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, ((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4)); break; } - case RequestGOTAndTransformToDelta16: { - assert(GOTSymbol && "No GOT section symbol"); - uint64_t Value = S - GOTBase + A; - if (!LLVM_UNLIKELY(isUInt<16>(Value))) - return makeTargetOutOfRangeError(G, B, E); - write16be(FixupPtr, Value); - break; - } - case RequestGOTAndTransformToDelta12: { + case DeltaPLT12FromGOT: { assert(GOTSymbol && "No GOT section symbol"); uint64_t Value = S - GOTBase + A; if (!LLVM_UNLIKELY(isUInt<12>(Value))) @@ -832,7 +799,7 @@ inline Block &createPointerJumpStubBlock(LinkGraph &G, Section &StubSection, Symbol &PointerSymbol) { auto &B = G.createContentBlock(StubSection, getStubBlockContent(G), orc::ExecutorAddr(), 8, 0); - B.addEdge(Branch32dblToStub, 0, PointerSymbol, 0); + B.addEdge(Delta32dbl, 0, PointerSymbol, 0); return B; } @@ -859,16 +826,28 @@ class GOTTableManager : public TableManager { Edge::Kind KindToSet = Edge::Invalid; switch (E.getKind()) { case systemz::RequestGOTAndTransformToDelta12: + KindToSet = systemz::DeltaPLT12FromGOT; + break; case systemz::RequestGOTAndTransformToDelta16: + case systemz::RequestGOTAndTransformToDelta16FromGOT: + KindToSet = systemz::DeltaPLT16FromGOT; + break; case systemz::RequestGOTAndTransformToDelta20: + KindToSet = systemz::DeltaPLT20FromGOT; + break; case systemz::RequestGOTAndTransformToDelta32: - case systemz::RequestGOTAndTransformToDelta64: - case systemz::RequestGOTAndTransformToDelta16FromGOT: case systemz::RequestGOTAndTransformToDelta32FromGOT: + KindToSet = systemz::DeltaPLT32FromGOT; + break; + case systemz::RequestGOTAndTransformToDelta64: case systemz::RequestGOTAndTransformToDelta64FromGOT: - case systemz::RequestGOTAndTransformToDelta32GOTBase: - case systemz::RequestGOTAndTransformToDelta32GOTBasedbl: + KindToSet = systemz::DeltaPLT64FromGOT; + break; case systemz::RequestGOTAndTransformToDelta32dbl: + KindToSet = systemz::DeltaPLT32dbl; + break; + case systemz::Delta32GOTBase: + case systemz::Delta32dblGOTBase: KindToSet = E.getKind(); break; default: @@ -881,6 +860,7 @@ class GOTTableManager : public TableManager { << B->getFixupAddress(E) << " (" << B->getAddress() << " + " << formatv("{0:x}", E.getOffset()) << ")\n"; }); + E.setKind(KindToSet); E.setTarget(getEntryForTarget(G, E.getTarget())); return true; } diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp index 630736d3d1ad4..74d9531d3631f 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp @@ -314,11 +314,11 @@ class ELFLinkGraphBuilder_systemz break; } case ELF::R_390_GOTPC: { - Kind = systemz::RequestGOTAndTransformToDelta32GOTBase; + Kind = systemz::Delta32GOTBase; break; } case ELF::R_390_GOTPCDBL: { - Kind = systemz::RequestGOTAndTransformToDelta32GOTBasedbl; + Kind = systemz::Delta32dblGOTBase; break; } case ELF::R_390_GOTENT: diff --git a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp index 273f3345f10d6..4e64036ea1eac 100644 --- a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp @@ -100,10 +100,10 @@ const char *getEdgeKindName(Edge::Kind R) { return "RequestGOTAndTransformToDelta16"; case RequestGOTAndTransformToDelta12: return "RequestGOTAndTransformToDelta12"; - case RequestGOTAndTransformToDelta32GOTBase: - return "RequestGOTAndTransformToDelta32GOTBase"; - case RequestGOTAndTransformToDelta32GOTBasedbl: - return "RequestGOTAndTransformToDelta32GOTBasedbl"; + case Delta32GOTBase: + return "Delta32GOTBase"; + case Delta32dblGOTBase: + return "Delta32dblGOTBase"; default: return getGenericEdgeKindName(static_cast(R)); } From 47482b25280f7b78009def2013dd1c5afc2802a9 Mon Sep 17 00:00:00 2001 From: anoopkg6 Date: Wed, 5 Nov 2025 03:55:05 +0100 Subject: [PATCH 07/14] 1. Created GOTPC section for R_390_GOTPC and R_390_GOTPCDBL relocation. 2. Incorporate code review feedback. --- .../llvm/ExecutionEngine/JITLink/systemz.h | 264 ++++++++++-------- .../ExecutionEngine/JITLink/ELF_systemz.cpp | 23 +- llvm/lib/ExecutionEngine/JITLink/systemz.cpp | 30 +- 3 files changed, 175 insertions(+), 142 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h index ebb0d7042d430..460ed429418b1 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h @@ -49,7 +49,7 @@ enum EdgeKind_systemz : Edge::Kind { /// Fixup <- Target + Addend : uint20 /// /// Errors: - /// - The target must reside in the mid 20-bits of the address space, + /// - The target must reside in the low 20-bits of the address space, /// otherwise an out-of-range error will be returned. /// Pointer20, @@ -203,50 +203,67 @@ enum EdgeKind_systemz : Edge::Kind { /// an out-of-range error will be returned. NegDelta32, - /// A 64-bit GOT delta. + /// A GOT entry getter/constructor, transformed to DeltaPLT64FromGOT pointing + /// at the GOT entry for the original target. /// - /// Delta from the global offset table to the target + /// Indicates that this edge should be transformed into a DeltaPLT64FromGOT + /// targeting the GOT entry for the edge's current target, maintaining the + /// same addend. A GOT entry for the target should be created if one does + /// not already exist. + /// + /// Edges of this kind are usually handled by a GOT builder pass inserted by + /// default. /// /// Fixup expression: - /// Fixup <- Target - GOTSymbol + Addend : int64 + /// NONE /// /// Errors: - /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section - /// symbol was not been defined. - RequestGOTAndTransformToDelta64FromGOT, + /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup + /// + RequestGOTAndTransformToDeltaPLT64FromGOT, - /// A 32-bit GOT delta. + /// A GOT entry getter/constructor, transformed to DeltaPLT32FromGOT pointing + /// at the GOT entry for the original target. + /// + /// Indicates that this edge should be transformed into a DeltaPLT32FromGOT + /// targeting the GOT entry for the edge's current target, maintaining the + /// same addend. A GOT entry for the target should be created if one does + /// not already exist. /// - /// Delta from the global offset table to the target + /// Edges of this kind are usually handled by a GOT builder pass inserted by + /// default. /// /// Fixup expression: - /// Fixup <- Target - GOTSymbol + Addend : int32 + /// NONE /// /// Errors: - /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section - /// symbol was not been defined. - /// - The result of the fixup expression must fit into an int32, otherwise - /// an out-of-range error will be returned. - RequestGOTAndTransformToDelta32FromGOT, + /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup + /// + RequestGOTAndTransformToDeltaPLT32FromGOT, - /// A 16-bit GOT delta. + /// A GOT entry getter/constructor, transformed to DeltaPLT16FromGOT pointing + /// at the GOT entry for the original target. /// - /// Delta from the global offset table to the target + /// Indicates that this edge should be transformed into a DeltaPLT16FromGOT + /// targeting the GOT entry for the edge's current target, maintaining the + /// same addend. A GOT entry for the target should be created if one does + /// not already exist. + /// + /// Edges of this kind are usually handled by a GOT builder pass inserted by + /// default. /// /// Fixup expression: - /// Fixup <- Target - GOTSymbol + Addend : int16 + /// NONE /// /// Errors: - /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section - /// symbol was not been defined. - /// - The result of the fixup expression must fit into an int16, otherwise - /// an out-of-range error will be returned. - RequestGOTAndTransformToDelta16FromGOT, + /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup + /// + RequestGOTAndTransformToDeltaPLT16FromGOT, - /// A 32-bit PC rel. PLT shifted by 1. + /// A 32-bit Delta shifted by 1. /// - /// Delta from the fixup to the target. This will lead to creation of a - /// PLT stub. + /// Delta from the fixup to the PLT slot for the target. This will lead to + /// creation of a PLT stub. /// /// Fixup expression: /// Fixup <- (Target - Fixup + Addend) >> 1 : int32 @@ -259,10 +276,10 @@ enum EdgeKind_systemz : Edge::Kind { /// DeltaPLT32dbl, - /// A 24-bit PC rel. PLT shifted by 1. + /// A 24-bit Delta shifted by 1. /// - /// Delta from the fixup to the target. This will lead to creation of a - /// PLT stub. + /// Delta from the fixup to the PLT slot for the target. This will lead to + /// creation of a PLT stub. /// /// Fixup expression: /// Fixup <- (Target - Fixup + Addend) >> 1 : int24 @@ -275,10 +292,10 @@ enum EdgeKind_systemz : Edge::Kind { /// DeltaPLT24dbl, - /// A 16-bit PC rel. PLT shifted by 1. + /// A 16-bit Delta shifted by 1. /// - /// Delta from the fixup to the target. This will lead to creation of a - /// PLT stub. + /// Delta from the fixup to the PLT slot for the target. This will lead to + /// creation of a PLT stub. /// /// Fixup expression: /// Fixup <- (Target - Fixup + Addend) >> 1 : int16 @@ -291,10 +308,10 @@ enum EdgeKind_systemz : Edge::Kind { /// DeltaPLT16dbl, - /// A 12-bit PC rel. PLT shifted by 1. + /// A 12-bit Delta shifted by 1. /// - /// Delta from the fixup to the target. This will lead to creation of a - /// PLT stub. + /// Delta from the fixup to the PLT slot for the target. This will lead to + /// creation of a PLT stub. /// /// Fixup expression: /// Fixup <- (Target - Fixup + Addend) >> 1 : int12 @@ -307,20 +324,20 @@ enum EdgeKind_systemz : Edge::Kind { /// DeltaPLT12dbl, - /// A 64-bit PC rel. PLT address. + /// A 64-bit Delta. /// - /// Delta from the fixup to the target. This will lead to creation of a - /// PLT stub. + /// Delta from the fixup to the PLT slot for the target. This will lead to + /// creation of a PLT stub. /// /// Fixup expression: /// Fixup <- Target - Fixup + Addend : int64 /// DeltaPLT64, - /// A 32-bit PC rel. PLT address. + /// A 32-bit Delta. /// - /// Delta from the fixup to the target. This will lead to creation of a - /// PLT stub. + /// Delta from the fixup to the PLT slot for the target. This will lead to + /// creation of a PLT stub. /// /// Fixup expression: /// Fixup <- Target - Fixup + Addend : int32 @@ -397,13 +414,13 @@ enum EdgeKind_systemz : Edge::Kind { /// DeltaPLT12FromGOT, - /// A GOT entry getter/constructor, transformed to Delta64 pointing at the GOT - /// entry for the original target. + /// A GOT entry getter/constructor, transformed to DeltaPLT20FromGOT pointing + /// at the GOT entry for the original target. /// - /// Indicates that this edge should be transformed into a Delta32 targeting - /// the GOT entry for the edge's current target, maintaining the same addend. - /// A GOT entry for the target should be created if one does not already - /// exist. + /// Indicates that this edge should be transformed into a DeltaPLT20FromGOT + /// targeting the GOT entry for the edge's current target, maintaining the + /// same addend. A GOT entry for the target should be created if one does + /// not already exist. /// /// Edges of this kind are usually handled by a GOT builder pass inserted by /// default. @@ -413,17 +430,16 @@ enum EdgeKind_systemz : Edge::Kind { /// /// Errors: /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup - /// phase will result in an assert/unreachable during the fixup phase. /// - RequestGOTAndTransformToDelta64, + RequestGOTAndTransformToDeltaPLT20FromGOT, - /// A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT - /// entry for the original target. + /// A GOT entry getter/constructor, transformed to DeltaPLT12FromGOT pointing + /// at the GOT entry for the original target. /// - /// Indicates that this edge should be transformed into a Delta32 targeting - /// the GOT entry for the edge's current target, maintaining the same addend. - /// A GOT entry for the target should be created if one does not already - /// exist. + /// Indicates that this edge should be transformed into a DeltaPLT12FromGOT + /// targeting the GOT entry for the edge's current target, maintaining the + /// same addend. A GOT entry for the target should be created if one does + /// not already exist. /// /// Edges of this kind are usually handled by a GOT builder pass inserted by /// default. @@ -435,12 +451,12 @@ enum EdgeKind_systemz : Edge::Kind { /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup /// phase will result in an assert/unreachable during the fixup phase. /// - RequestGOTAndTransformToDelta32, + RequestGOTAndTransformToDeltaPLT12FromGOT, - /// A GOT entry getter/constructor, transformed to Delta20 pointing at the GOT - /// entry for the original target. + /// A GOT entry getter/constructor, transformed to Delta32dbl pointing at + /// the GOT entry for the original target. /// - /// Indicates that this edge should be transformed into a Delta32 targeting + /// Indicates that this edge should be transformed into a Delta32dbl targeting /// the GOT entry for the edge's current target, maintaining the same addend. /// A GOT entry for the target should be created if one does not already /// exist. @@ -455,38 +471,18 @@ enum EdgeKind_systemz : Edge::Kind { /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup /// phase will result in an assert/unreachable during the fixup phase. /// - RequestGOTAndTransformToDelta20, - - /// A GOT entry getter/constructor, transformed to Delta16 pointing at the GOT - /// entry for the original target. - /// - /// Indicates that this edge should be transformed into a Delta32 targeting - /// the GOT entry for the edge's current target, maintaining the same addend. - /// A GOT entry for the target should be created if one does not already - /// exist. - /// - /// Edges of this kind are usually handled by a GOT builder pass inserted by - /// default. - /// - /// Fixup expression: - /// NONE - /// - /// Errors: - /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup - /// phase will result in an assert/unreachable during the fixup phase. - /// - RequestGOTAndTransformToDelta16, + RequestGOTAndTransformToDelta32dbl, - /// A GOT entry getter/constructor, transformed to Delta12 pointing at the GOT - /// entry for the original target. + /// A GOTPC entry getter/constructor, transformed to Delta32GOTBase + /// delta to GOT base. /// - /// Indicates that this edge should be transformed into a Delta32 targeting - /// the GOT entry for the edge's current target, maintaining the same addend. - /// A GOT entry for the target should be created if one does not already - /// exist. + /// Indicates that this edge should be transformed into a Delta32GOTBase + /// targeting the GOTPC entry for the edge's current target, maintaining + /// the same addend. A GOTPC entry for the target should be created if + /// one does not already exist. /// - /// Edges of this kind are usually handled by a GOT builder pass inserted by - /// default. + /// Edges of this kind are usually handled by a GOTPC builder pass inserted + /// by default. /// /// Fixup expression: /// NONE @@ -494,19 +490,18 @@ enum EdgeKind_systemz : Edge::Kind { /// Errors: /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup /// phase will result in an assert/unreachable during the fixup phase. - /// - RequestGOTAndTransformToDelta12, + RequestGOTPCAndTransformToDelta32GOTBase, - /// A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT - /// entry for the original target. + /// A GOTPC entry getter/constructor, transformed to Delta32dblGOTBase + /// delta to GOT base. /// - /// Indicates that this edge should be transformed into a Delta32 targeting - /// the GOT entry for the edge's current target, maintaining the same addend. - /// A GOT entry for the target should be created if one does not already - /// exist. + /// Indicates that this edge should be transformed into a Delta32dblGOTBase + /// targeting the GOTPC entry for the edge's current target, maintaining + /// the same addend. A GOTPC entry for the target should be created if + /// one does not already exist. /// - /// Edges of this kind are usually handled by a GOT builder pass inserted by - /// default. + /// Edges of this kind are usually handled by a GOTPC builder pass inserted + /// by default. /// /// Fixup expression: /// NONE @@ -514,10 +509,9 @@ enum EdgeKind_systemz : Edge::Kind { /// Errors: /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup /// phase will result in an assert/unreachable during the fixup phase. - /// - RequestGOTAndTransformToDelta32dbl, + RequestGOTPCAndTransformToDelta32dblGOTBase, - /// A 32-bit PC rel. offset to GOT. + /// A 32-bit Delta to GOT base. /// /// Fixup expression: /// Fixup <- GOTBase - Fixup + Addend : int32 @@ -530,7 +524,7 @@ enum EdgeKind_systemz : Edge::Kind { /// Delta32GOTBase, - /// A 32-bit PC rel. offset to GOT shifted by 1. + /// A 32-bit Delta to GOT base shifted by 1. /// /// Fixup expression: /// Fixup <- (GOTBase - Fixup + Addend) >> 1 : int32 @@ -799,7 +793,7 @@ inline Block &createPointerJumpStubBlock(LinkGraph &G, Section &StubSection, Symbol &PointerSymbol) { auto &B = G.createContentBlock(StubSection, getStubBlockContent(G), orc::ExecutorAddr(), 8, 0); - B.addEdge(Delta32dbl, 0, PointerSymbol, 0); + B.addEdge(Delta32dbl, 2, PointerSymbol, 0); return B; } @@ -825,31 +819,24 @@ class GOTTableManager : public TableManager { return false; Edge::Kind KindToSet = Edge::Invalid; switch (E.getKind()) { - case systemz::RequestGOTAndTransformToDelta12: + case systemz::RequestGOTAndTransformToDeltaPLT12FromGOT: KindToSet = systemz::DeltaPLT12FromGOT; break; - case systemz::RequestGOTAndTransformToDelta16: - case systemz::RequestGOTAndTransformToDelta16FromGOT: + case systemz::RequestGOTAndTransformToDeltaPLT16FromGOT: KindToSet = systemz::DeltaPLT16FromGOT; break; - case systemz::RequestGOTAndTransformToDelta20: + case systemz::RequestGOTAndTransformToDeltaPLT20FromGOT: KindToSet = systemz::DeltaPLT20FromGOT; break; - case systemz::RequestGOTAndTransformToDelta32: - case systemz::RequestGOTAndTransformToDelta32FromGOT: + case systemz::RequestGOTAndTransformToDeltaPLT32FromGOT: KindToSet = systemz::DeltaPLT32FromGOT; break; - case systemz::RequestGOTAndTransformToDelta64: - case systemz::RequestGOTAndTransformToDelta64FromGOT: + case systemz::RequestGOTAndTransformToDeltaPLT64FromGOT: KindToSet = systemz::DeltaPLT64FromGOT; break; case systemz::RequestGOTAndTransformToDelta32dbl: KindToSet = systemz::DeltaPLT32dbl; break; - case systemz::Delta32GOTBase: - case systemz::Delta32dblGOTBase: - KindToSet = E.getKind(); - break; default: return false; } @@ -931,6 +918,53 @@ class PLTTableManager : public TableManager { Section *StubsSection = nullptr; }; +/// GOTPC Table Builder. +class GOTPCTableManager : public TableManager { +public: + GOTPCTableManager(GOTTableManager &GOT) : GOT(GOT) {} + + static StringRef getSectionName() { return "$__GOTPC"; } + + bool visitEdge(LinkGraph &G, Block *B, Edge &E) { + Edge::Kind KindToSet = Edge::Invalid; + switch (E.getKind()) { + case systemz::RequestGOTPCAndTransformToDelta32GOTBase: + KindToSet = systemz::Delta32GOTBase; + break; + case systemz::RequestGOTPCAndTransformToDelta32dblGOTBase: + KindToSet = systemz::Delta32dblGOTBase; + break; + default: + return false; + } + assert(KindToSet != Edge::Invalid && + "Fell through switch, but no new kind to set"); + DEBUG_WITH_TYPE("jitlink", { + dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at " + << B->getFixupAddress(E) << " (" << B->getAddress() << " + " + << formatv("{0:x}", E.getOffset()) << ")\n"; + }); + E.setKind(KindToSet); + E.setTarget(getEntryForTarget(G, E.getTarget())); + return true; + } + + Symbol &createEntry(LinkGraph &G, Symbol &Target) { + return createAnonymousPointer(G, getGOTPCSection(G), &Target); + } + +private: + Section &getGOTPCSection(LinkGraph &G) { + if (!GOTPCSection) + GOTPCSection = &G.createSection(getSectionName(), + orc::MemProt::Read | orc::MemProt::Exec); + return *GOTPCSection; + } + + GOTTableManager &GOT; + Section *GOTPCSection = nullptr; +}; + } // namespace systemz } // namespace jitlink } // namespace llvm diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp index 74d9531d3631f..9ddba46e3b211 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp @@ -32,7 +32,8 @@ Error buildTables_ELF_systemz(LinkGraph &G) { LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); systemz::GOTTableManager GOT; systemz::PLTTableManager PLT(GOT); - visitExistingEdges(G, GOT, PLT); + systemz::GOTPCTableManager GOTPC(GOT); + visitExistingEdges(G, GOT, PLT, GOTPC); return Error::success(); } @@ -277,48 +278,48 @@ class ELFLinkGraphBuilder_systemz } // Relocations targeting the GOT entry associated with the symbol. case ELF::R_390_GOTOFF64: { - Kind = systemz::RequestGOTAndTransformToDelta64FromGOT; + Kind = systemz::RequestGOTAndTransformToDeltaPLT64FromGOT; break; } case ELF::R_390_GOTOFF: { - Kind = systemz::RequestGOTAndTransformToDelta32FromGOT; + Kind = systemz::RequestGOTAndTransformToDeltaPLT32FromGOT; break; } case ELF::R_390_GOTOFF16: { - Kind = systemz::RequestGOTAndTransformToDelta16FromGOT; + Kind = systemz::RequestGOTAndTransformToDeltaPLT16FromGOT; break; } case ELF::R_390_GOT64: case ELF::R_390_GOTPLT64: { - Kind = systemz::RequestGOTAndTransformToDelta64; + Kind = systemz::RequestGOTAndTransformToDeltaPLT64FromGOT; break; } case ELF::R_390_GOT32: case ELF::R_390_GOTPLT32: { - Kind = systemz::RequestGOTAndTransformToDelta32; + Kind = systemz::RequestGOTAndTransformToDeltaPLT32FromGOT; break; } case ELF::R_390_GOT20: case ELF::R_390_GOTPLT20: { - Kind = systemz::RequestGOTAndTransformToDelta20; + Kind = systemz::RequestGOTAndTransformToDeltaPLT20FromGOT; break; } case ELF::R_390_GOT16: case ELF::R_390_GOTPLT16: { - Kind = systemz::RequestGOTAndTransformToDelta16; + Kind = systemz::RequestGOTAndTransformToDeltaPLT16FromGOT; break; } case ELF::R_390_GOT12: case ELF::R_390_GOTPLT12: { - Kind = systemz::RequestGOTAndTransformToDelta12; + Kind = systemz::RequestGOTAndTransformToDeltaPLT12FromGOT; break; } case ELF::R_390_GOTPC: { - Kind = systemz::Delta32GOTBase; + Kind = systemz::RequestGOTPCAndTransformToDelta32GOTBase; break; } case ELF::R_390_GOTPCDBL: { - Kind = systemz::Delta32dblGOTBase; + Kind = systemz::RequestGOTPCAndTransformToDelta32dblGOTBase; break; } case ELF::R_390_GOTENT: diff --git a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp index 4e64036ea1eac..7f6d18c04ca59 100644 --- a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp @@ -64,12 +64,12 @@ const char *getEdgeKindName(Edge::Kind R) { return "NegDelta64"; case NegDelta32: return "NegDelta32"; - case RequestGOTAndTransformToDelta64FromGOT: - return "RequestGOTAndTransformToDelta64FromGOT"; - case RequestGOTAndTransformToDelta32FromGOT: - return "RequestGOTAndTransformToDelta32FromGOT"; - case RequestGOTAndTransformToDelta16FromGOT: - return "RequestGOTAndTransformToDelta16FromGOT"; + case RequestGOTAndTransformToDeltaPLT64FromGOT: + return "RequestGOTAndTransformToDeltaPLT64FromGOT"; + case RequestGOTAndTransformToDeltaPLT32FromGOT: + return "RequestGOTAndTransformToDeltaPLT32FromGOT"; + case RequestGOTAndTransformToDeltaPLT16FromGOT: + return "RequestGOTAndTransformToDeltaPLT16FromGOT"; case DeltaPLT32dbl: return "DeltaPLT32dbl"; case DeltaPLT24dbl: @@ -90,16 +90,14 @@ const char *getEdgeKindName(Edge::Kind R) { return "DeltaPLT32FromGOT"; case DeltaPLT16FromGOT: return "DeltaPLT16FromGOT"; - case RequestGOTAndTransformToDelta64: - return "RequestGOTAndTransformToDelta64"; - case RequestGOTAndTransformToDelta32: - return "RequestGOTAndTransformToDelta32"; - case RequestGOTAndTransformToDelta20: - return "RequestGOTAndTransformToDelta20"; - case RequestGOTAndTransformToDelta16: - return "RequestGOTAndTransformToDelta16"; - case RequestGOTAndTransformToDelta12: - return "RequestGOTAndTransformToDelta12"; + case RequestGOTAndTransformToDeltaPLT20FromGOT: + return "RequestGOTAndTransformToDeltaPLT20FromGOT"; + case RequestGOTAndTransformToDeltaPLT12FromGOT: + return "RequestGOTAndTransformToDeltaPLT12FromGOT"; + case RequestGOTPCAndTransformToDelta32GOTBase: + return "RequestGOTPCAndTransformToDelta32GOTBase"; + case RequestGOTPCAndTransformToDelta32dblGOTBase: + return "RequestGOTPCAndTransformToDelta32dblGOTBase"; case Delta32GOTBase: return "Delta32GOTBase"; case Delta32dblGOTBase: From f6b25567ba07596c2afdd3db8ca728ae4a953d95 Mon Sep 17 00:00:00 2001 From: anoopkg6 Date: Thu, 6 Nov 2025 02:54:25 +0100 Subject: [PATCH 08/14] Incorporate code review feedback --- .../llvm/ExecutionEngine/JITLink/systemz.h | 212 +++++++----------- .../ExecutionEngine/JITLink/ELF_systemz.cpp | 44 ++-- llvm/lib/ExecutionEngine/JITLink/systemz.cpp | 42 ++-- 3 files changed, 127 insertions(+), 171 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h index 460ed429418b1..1ef5f693d87d8 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h @@ -203,10 +203,10 @@ enum EdgeKind_systemz : Edge::Kind { /// an out-of-range error will be returned. NegDelta32, - /// A GOT entry getter/constructor, transformed to DeltaPLT64FromGOT pointing + /// A GOT entry getter/constructor, transformed to Delta64FromGOT pointing /// at the GOT entry for the original target. /// - /// Indicates that this edge should be transformed into a DeltaPLT64FromGOT + /// Indicates that this edge should be transformed into a Delta64FromGOT /// targeting the GOT entry for the edge's current target, maintaining the /// same addend. A GOT entry for the target should be created if one does /// not already exist. @@ -220,12 +220,12 @@ enum EdgeKind_systemz : Edge::Kind { /// Errors: /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup /// - RequestGOTAndTransformToDeltaPLT64FromGOT, + RequestGOTAndTransformToDelta64FromGOT, - /// A GOT entry getter/constructor, transformed to DeltaPLT32FromGOT pointing + /// A GOT entry getter/constructor, transformed to Delta32FromGOT pointing /// at the GOT entry for the original target. /// - /// Indicates that this edge should be transformed into a DeltaPLT32FromGOT + /// Indicates that this edge should be transformed into a Delta32FromGOT /// targeting the GOT entry for the edge's current target, maintaining the /// same addend. A GOT entry for the target should be created if one does /// not already exist. @@ -239,12 +239,12 @@ enum EdgeKind_systemz : Edge::Kind { /// Errors: /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup /// - RequestGOTAndTransformToDeltaPLT32FromGOT, + RequestGOTAndTransformToDelta32FromGOT, - /// A GOT entry getter/constructor, transformed to DeltaPLT16FromGOT pointing + /// A GOT entry getter/constructor, transformed to Delta16FromGOT pointing /// at the GOT entry for the original target. /// - /// Indicates that this edge should be transformed into a DeltaPLT16FromGOT + /// Indicates that this edge should be transformed into a Delta16FromGOT /// targeting the GOT entry for the edge's current target, maintaining the /// same addend. A GOT entry for the target should be created if one does /// not already exist. @@ -258,7 +258,7 @@ enum EdgeKind_systemz : Edge::Kind { /// Errors: /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup /// - RequestGOTAndTransformToDeltaPLT16FromGOT, + RequestGOTAndTransformToDelta16FromGOT, /// A 32-bit Delta shifted by 1. /// @@ -350,9 +350,6 @@ enum EdgeKind_systemz : Edge::Kind { /// A 64-bit offset from GOT to PLT. /// - /// Delta from the fixup to the target. This will lead to creation of a - /// PLT stub. - /// /// Fixup expression: /// Fixup <- Target - GOTBase + Addend : int64 /// @@ -360,7 +357,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section /// symbol was not been defined. /// - DeltaPLT64FromGOT, + Delta64PLTFromGOT, /// A 32-bit offset from GOT to PLT. /// @@ -373,12 +370,12 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression must fit into an int32, otherwise /// an out-of-range error will be returned. /// - DeltaPLT32FromGOT, + Delta32PLTFromGOT, - /// A 20-bit offset from GOT to PLT. + /// A 16-bit offset from GOT to PLT. /// /// Fixup expression: - /// Fixup <- Target - GOTBase + Addend : int20 + /// Fixup <- Target - GOTBase + Addend : int16 /// /// Errors: /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section @@ -386,9 +383,33 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression must fit into an int16, otherwise /// an out-of-range error will be returned. /// - DeltaPLT20FromGOT, + Delta16PLTFromGOT, - /// A 16-bit offset from GOT to PLT. + /// A 64-bit offset from GOT. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int64 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// + Delta64FromGOT, + + /// A 32-bit offset from GOT. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int32 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int32, otherwise + /// an out-of-range error will be returned. + /// + Delta32FromGOT, + + /// A 16-bit offset from GOT. /// /// Fixup expression: /// Fixup <- Target - GOTBase + Addend : int16 @@ -399,9 +420,22 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression must fit into an int16, otherwise /// an out-of-range error will be returned. /// - DeltaPLT16FromGOT, + Delta16FromGOT, + + /// A 20-bit offset from GOT. + /// + /// Fixup expression: + /// Fixup <- Target - GOTBase + Addend : int20 + /// + /// Errors: + /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section + /// symbol was not been defined. + /// - The result of the fixup expression must fit into an int16, otherwise + /// an out-of-range error will be returned. + /// + Delta20FromGOT, - /// A 12-bit offset from GOT to PLT. + /// A 12-bit offset from GOT. /// /// Fixup expression: /// Fixup <- Target - GOTBase + Addend : int12 @@ -412,12 +446,12 @@ enum EdgeKind_systemz : Edge::Kind { /// - The result of the fixup expression must fit into an int16, otherwise /// an out-of-range error will be returned. /// - DeltaPLT12FromGOT, + Delta12FromGOT, - /// A GOT entry getter/constructor, transformed to DeltaPLT20FromGOT pointing + /// A GOT entry getter/constructor, transformed to Delta20FromGOT pointing /// at the GOT entry for the original target. /// - /// Indicates that this edge should be transformed into a DeltaPLT20FromGOT + /// Indicates that this edge should be transformed into a Delta20FromGOT /// targeting the GOT entry for the edge's current target, maintaining the /// same addend. A GOT entry for the target should be created if one does /// not already exist. @@ -431,12 +465,12 @@ enum EdgeKind_systemz : Edge::Kind { /// Errors: /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup /// - RequestGOTAndTransformToDeltaPLT20FromGOT, + RequestGOTAndTransformToDelta20FromGOT, - /// A GOT entry getter/constructor, transformed to DeltaPLT12FromGOT pointing + /// A GOT entry getter/constructor, transformed to Delta12FromGOT pointing /// at the GOT entry for the original target. /// - /// Indicates that this edge should be transformed into a DeltaPLT12FromGOT + /// Indicates that this edge should be transformed into a Delta12FromGOT /// targeting the GOT entry for the edge's current target, maintaining the /// same addend. A GOT entry for the target should be created if one does /// not already exist. @@ -451,7 +485,7 @@ enum EdgeKind_systemz : Edge::Kind { /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup /// phase will result in an assert/unreachable during the fixup phase. /// - RequestGOTAndTransformToDeltaPLT12FromGOT, + RequestGOTAndTransformToDelta12FromGOT, /// A GOT entry getter/constructor, transformed to Delta32dbl pointing at /// the GOT entry for the original target. @@ -473,44 +507,6 @@ enum EdgeKind_systemz : Edge::Kind { /// RequestGOTAndTransformToDelta32dbl, - /// A GOTPC entry getter/constructor, transformed to Delta32GOTBase - /// delta to GOT base. - /// - /// Indicates that this edge should be transformed into a Delta32GOTBase - /// targeting the GOTPC entry for the edge's current target, maintaining - /// the same addend. A GOTPC entry for the target should be created if - /// one does not already exist. - /// - /// Edges of this kind are usually handled by a GOTPC builder pass inserted - /// by default. - /// - /// Fixup expression: - /// NONE - /// - /// Errors: - /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup - /// phase will result in an assert/unreachable during the fixup phase. - RequestGOTPCAndTransformToDelta32GOTBase, - - /// A GOTPC entry getter/constructor, transformed to Delta32dblGOTBase - /// delta to GOT base. - /// - /// Indicates that this edge should be transformed into a Delta32dblGOTBase - /// targeting the GOTPC entry for the edge's current target, maintaining - /// the same addend. A GOTPC entry for the target should be created if - /// one does not already exist. - /// - /// Edges of this kind are usually handled by a GOTPC builder pass inserted - /// by default. - /// - /// Fixup expression: - /// NONE - /// - /// Errors: - /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup - /// phase will result in an assert/unreachable during the fixup phase. - RequestGOTPCAndTransformToDelta32dblGOTBase, - /// A 32-bit Delta to GOT base. /// /// Fixup expression: @@ -701,13 +697,15 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, write32be(FixupPtr, Value >> 1); break; } - case DeltaPLT64FromGOT: { + case Delta64PLTFromGOT: + case Delta64FromGOT: { assert(GOTSymbol && "No GOT section symbol"); int64_t Value = (S + A - GOTBase); write64be(FixupPtr, Value); break; } - case DeltaPLT32FromGOT: { + case Delta32PLTFromGOT: + case Delta32FromGOT: { assert(GOTSymbol && "No GOT section symbol"); int64_t Value = (S + A - GOTBase); if (!LLVM_UNLIKELY(isInt<32>(Value))) @@ -715,7 +713,8 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, write32be(FixupPtr, Value); break; } - case DeltaPLT16FromGOT: { + case Delta16PLTFromGOT: + case Delta16FromGOT: { assert(GOTSymbol && "No GOT section symbol"); int64_t Value = (S + A - GOTBase); if (!LLVM_UNLIKELY(isInt<16>(Value))) @@ -723,7 +722,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, write16be(FixupPtr, Value); break; } - case DeltaPLT20FromGOT: { + case Delta20FromGOT: { assert(GOTSymbol && "No GOT section symbol"); uint64_t Value = S - GOTBase + A; if (!LLVM_UNLIKELY(isInt<20>(Value))) @@ -732,7 +731,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, ((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4)); break; } - case DeltaPLT12FromGOT: { + case Delta12FromGOT: { assert(GOTSymbol && "No GOT section symbol"); uint64_t Value = S - GOTBase + A; if (!LLVM_UNLIKELY(isUInt<12>(Value))) @@ -819,20 +818,20 @@ class GOTTableManager : public TableManager { return false; Edge::Kind KindToSet = Edge::Invalid; switch (E.getKind()) { - case systemz::RequestGOTAndTransformToDeltaPLT12FromGOT: - KindToSet = systemz::DeltaPLT12FromGOT; + case systemz::RequestGOTAndTransformToDelta12FromGOT: + KindToSet = systemz::Delta12FromGOT; break; - case systemz::RequestGOTAndTransformToDeltaPLT16FromGOT: - KindToSet = systemz::DeltaPLT16FromGOT; + case systemz::RequestGOTAndTransformToDelta16FromGOT: + KindToSet = systemz::Delta16FromGOT; break; - case systemz::RequestGOTAndTransformToDeltaPLT20FromGOT: - KindToSet = systemz::DeltaPLT20FromGOT; + case systemz::RequestGOTAndTransformToDelta20FromGOT: + KindToSet = systemz::Delta20FromGOT; break; - case systemz::RequestGOTAndTransformToDeltaPLT32FromGOT: - KindToSet = systemz::DeltaPLT32FromGOT; + case systemz::RequestGOTAndTransformToDelta32FromGOT: + KindToSet = systemz::Delta32FromGOT; break; - case systemz::RequestGOTAndTransformToDeltaPLT64FromGOT: - KindToSet = systemz::DeltaPLT64FromGOT; + case systemz::RequestGOTAndTransformToDelta64FromGOT: + KindToSet = systemz::Delta64FromGOT; break; case systemz::RequestGOTAndTransformToDelta32dbl: KindToSet = systemz::DeltaPLT32dbl; @@ -885,9 +884,9 @@ class PLTTableManager : public TableManager { case systemz::DeltaPLT16dbl: case systemz::DeltaPLT24dbl: case systemz::DeltaPLT32dbl: - case systemz::DeltaPLT16FromGOT: - case systemz::DeltaPLT32FromGOT: - case systemz::DeltaPLT64FromGOT: + case systemz::Delta16PLTFromGOT: + case systemz::Delta32PLTFromGOT: + case systemz::Delta64PLTFromGOT: break; default: return false; @@ -918,53 +917,6 @@ class PLTTableManager : public TableManager { Section *StubsSection = nullptr; }; -/// GOTPC Table Builder. -class GOTPCTableManager : public TableManager { -public: - GOTPCTableManager(GOTTableManager &GOT) : GOT(GOT) {} - - static StringRef getSectionName() { return "$__GOTPC"; } - - bool visitEdge(LinkGraph &G, Block *B, Edge &E) { - Edge::Kind KindToSet = Edge::Invalid; - switch (E.getKind()) { - case systemz::RequestGOTPCAndTransformToDelta32GOTBase: - KindToSet = systemz::Delta32GOTBase; - break; - case systemz::RequestGOTPCAndTransformToDelta32dblGOTBase: - KindToSet = systemz::Delta32dblGOTBase; - break; - default: - return false; - } - assert(KindToSet != Edge::Invalid && - "Fell through switch, but no new kind to set"); - DEBUG_WITH_TYPE("jitlink", { - dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at " - << B->getFixupAddress(E) << " (" << B->getAddress() << " + " - << formatv("{0:x}", E.getOffset()) << ")\n"; - }); - E.setKind(KindToSet); - E.setTarget(getEntryForTarget(G, E.getTarget())); - return true; - } - - Symbol &createEntry(LinkGraph &G, Symbol &Target) { - return createAnonymousPointer(G, getGOTPCSection(G), &Target); - } - -private: - Section &getGOTPCSection(LinkGraph &G) { - if (!GOTPCSection) - GOTPCSection = &G.createSection(getSectionName(), - orc::MemProt::Read | orc::MemProt::Exec); - return *GOTPCSection; - } - - GOTTableManager &GOT; - Section *GOTPCSection = nullptr; -}; - } // namespace systemz } // namespace jitlink } // namespace llvm diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp index 9ddba46e3b211..2ad2b6226d58f 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp @@ -32,8 +32,7 @@ Error buildTables_ELF_systemz(LinkGraph &G) { LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); systemz::GOTTableManager GOT; systemz::PLTTableManager PLT(GOT); - systemz::GOTPCTableManager GOTPC(GOT); - visitExistingEdges(G, GOT, PLT, GOTPC); + visitExistingEdges(G, GOT, PLT); return Error::success(); } @@ -265,66 +264,69 @@ class ELFLinkGraphBuilder_systemz break; } case ELF::R_390_PLTOFF64: { - Kind = systemz::DeltaPLT64FromGOT; + Kind = systemz::Delta64PLTFromGOT; break; } case ELF::R_390_PLTOFF32: { - Kind = systemz::DeltaPLT32FromGOT; + Kind = systemz::Delta32PLTFromGOT; break; } case ELF::R_390_PLTOFF16: { - Kind = systemz::DeltaPLT16FromGOT; + Kind = systemz::Delta16PLTFromGOT; break; } - // Relocations targeting the GOT entry associated with the symbol. + // Relocations targeting the actual symbol (just relative to the GOT). case ELF::R_390_GOTOFF64: { - Kind = systemz::RequestGOTAndTransformToDeltaPLT64FromGOT; + Kind = systemz::RequestGOTAndTransformToDelta64FromGOT; break; } case ELF::R_390_GOTOFF: { - Kind = systemz::RequestGOTAndTransformToDeltaPLT32FromGOT; + Kind = systemz::RequestGOTAndTransformToDelta32FromGOT; break; } case ELF::R_390_GOTOFF16: { - Kind = systemz::RequestGOTAndTransformToDeltaPLT16FromGOT; + Kind = systemz::RequestGOTAndTransformToDelta16FromGOT; break; } + // Relocations targeting the GOT entry associated with the symbol. case ELF::R_390_GOT64: case ELF::R_390_GOTPLT64: { - Kind = systemz::RequestGOTAndTransformToDeltaPLT64FromGOT; + Kind = systemz::RequestGOTAndTransformToDelta64FromGOT; break; } case ELF::R_390_GOT32: case ELF::R_390_GOTPLT32: { - Kind = systemz::RequestGOTAndTransformToDeltaPLT32FromGOT; + Kind = systemz::RequestGOTAndTransformToDelta32FromGOT; break; } case ELF::R_390_GOT20: case ELF::R_390_GOTPLT20: { - Kind = systemz::RequestGOTAndTransformToDeltaPLT20FromGOT; + Kind = systemz::RequestGOTAndTransformToDelta20FromGOT; break; } case ELF::R_390_GOT16: case ELF::R_390_GOTPLT16: { - Kind = systemz::RequestGOTAndTransformToDeltaPLT16FromGOT; + Kind = systemz::RequestGOTAndTransformToDelta16FromGOT; break; } case ELF::R_390_GOT12: case ELF::R_390_GOTPLT12: { - Kind = systemz::RequestGOTAndTransformToDeltaPLT12FromGOT; + Kind = systemz::RequestGOTAndTransformToDelta12FromGOT; break; } - case ELF::R_390_GOTPC: { - Kind = systemz::RequestGOTPCAndTransformToDelta32GOTBase; + case ELF::R_390_GOTENT: + case ELF::R_390_GOTPLTENT: { + Kind = systemz::RequestGOTAndTransformToDelta32dbl; break; } - case ELF::R_390_GOTPCDBL: { - Kind = systemz::RequestGOTPCAndTransformToDelta32dblGOTBase; + // R_390_GOTPC and R_390_GOTPCDBL don't create GOT entry, they don't even + // have symbol. + case ELF::R_390_GOTPC: { + Kind = systemz::Delta32GOTBase; break; } - case ELF::R_390_GOTENT: - case ELF::R_390_GOTPLTENT: { - Kind = systemz::RequestGOTAndTransformToDelta32dbl; + case ELF::R_390_GOTPCDBL: { + Kind = systemz::Delta32dblGOTBase; break; } default: diff --git a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp index 7f6d18c04ca59..6cc6c79065d1d 100644 --- a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp @@ -64,12 +64,12 @@ const char *getEdgeKindName(Edge::Kind R) { return "NegDelta64"; case NegDelta32: return "NegDelta32"; - case RequestGOTAndTransformToDeltaPLT64FromGOT: - return "RequestGOTAndTransformToDeltaPLT64FromGOT"; - case RequestGOTAndTransformToDeltaPLT32FromGOT: - return "RequestGOTAndTransformToDeltaPLT32FromGOT"; - case RequestGOTAndTransformToDeltaPLT16FromGOT: - return "RequestGOTAndTransformToDeltaPLT16FromGOT"; + case RequestGOTAndTransformToDelta64FromGOT: + return "RequestGOTAndTransformToDelta64FromGOT"; + case RequestGOTAndTransformToDelta32FromGOT: + return "RequestGOTAndTransformToDelta32FromGOT"; + case RequestGOTAndTransformToDelta16FromGOT: + return "RequestGOTAndTransformToDelta16FromGOT"; case DeltaPLT32dbl: return "DeltaPLT32dbl"; case DeltaPLT24dbl: @@ -84,20 +84,22 @@ const char *getEdgeKindName(Edge::Kind R) { return "DeltaPLT64"; case DeltaPLT32: return "DeltaPLT32"; - case DeltaPLT64FromGOT: - return "DeltaPLT64FromGOT"; - case DeltaPLT32FromGOT: - return "DeltaPLT32FromGOT"; - case DeltaPLT16FromGOT: - return "DeltaPLT16FromGOT"; - case RequestGOTAndTransformToDeltaPLT20FromGOT: - return "RequestGOTAndTransformToDeltaPLT20FromGOT"; - case RequestGOTAndTransformToDeltaPLT12FromGOT: - return "RequestGOTAndTransformToDeltaPLT12FromGOT"; - case RequestGOTPCAndTransformToDelta32GOTBase: - return "RequestGOTPCAndTransformToDelta32GOTBase"; - case RequestGOTPCAndTransformToDelta32dblGOTBase: - return "RequestGOTPCAndTransformToDelta32dblGOTBase"; + case Delta64FromGOT: + return "Delta64FromGOT"; + case Delta32FromGOT: + return "Delta32FromGOT"; + case Delta16FromGOT: + return "Delta16FromGOT"; + case Delta64PLTFromGOT: + return "Delta64PLTFromGOT"; + case Delta32PLTFromGOT: + return "Delta32PLTFromGOT"; + case Delta16PLTFromGOT: + return "Delta16PLTFromGOT"; + case RequestGOTAndTransformToDelta20FromGOT: + return "RequestGOTAndTransformToDelta20FromGOT"; + case RequestGOTAndTransformToDelta12FromGOT: + return "RequestGOTAndTransformToDelta12FromGOT"; case Delta32GOTBase: return "Delta32GOTBase"; case Delta32dblGOTBase: From 5c118d31e2de0ece9f983dfe73b97dcf34f96632 Mon Sep 17 00:00:00 2001 From: anoopkg6 Date: Fri, 7 Nov 2025 01:45:20 +0100 Subject: [PATCH 09/14] Incorporate code review feedback --- .../llvm/ExecutionEngine/JITLink/systemz.h | 128 +++++++++--------- .../ExecutionEngine/JITLink/ELF_systemz.cpp | 6 +- .../JITLink/systemz/ELF_systemz_got.s | 78 ----------- .../systemz/ELF_systemz_reloc_call_pic.s | 14 +- .../systemz/ELF_systemz_reloc_gotrel.s | 16 +-- .../JITLink/systemz/ELF_systemz_reloc_pc16.s | 1 + .../JITLink/systemz/ELF_systemz_reloc_pc32.s | 1 + 7 files changed, 84 insertions(+), 160 deletions(-) delete mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_got.s diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h index 1ef5f693d87d8..a55a821a5226f 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h @@ -203,63 +203,6 @@ enum EdgeKind_systemz : Edge::Kind { /// an out-of-range error will be returned. NegDelta32, - /// A GOT entry getter/constructor, transformed to Delta64FromGOT pointing - /// at the GOT entry for the original target. - /// - /// Indicates that this edge should be transformed into a Delta64FromGOT - /// targeting the GOT entry for the edge's current target, maintaining the - /// same addend. A GOT entry for the target should be created if one does - /// not already exist. - /// - /// Edges of this kind are usually handled by a GOT builder pass inserted by - /// default. - /// - /// Fixup expression: - /// NONE - /// - /// Errors: - /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup - /// - RequestGOTAndTransformToDelta64FromGOT, - - /// A GOT entry getter/constructor, transformed to Delta32FromGOT pointing - /// at the GOT entry for the original target. - /// - /// Indicates that this edge should be transformed into a Delta32FromGOT - /// targeting the GOT entry for the edge's current target, maintaining the - /// same addend. A GOT entry for the target should be created if one does - /// not already exist. - /// - /// Edges of this kind are usually handled by a GOT builder pass inserted by - /// default. - /// - /// Fixup expression: - /// NONE - /// - /// Errors: - /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup - /// - RequestGOTAndTransformToDelta32FromGOT, - - /// A GOT entry getter/constructor, transformed to Delta16FromGOT pointing - /// at the GOT entry for the original target. - /// - /// Indicates that this edge should be transformed into a Delta16FromGOT - /// targeting the GOT entry for the edge's current target, maintaining the - /// same addend. A GOT entry for the target should be created if one does - /// not already exist. - /// - /// Edges of this kind are usually handled by a GOT builder pass inserted by - /// default. - /// - /// Fixup expression: - /// NONE - /// - /// Errors: - /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup - /// - RequestGOTAndTransformToDelta16FromGOT, - /// A 32-bit Delta shifted by 1. /// /// Delta from the fixup to the PLT slot for the target. This will lead to @@ -448,6 +391,44 @@ enum EdgeKind_systemz : Edge::Kind { /// Delta12FromGOT, + /// A GOT entry getter/constructor, transformed to Delta64FromGOT pointing + /// at the GOT entry for the original target. + /// + /// Indicates that this edge should be transformed into a Delta64FromGOT + /// targeting the GOT entry for the edge's current target, maintaining the + /// same addend. A GOT entry for the target should be created if one does + /// not already exist. + /// + /// Edges of this kind are usually handled by a GOT builder pass inserted by + /// default. + /// + /// Fixup expression: + /// NONE + /// + /// Errors: + /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup + /// + RequestGOTAndTransformToDelta64FromGOT, + + /// A GOT entry getter/constructor, transformed to Delta32FromGOT pointing + /// at the GOT entry for the original target. + /// + /// Indicates that this edge should be transformed into a Delta32FromGOT + /// targeting the GOT entry for the edge's current target, maintaining the + /// same addend. A GOT entry for the target should be created if one does + /// not already exist. + /// + /// Edges of this kind are usually handled by a GOT builder pass inserted by + /// default. + /// + /// Fixup expression: + /// NONE + /// + /// Errors: + /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup + /// + RequestGOTAndTransformToDelta32FromGOT, + /// A GOT entry getter/constructor, transformed to Delta20FromGOT pointing /// at the GOT entry for the original target. /// @@ -467,6 +448,25 @@ enum EdgeKind_systemz : Edge::Kind { /// RequestGOTAndTransformToDelta20FromGOT, + /// A GOT entry getter/constructor, transformed to Delta16FromGOT pointing + /// at the GOT entry for the original target. + /// + /// Indicates that this edge should be transformed into a Delta16FromGOT + /// targeting the GOT entry for the edge's current target, maintaining the + /// same addend. A GOT entry for the target should be created if one does + /// not already exist. + /// + /// Edges of this kind are usually handled by a GOT builder pass inserted by + /// default. + /// + /// Fixup expression: + /// NONE + /// + /// Errors: + /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup + /// + RequestGOTAndTransformToDelta16FromGOT, + /// A GOT entry getter/constructor, transformed to Delta12FromGOT pointing /// at the GOT entry for the original target. /// @@ -638,7 +638,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, } case Delta32dbl: case DeltaPLT32dbl: { - int64_t Value = (S + A - P); + int64_t Value = S + A - P; if (!LLVM_UNLIKELY(isInt<33>(Value))) return makeTargetOutOfRangeError(G, B, E); if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) @@ -648,7 +648,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, } case Delta24dbl: case DeltaPLT24dbl: { - int64_t Value = (S + A - P); + int64_t Value = S + A - P; if (!LLVM_UNLIKELY(isInt<25>(Value))) return makeTargetOutOfRangeError(G, B, E); if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) @@ -660,7 +660,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, } case Delta16dbl: case DeltaPLT16dbl: { - int64_t Value = (S + A - P); + int64_t Value = S + A - P; if (!LLVM_UNLIKELY(isInt<17>(Value))) return makeTargetOutOfRangeError(G, B, E); if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) @@ -670,7 +670,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, } case Delta12dbl: case DeltaPLT12dbl: { - int64_t Value = (S + A - P); + int64_t Value = S + A - P; if (!LLVM_UNLIKELY(isInt<13>(Value))) return makeTargetOutOfRangeError(G, B, E); if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) @@ -700,14 +700,14 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, case Delta64PLTFromGOT: case Delta64FromGOT: { assert(GOTSymbol && "No GOT section symbol"); - int64_t Value = (S + A - GOTBase); + int64_t Value = S + A - GOTBase; write64be(FixupPtr, Value); break; } case Delta32PLTFromGOT: case Delta32FromGOT: { assert(GOTSymbol && "No GOT section symbol"); - int64_t Value = (S + A - GOTBase); + int64_t Value = S + A - GOTBase; if (!LLVM_UNLIKELY(isInt<32>(Value))) return makeTargetOutOfRangeError(G, B, E); write32be(FixupPtr, Value); @@ -716,7 +716,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, case Delta16PLTFromGOT: case Delta16FromGOT: { assert(GOTSymbol && "No GOT section symbol"); - int64_t Value = (S + A - GOTBase); + int64_t Value = S + A - GOTBase; if (!LLVM_UNLIKELY(isInt<16>(Value))) return makeTargetOutOfRangeError(G, B, E); write16be(FixupPtr, Value); diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp index 2ad2b6226d58f..29eeecceea766 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp @@ -277,15 +277,15 @@ class ELFLinkGraphBuilder_systemz } // Relocations targeting the actual symbol (just relative to the GOT). case ELF::R_390_GOTOFF64: { - Kind = systemz::RequestGOTAndTransformToDelta64FromGOT; + Kind = systemz::Delta64FromGOT; break; } case ELF::R_390_GOTOFF: { - Kind = systemz::RequestGOTAndTransformToDelta32FromGOT; + Kind = systemz::Delta32FromGOT; break; } case ELF::R_390_GOTOFF16: { - Kind = systemz::RequestGOTAndTransformToDelta16FromGOT; + Kind = systemz::Delta16FromGOT; break; } // Relocations targeting the GOT entry associated with the symbol. diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_got.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_got.s deleted file mode 100644 index 00b111d5d59f1..0000000000000 --- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_got.s +++ /dev/null @@ -1,78 +0,0 @@ -# REQUIRES: system-linux -# RUN: rm -rf %t && mkdir -p %t -# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \ -# RUN: -filetype=obj -o %t/elf_reloc.o %s -# -# RUN: llvm-jitlink -noexec \ -# RUN: -slab-allocate 100Kb -slab-address 0x6ff00000 -slab-page-size 4096 \ -# RUN: -abs foo=0x6ff04040 \ -# RUN: -abs bar=0x6ff04048 \ -# RUN: %t/elf_reloc.o -# -# Check R_390_GOT* handling. - - .text - .globl main - .type main,@function -main: - larl %r12, _GLOBAL_OFFSET_TABLE_ - .reloc .+2, R_390_GOTENT, foo+2 - larl %r1, 0 - .reloc .+2, R_390_GOTENT, bar+2 - larl %r1, 0 - .reloc .+2, R_390_GOTPLTENT, foo+2 - larl %r1, 0 - .reloc .+2, R_390_GOTPLTENT, bar+2 - larl %r1, 0 - .reloc .+2, R_390_GOT12, foo - l %r1, 0(%r12) - .reloc .+2, R_390_GOT12, bar - l %r1, 0(%r12) - .reloc .+2, R_390_GOTPLT12, foo - l %r1, 0(%r12) - .reloc .+2, R_390_GOTPLT12, bar - l %r1, 0(%r12) - .reloc .+2, R_390_GOT20, foo - lg %r1, 0(%r12) - .reloc .+2, R_390_GOT20, bar - lg %r1, 0(%r12) - .reloc .+2, R_390_GOTPLT20, foo - lg %r1, 0(%r12) - .reloc .+2, R_390_GOTPLT20, bar - lg %r1, 0(%r12) - br %r14 - .size main, .-main - - .data - .reloc ., R_390_GOT16, foo - .space 2 - .reloc ., R_390_GOT16, bar - .space 2 - .reloc ., R_390_GOTPLT16, foo - .space 2 - .reloc ., R_390_GOTPLT16, bar - .space 2 - .reloc ., R_390_GOT32, foo - .space 4 - .reloc ., R_390_GOT32, bar - .space 4 - .reloc ., R_390_GOTPLT32, foo - .space 4 - .reloc ., R_390_GOTPLT32, bar - .space 4 - .reloc ., R_390_GOT64, foo - .space 8 - .reloc ., R_390_GOT64, bar - .space 8 - .reloc ., R_390_GOTPLT64, foo - .space 8 - .reloc ., R_390_GOTPLT64, bar - .space 8 - .reloc ., R_390_GOTPC, foo - .space 4 - .reloc ., R_390_GOTPC, bar - .space 4 - .reloc ., R_390_GOTPCDBL, foo - .space 4 - .reloc ., R_390_GOTPCDBL, bar - .space 4 diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s index 2b4c3d2102231..25a48e00e4413 100644 --- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s @@ -26,9 +26,9 @@ named_func: br %r14 .size named_func, .-named_func -# Check R_390_PLT32DBL handling with a call to a local function in the text -# section. This produces a Branch32 edge that is resolved like a regular -# BranchPCRelPLT32dbl(no PLT entry created). +# Check R_390_PC32DBL handling with a call to a local function in the text +# section. This produces a Delta32dbl edge that is resolved like a regular +# direct relative branches(no PLT entry created). # # jitlink-check: decode_operand(test_call_local, 1) = \ # jitlink-check: named_func - test_call_local @@ -40,8 +40,8 @@ test_call_local: .size test_call_local, .-test_call_local -# Check R_390_PLT32dbl(BranchPCRelPLT32dbl) handling with a call to an -# external via PLT. This produces a Branch32ToStub edge, because externals are +# Check R_390_PLT32dbl(DeltaPLT32dbl) handling with a call to an +# external via PLT. This produces a Delta32dbl edge, because externals are # not defined locally. As the target is out-of-range from the callsite, # the edge keeps using its PLT entry. # @@ -58,8 +58,8 @@ test_call_extern_plt: .size test_call_extern_plt, .-test_call_extern_plt -# Check R_390_PLT32(BranchPCRelPLT32dbl) handling with a call to an external. -# This produces a Branch32ToStub edge, because externals are not defined +# Check R_390_PLT32(DeltaPLT32dbl) handling with a call to an external. +# This produces a Delta32dbl edge, because externals are not defined # locally. During resolution, the target turns out to be in-range from the # callsite. ### TODO: edge can be relaxed in post-allocation optimization, it will then diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_gotrel.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_gotrel.s index bb1220d3780bb..af37b3f75ca42 100644 --- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_gotrel.s +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_gotrel.s @@ -18,8 +18,7 @@ main: .data .globl test_gotoff16_bar -# jitlink-check: *{2}test_gotoff16_bar = \ -# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) +# jitlink-check: *{2}test_gotoff16_bar = (bar - _GLOBAL_OFFSET_TABLE_) & 0xffff test_gotoff16_bar: .reloc ., R_390_GOTOFF16, bar .space 2 @@ -27,7 +26,8 @@ test_gotoff16_bar: .globl test_pltoff16_foo # jitlink-check: *{2}test_pltoff16_foo = \ -# jitlink-check: (stub_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) +# jitlink-check: (stub_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) \ +# jitlink-check: & 0xffff test_pltoff16_foo: .reloc ., R_390_PLTOFF16, foo .space 2 @@ -35,8 +35,8 @@ test_pltoff16_foo: .globl test_gotoff32_bar -# jitlink-check: *{4}test_gotoff32_bar = \ -# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) +# jitlink-check: *{4}test_gotoff32_bar = (bar - _GLOBAL_OFFSET_TABLE_) \ +# jitlink-check: & 0xffffffff test_gotoff32_bar: .reloc ., R_390_GOTOFF, bar .space 4 @@ -44,15 +44,15 @@ test_gotoff32_bar: .globl test_pltoff32_foo # jitlink-check: *{4}test_pltoff32_foo = \ -# jitlink-check: (stub_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) +# jitlink-check: (stub_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_) \ +# jitlink-check: & 0xffffffff test_pltoff32_foo: .reloc ., R_390_PLTOFF32, foo .space 4 .size test_pltoff32_foo, .-test_pltoff32_foo .globl test_gotoff64_bar -# jitlink-check: *{8}test_gotoff64_bar = \ -# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_) +# jitlink-check: *{8}test_gotoff64_bar = bar - _GLOBAL_OFFSET_TABLE_ test_gotoff64_bar: .reloc ., R_390_GOTOFF64, bar .space 8 diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc16.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc16.s index 47a7262902fd9..0da54b2a58972 100644 --- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc16.s +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc16.s @@ -14,6 +14,7 @@ # RUN: FileCheck -check-prefix=CHECK-ERROR %s # # jitlink-check: *{2}test_pc16 = OFFSET +# jitlink-check: *{2}test_pc16dbl = OFFSET # CHECK-ERROR: {{.*}} is out of range of Delta16 fixup diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc32.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc32.s index cda90dbe5a316..503fd2d0a5d49 100644 --- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc32.s +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc32.s @@ -14,6 +14,7 @@ # RUN: FileCheck -check-prefix=CHECK-ERROR %s # # jitlink-check: *{4}test_pc32 = OFFSET +# jitlink-check: *{4}test_pc32dbl = OFFSET # CHECK-ERROR: {{.*}} is out of range of Delta32 fixup From dde6b1f78954e7721396791f5dbeeda40e1b42c2 Mon Sep 17 00:00:00 2001 From: anoopkg6 Date: Fri, 7 Nov 2025 17:26:32 +0100 Subject: [PATCH 10/14] Minor cleanup --- llvm/lib/ExecutionEngine/JITLink/systemz.cpp | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp index 6cc6c79065d1d..e217729b1c7aa 100644 --- a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp @@ -64,12 +64,6 @@ const char *getEdgeKindName(Edge::Kind R) { return "NegDelta64"; case NegDelta32: return "NegDelta32"; - case RequestGOTAndTransformToDelta64FromGOT: - return "RequestGOTAndTransformToDelta64FromGOT"; - case RequestGOTAndTransformToDelta32FromGOT: - return "RequestGOTAndTransformToDelta32FromGOT"; - case RequestGOTAndTransformToDelta16FromGOT: - return "RequestGOTAndTransformToDelta16FromGOT"; case DeltaPLT32dbl: return "DeltaPLT32dbl"; case DeltaPLT24dbl: @@ -78,8 +72,6 @@ const char *getEdgeKindName(Edge::Kind R) { return "DeltaPLT16dbl"; case DeltaPLT12dbl: return "DeltaPLT12dbl"; - case RequestGOTAndTransformToDelta32dbl: - return "RequestGOTAndTransformToDelta32dbl"; case DeltaPLT64: return "DeltaPLT64"; case DeltaPLT32: @@ -96,14 +88,22 @@ const char *getEdgeKindName(Edge::Kind R) { return "Delta32PLTFromGOT"; case Delta16PLTFromGOT: return "Delta16PLTFromGOT"; - case RequestGOTAndTransformToDelta20FromGOT: - return "RequestGOTAndTransformToDelta20FromGOT"; - case RequestGOTAndTransformToDelta12FromGOT: - return "RequestGOTAndTransformToDelta12FromGOT"; case Delta32GOTBase: return "Delta32GOTBase"; case Delta32dblGOTBase: return "Delta32dblGOTBase"; + case RequestGOTAndTransformToDelta64FromGOT: + return "RequestGOTAndTransformToDelta64FromGOT"; + case RequestGOTAndTransformToDelta32FromGOT: + return "RequestGOTAndTransformToDelta32FromGOT"; + case RequestGOTAndTransformToDelta20FromGOT: + return "RequestGOTAndTransformToDelta20FromGOT"; + case RequestGOTAndTransformToDelta16FromGOT: + return "RequestGOTAndTransformToDelta16FromGOT"; + case RequestGOTAndTransformToDelta12FromGOT: + return "RequestGOTAndTransformToDelta12FromGOT"; + case RequestGOTAndTransformToDelta32dbl: + return "RequestGOTAndTransformToDelta32dbl"; default: return getGenericEdgeKindName(static_cast(R)); } From 9d41ed4c3ba827ac95b33f3b49380d0a31e4ea96 Mon Sep 17 00:00:00 2001 From: anoopkg6 Date: Tue, 11 Nov 2025 05:14:52 +0100 Subject: [PATCH 11/14] Fix Stub block Delta32dbl edge with Addend 2 at offset 2 --- llvm/include/llvm/ExecutionEngine/JITLink/systemz.h | 2 +- .../JITLink/systemz/ELF_systemz_reloc_call_pic.s | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h index a55a821a5226f..786341899a8a6 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h @@ -792,7 +792,7 @@ inline Block &createPointerJumpStubBlock(LinkGraph &G, Section &StubSection, Symbol &PointerSymbol) { auto &B = G.createContentBlock(StubSection, getStubBlockContent(G), orc::ExecutorAddr(), 8, 0); - B.addEdge(Delta32dbl, 2, PointerSymbol, 0); + B.addEdge(Delta32dbl, 2, PointerSymbol, 2); return B; } diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s index 25a48e00e4413..b753ec54b2361 100644 --- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s @@ -58,6 +58,19 @@ test_call_extern_plt: .size test_call_extern_plt, .-test_call_extern_plt +# Check PLT stub relocation for lgrl(Delta32dbl). +# +# jitlink-check: *{4}(stub_addr(elf_pic_reloc.o, extern_out_of_range32) + 2) = \ +# jitlink-check: (got_addr(elf_pic_reloc.o, extern_out_of_range32) - \ +# jitlink-check: stub_addr(elf_pic_reloc.o, extern_out_of_range32)) >> 1 + .globl test_call_extern_plt_stub + .p2align 4 + .type test_call_extern_plt_stub,@function +test_call_extern_plt_stub: + brasl %r14, extern_out_of_range32@plt + + .size test_call_extern_plt_stub, .-test_call_extern_plt_stub + # Check R_390_PLT32(DeltaPLT32dbl) handling with a call to an external. # This produces a Delta32dbl edge, because externals are not defined # locally. During resolution, the target turns out to be in-range from the From 50d8559af71e522449e8373991006e20e98301f7 Mon Sep 17 00:00:00 2001 From: anoopkg6 Date: Tue, 11 Nov 2025 16:45:47 +0100 Subject: [PATCH 12/14] Make Stub block alignment 16-bit and some minor clean up --- .../llvm/ExecutionEngine/JITLink/systemz.h | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h index 786341899a8a6..c4efd8dded99d 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h @@ -122,12 +122,12 @@ enum EdgeKind_systemz : Edge::Kind { /// Delta16, - /// A 32-bit delta. + /// A 32-bit delta shifted by 1. /// /// Delta from the fixup to the target. /// /// Fixup expression: - /// Fixup <- (Target - Fixup + Addend : int32) >> 1 + /// Fixup <- (Target - Fixup + Addend) >> 1 : int32 /// /// Errors: /// - The result of the fixup expression before shifting right by 1 must @@ -137,12 +137,12 @@ enum EdgeKind_systemz : Edge::Kind { /// Delta32dbl, - /// A 24-bit delta. + /// A 24-bit delta shifted by 1. /// /// Delta from the fixup to the target. /// /// Fixup expression: - /// Fixup <- (Target - Fixup + Addend : int24) >> 1 + /// Fixup <- (Target - Fixup + Addend) >> 1 : int24 /// /// Errors: /// - The result of the fixup expression before shifting right by 1 must @@ -152,12 +152,12 @@ enum EdgeKind_systemz : Edge::Kind { /// Delta24dbl, - /// A 16-bit delta. + /// A 16-bit delta shifted by 1. /// /// Delta from the fixup to the target. /// /// Fixup expression: - /// Fixup <- (Target - Fixup + Addend : int16) >> 1 + /// Fixup <- (Target - Fixup + Addend) >> 1 : int16 /// /// Errors: /// - The result of the fixup expression before shifting right by 1 must @@ -167,12 +167,12 @@ enum EdgeKind_systemz : Edge::Kind { /// Delta16dbl, - /// A 12-bit delta. + /// A 12-bit delta shifted by 1. /// /// Delta from the fixup to the target. /// /// Fixup expression: - /// Fixup <- (Target - Fixup + Addend : int12) >> 1 + /// Fixup <- (Target - Fixup + Addend) >> 1 : int12 /// /// Errors: /// - The result of the fixup expression before shifting right by 1 must @@ -689,7 +689,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, } case Delta32dblGOTBase: { assert(GOTSymbol && "No GOT section symbol"); - int64_t Value = (GOTBase + A - P); + int64_t Value = GOTBase + A - P; if (!LLVM_UNLIKELY(isInt<33>(Value))) return makeTargetOutOfRangeError(G, B, E); if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2))) @@ -786,12 +786,12 @@ inline Symbol &createAnonymousPointer(LinkGraph &G, Section &PointerSection, /// Create a jump stub block that jumps via the pointer at the given symbol. /// /// The stub block will have the following default values: -/// alignment: 8-bit +/// alignment: 16-bit /// alignment-offset: 0 inline Block &createPointerJumpStubBlock(LinkGraph &G, Section &StubSection, Symbol &PointerSymbol) { auto &B = G.createContentBlock(StubSection, getStubBlockContent(G), - orc::ExecutorAddr(), 8, 0); + orc::ExecutorAddr(), 16, 0); B.addEdge(Delta32dbl, 2, PointerSymbol, 2); return B; } From 9b5da091ab528e1270d976ec72649c23eb631c62 Mon Sep 17 00:00:00 2001 From: anoopkg6 Date: Tue, 11 Nov 2025 17:13:50 +0100 Subject: [PATCH 13/14] Corrected Stub size --- llvm/include/llvm/ExecutionEngine/JITLink/systemz.h | 2 +- llvm/lib/ExecutionEngine/JITLink/systemz.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h index c4efd8dded99d..dde3448cd5da7 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h @@ -761,7 +761,7 @@ inline ArrayRef getGOTEntryBlockContent(LinkGraph &G) { /// pointer: /// lgrl %r1, ptr /// j %r1 -constexpr size_t StubEntrySize = 14; +constexpr size_t StubEntrySize = 8; extern const char Pointer64JumpStubContent[StubEntrySize]; inline ArrayRef getStubBlockContent(LinkGraph &G) { auto StubContent = Pointer64JumpStubContent; diff --git a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp index e217729b1c7aa..f6cc29fa6e6a1 100644 --- a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp @@ -21,7 +21,7 @@ namespace systemz { const char NullPointerContent[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -const char Pointer64JumpStubContent[14] = { +const char Pointer64JumpStubContent[8] = { static_cast(0xC4u), 0x18, 0x00, From aeb8b49bf3188aef03618e634dd19a98b9d53162 Mon Sep 17 00:00:00 2001 From: anoopkg6 Date: Tue, 11 Nov 2025 19:13:29 +0100 Subject: [PATCH 14/14] Fix build failure --- .../JITLink/systemz/ELF_systemz_reloc_call_pic.s | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s index b753ec54b2361..743181655a5cc 100644 --- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s +++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s @@ -61,8 +61,9 @@ test_call_extern_plt: # Check PLT stub relocation for lgrl(Delta32dbl). # # jitlink-check: *{4}(stub_addr(elf_pic_reloc.o, extern_out_of_range32) + 2) = \ -# jitlink-check: (got_addr(elf_pic_reloc.o, extern_out_of_range32) - \ -# jitlink-check: stub_addr(elf_pic_reloc.o, extern_out_of_range32)) >> 1 +# jitlink-check: ((got_addr(elf_pic_reloc.o, extern_out_of_range32) - \ +# jitlink-check: stub_addr(elf_pic_reloc.o, extern_out_of_range32)) >> 1) \ +# jitlink-check: & 0xffffffff .globl test_call_extern_plt_stub .p2align 4 .type test_call_extern_plt_stub,@function