brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.1 KiB · 27209a8 Raw
598 lines · cpp
1//===---- MachO_x86_64.cpp -JIT linker implementation for MachO/x86-64 ----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// MachO/x86-64 jit-link implementation.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/ExecutionEngine/JITLink/MachO_x86_64.h"14#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"15#include "llvm/ExecutionEngine/JITLink/x86_64.h"16#include "llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h"17 18#include "CompactUnwindSupport.h"19#include "DefineExternalSectionStartAndEndSymbols.h"20#include "MachOLinkGraphBuilder.h"21 22#define DEBUG_TYPE "jitlink"23 24using namespace llvm;25using namespace llvm::jitlink;26 27namespace {28 29class MachOLinkGraphBuilder_x86_64 : public MachOLinkGraphBuilder {30public:31  MachOLinkGraphBuilder_x86_64(const object::MachOObjectFile &Obj,32                               std::shared_ptr<orc::SymbolStringPool> SSP,33                               SubtargetFeatures Features)34      : MachOLinkGraphBuilder(Obj, std::move(SSP),35                              Triple("x86_64-apple-darwin"),36                              std::move(Features), x86_64::getEdgeKindName) {}37 38private:39  enum MachONormalizedRelocationType : unsigned {40    MachOBranch32,41    MachOPointer32,42    MachOPointer64,43    MachOPointer64Anon,44    MachOPCRel32,45    MachOPCRel32Minus1,46    MachOPCRel32Minus2,47    MachOPCRel32Minus4,48    MachOPCRel32Anon,49    MachOPCRel32Minus1Anon,50    MachOPCRel32Minus2Anon,51    MachOPCRel32Minus4Anon,52    MachOPCRel32GOTLoad,53    MachOPCRel32GOT,54    MachOPCRel32TLV,55    MachOSubtractor32,56    MachOSubtractor64,57  };58 59  static Expected<MachONormalizedRelocationType>60  getRelocKind(const MachO::relocation_info &RI) {61    switch (RI.r_type) {62    case MachO::X86_64_RELOC_UNSIGNED:63      if (!RI.r_pcrel) {64        if (RI.r_length == 3)65          return RI.r_extern ? MachOPointer64 : MachOPointer64Anon;66        else if (RI.r_extern && RI.r_length == 2)67          return MachOPointer32;68      }69      break;70    case MachO::X86_64_RELOC_SIGNED:71      if (RI.r_pcrel && RI.r_length == 2)72        return RI.r_extern ? MachOPCRel32 : MachOPCRel32Anon;73      break;74    case MachO::X86_64_RELOC_BRANCH:75      if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)76        return MachOBranch32;77      break;78    case MachO::X86_64_RELOC_GOT_LOAD:79      if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)80        return MachOPCRel32GOTLoad;81      break;82    case MachO::X86_64_RELOC_GOT:83      if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)84        return MachOPCRel32GOT;85      break;86    case MachO::X86_64_RELOC_SUBTRACTOR:87      if (!RI.r_pcrel && RI.r_extern) {88        if (RI.r_length == 2)89          return MachOSubtractor32;90        else if (RI.r_length == 3)91          return MachOSubtractor64;92      }93      break;94    case MachO::X86_64_RELOC_SIGNED_1:95      if (RI.r_pcrel && RI.r_length == 2)96        return RI.r_extern ? MachOPCRel32Minus1 : MachOPCRel32Minus1Anon;97      break;98    case MachO::X86_64_RELOC_SIGNED_2:99      if (RI.r_pcrel && RI.r_length == 2)100        return RI.r_extern ? MachOPCRel32Minus2 : MachOPCRel32Minus2Anon;101      break;102    case MachO::X86_64_RELOC_SIGNED_4:103      if (RI.r_pcrel && RI.r_length == 2)104        return RI.r_extern ? MachOPCRel32Minus4 : MachOPCRel32Minus4Anon;105      break;106    case MachO::X86_64_RELOC_TLV:107      if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)108        return MachOPCRel32TLV;109      break;110    }111 112    return make_error<JITLinkError>(113        "Unsupported x86-64 relocation: address=" +114        formatv("{0:x8}", RI.r_address) +115        ", symbolnum=" + formatv("{0:x6}", RI.r_symbolnum) +116        ", kind=" + formatv("{0:x1}", RI.r_type) +117        ", pc_rel=" + (RI.r_pcrel ? "true" : "false") +118        ", extern=" + (RI.r_extern ? "true" : "false") +119        ", length=" + formatv("{0:d}", RI.r_length));120  }121 122  using PairRelocInfo = std::tuple<Edge::Kind, Symbol *, uint64_t>;123 124  // Parses paired SUBTRACTOR/UNSIGNED relocations and, on success,125  // returns the edge kind and addend to be used.126  Expected<PairRelocInfo> parsePairRelocation(127      Block &BlockToFix, MachONormalizedRelocationType SubtractorKind,128      const MachO::relocation_info &SubRI, orc::ExecutorAddr FixupAddress,129      const char *FixupContent, object::relocation_iterator &UnsignedRelItr,130      object::relocation_iterator &RelEnd) {131    using namespace support;132 133    assert(((SubtractorKind == MachOSubtractor32 && SubRI.r_length == 2) ||134            (SubtractorKind == MachOSubtractor64 && SubRI.r_length == 3)) &&135           "Subtractor kind should match length");136    assert(SubRI.r_extern && "SUBTRACTOR reloc symbol should be extern");137    assert(!SubRI.r_pcrel && "SUBTRACTOR reloc should not be PCRel");138 139    if (UnsignedRelItr == RelEnd)140      return make_error<JITLinkError>("x86_64 SUBTRACTOR without paired "141                                      "UNSIGNED relocation");142 143    auto UnsignedRI = getRelocationInfo(UnsignedRelItr);144 145    if (SubRI.r_address != UnsignedRI.r_address)146      return make_error<JITLinkError>("x86_64 SUBTRACTOR and paired UNSIGNED "147                                      "point to different addresses");148 149    if (SubRI.r_length != UnsignedRI.r_length)150      return make_error<JITLinkError>("length of x86_64 SUBTRACTOR and paired "151                                      "UNSIGNED reloc must match");152 153    Symbol *FromSymbol;154    if (auto FromSymbolOrErr = findSymbolByIndex(SubRI.r_symbolnum))155      FromSymbol = FromSymbolOrErr->GraphSymbol;156    else157      return FromSymbolOrErr.takeError();158 159    // Read the current fixup value.160    uint64_t FixupValue = 0;161    if (SubRI.r_length == 3)162      FixupValue = *(const little64_t *)FixupContent;163    else164      FixupValue = *(const little32_t *)FixupContent;165 166    // Find 'ToSymbol' using symbol number or address, depending on whether the167    // paired UNSIGNED relocation is extern.168    Symbol *ToSymbol = nullptr;169    if (UnsignedRI.r_extern) {170      // Find target symbol by symbol index.171      if (auto ToSymbolOrErr = findSymbolByIndex(UnsignedRI.r_symbolnum))172        ToSymbol = ToSymbolOrErr->GraphSymbol;173      else174        return ToSymbolOrErr.takeError();175    } else {176      auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1);177      if (!ToSymbolSec)178        return ToSymbolSec.takeError();179      ToSymbol = getSymbolByAddress(*ToSymbolSec, ToSymbolSec->Address);180      assert(ToSymbol && "No symbol for section");181      FixupValue -= ToSymbol->getAddress().getValue();182    }183 184    Edge::Kind DeltaKind;185    Symbol *TargetSymbol;186    uint64_t Addend;187 188    bool FixingFromSymbol = true;189    if (&BlockToFix == &FromSymbol->getAddressable()) {190      if (LLVM_UNLIKELY(&BlockToFix == &ToSymbol->getAddressable())) {191        // From and To are symbols in the same block. Decide direction by offset192        // instead.193        if (ToSymbol->getAddress() > FixupAddress)194          FixingFromSymbol = true;195        else if (FromSymbol->getAddress() > FixupAddress)196          FixingFromSymbol = false;197        else198          FixingFromSymbol = FromSymbol->getAddress() >= ToSymbol->getAddress();199      } else200        FixingFromSymbol = true;201    } else {202      if (&BlockToFix == &ToSymbol->getAddressable())203        FixingFromSymbol = false;204      else {205        // BlockToFix was neither FromSymbol nor ToSymbol.206        return make_error<JITLinkError>("SUBTRACTOR relocation must fix up "207                                        "either 'A' or 'B' (or a symbol in one "208                                        "of their alt-entry groups)");209      }210    }211 212    if (FixingFromSymbol) {213      TargetSymbol = ToSymbol;214      DeltaKind = (SubRI.r_length == 3) ? x86_64::Delta64 : x86_64::Delta32;215      Addend = FixupValue + (FixupAddress - FromSymbol->getAddress());216      // FIXME: handle extern 'from'.217    } else {218      TargetSymbol = FromSymbol;219      DeltaKind =220          (SubRI.r_length == 3) ? x86_64::NegDelta64 : x86_64::NegDelta32;221      Addend = FixupValue - (FixupAddress - ToSymbol->getAddress());222    }223 224    return PairRelocInfo(DeltaKind, TargetSymbol, Addend);225  }226 227  Error addRelocations() override {228    using namespace support;229    auto &Obj = getObject();230 231    LLVM_DEBUG(dbgs() << "Processing relocations:\n");232 233    for (const auto &S : Obj.sections()) {234 235      orc::ExecutorAddr SectionAddress(S.getAddress());236 237      // Skip relocations virtual sections.238      if (S.isVirtual()) {239        if (!S.relocations().empty())240          return make_error<JITLinkError>("Virtual section contains "241                                          "relocations");242        continue;243      }244 245      auto NSec =246          findSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));247      if (!NSec)248        return NSec.takeError();249 250      // Skip relocations for MachO sections without corresponding graph251      // sections.252      {253        if (!NSec->GraphSection) {254          LLVM_DEBUG({255            dbgs() << "  Skipping relocations for MachO section "256                   << NSec->SegName << "/" << NSec->SectName257                   << " which has no associated graph section\n";258          });259          continue;260        }261      }262 263      // Add relocations for section.264      for (auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();265           RelItr != RelEnd; ++RelItr) {266 267        MachO::relocation_info RI = getRelocationInfo(RelItr);268 269        // Find the address of the value to fix up.270        auto FixupAddress = SectionAddress + (uint32_t)RI.r_address;271 272        LLVM_DEBUG({273          dbgs() << "  " << NSec->SectName << " + "274                 << formatv("{0:x8}", RI.r_address) << ":\n";275        });276 277        // Find the block that the fixup points to.278        Block *BlockToFix = nullptr;279        {280          auto SymbolToFixOrErr = findSymbolByAddress(*NSec, FixupAddress);281          if (!SymbolToFixOrErr)282            return SymbolToFixOrErr.takeError();283          BlockToFix = &SymbolToFixOrErr->getBlock();284        }285 286        if (FixupAddress + orc::ExecutorAddrDiff(1ULL << RI.r_length) >287            BlockToFix->getAddress() + BlockToFix->getContent().size())288          return make_error<JITLinkError>(289              "Relocation extends past end of fixup block");290 291        // Get a pointer to the fixup content.292        const char *FixupContent = BlockToFix->getContent().data() +293                                   (FixupAddress - BlockToFix->getAddress());294 295        size_t FixupOffset = FixupAddress - BlockToFix->getAddress();296 297        // The target symbol and addend will be populated by the switch below.298        Symbol *TargetSymbol = nullptr;299        uint64_t Addend = 0;300 301        // Validate the relocation kind.302        auto MachORelocKind = getRelocKind(RI);303        if (!MachORelocKind)304          return MachORelocKind.takeError();305 306        Edge::Kind Kind = Edge::Invalid;307 308        switch (*MachORelocKind) {309        case MachOBranch32:310          if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))311            TargetSymbol = TargetSymbolOrErr->GraphSymbol;312          else313            return TargetSymbolOrErr.takeError();314          Addend = *(const little32_t *)FixupContent;315          Kind = x86_64::BranchPCRel32;316          break;317        case MachOPCRel32:318          if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))319            TargetSymbol = TargetSymbolOrErr->GraphSymbol;320          else321            return TargetSymbolOrErr.takeError();322          Addend = *(const little32_t *)FixupContent - 4;323          Kind = x86_64::Delta32;324          break;325        case MachOPCRel32GOTLoad:326          if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))327            TargetSymbol = TargetSymbolOrErr->GraphSymbol;328          else329            return TargetSymbolOrErr.takeError();330          Addend = *(const little32_t *)FixupContent;331          Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable;332          if (FixupOffset < 3)333            return make_error<JITLinkError>("GOTLD at invalid offset " +334                                            formatv("{0}", FixupOffset));335          break;336        case MachOPCRel32GOT:337          if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))338            TargetSymbol = TargetSymbolOrErr->GraphSymbol;339          else340            return TargetSymbolOrErr.takeError();341          Addend = *(const little32_t *)FixupContent - 4;342          Kind = x86_64::RequestGOTAndTransformToDelta32;343          break;344        case MachOPCRel32TLV:345          if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))346            TargetSymbol = TargetSymbolOrErr->GraphSymbol;347          else348            return TargetSymbolOrErr.takeError();349          Addend = *(const little32_t *)FixupContent;350          Kind = x86_64::RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable;351          if (FixupOffset < 3)352            return make_error<JITLinkError>("TLV at invalid offset " +353                                            formatv("{0}", FixupOffset));354          break;355        case MachOPointer32:356          if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))357            TargetSymbol = TargetSymbolOrErr->GraphSymbol;358          else359            return TargetSymbolOrErr.takeError();360          Addend = *(const ulittle32_t *)FixupContent;361          Kind = x86_64::Pointer32;362          break;363        case MachOPointer64:364          if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))365            TargetSymbol = TargetSymbolOrErr->GraphSymbol;366          else367            return TargetSymbolOrErr.takeError();368          Addend = *(const ulittle64_t *)FixupContent;369          Kind = x86_64::Pointer64;370          break;371        case MachOPointer64Anon: {372          orc::ExecutorAddr TargetAddress(*(const ulittle64_t *)FixupContent);373          auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);374          if (!TargetNSec)375            return TargetNSec.takeError();376          if (auto TargetSymbolOrErr =377                  findSymbolByAddress(*TargetNSec, TargetAddress))378            TargetSymbol = &*TargetSymbolOrErr;379          else380            return TargetSymbolOrErr.takeError();381          Addend = TargetAddress - TargetSymbol->getAddress();382          Kind = x86_64::Pointer64;383          break;384        }385        case MachOPCRel32Minus1:386        case MachOPCRel32Minus2:387        case MachOPCRel32Minus4:388          if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))389            TargetSymbol = TargetSymbolOrErr->GraphSymbol;390          else391            return TargetSymbolOrErr.takeError();392          Addend = *(const little32_t *)FixupContent - 4;393          Kind = x86_64::Delta32;394          break;395        case MachOPCRel32Anon: {396          orc::ExecutorAddr TargetAddress(FixupAddress + 4 +397                                          *(const little32_t *)FixupContent);398          auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);399          if (!TargetNSec)400            return TargetNSec.takeError();401          if (auto TargetSymbolOrErr =402                  findSymbolByAddress(*TargetNSec, TargetAddress))403            TargetSymbol = &*TargetSymbolOrErr;404          else405            return TargetSymbolOrErr.takeError();406          Addend = TargetAddress - TargetSymbol->getAddress() - 4;407          Kind = x86_64::Delta32;408          break;409        }410        case MachOPCRel32Minus1Anon:411        case MachOPCRel32Minus2Anon:412        case MachOPCRel32Minus4Anon: {413          orc::ExecutorAddrDiff Delta =414              4 + orc::ExecutorAddrDiff(415                      1ULL << (*MachORelocKind - MachOPCRel32Minus1Anon));416          orc::ExecutorAddr TargetAddress =417              FixupAddress + Delta + *(const little32_t *)FixupContent;418          auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);419          if (!TargetNSec)420            return TargetNSec.takeError();421          if (auto TargetSymbolOrErr =422                  findSymbolByAddress(*TargetNSec, TargetAddress))423            TargetSymbol = &*TargetSymbolOrErr;424          else425            return TargetSymbolOrErr.takeError();426          Addend = TargetAddress - TargetSymbol->getAddress() - Delta;427          Kind = x86_64::Delta32;428          break;429        }430        case MachOSubtractor32:431        case MachOSubtractor64: {432          // We use Delta32/Delta64 to represent SUBTRACTOR relocations.433          // parsePairRelocation handles the paired reloc, and returns the434          // edge kind to be used (either Delta32/Delta64, or435          // NegDelta32/NegDelta64, depending on the direction of the436          // subtraction) along with the addend.437          auto PairInfo =438              parsePairRelocation(*BlockToFix, *MachORelocKind, RI,439                                  FixupAddress, FixupContent, ++RelItr, RelEnd);440          if (!PairInfo)441            return PairInfo.takeError();442          std::tie(Kind, TargetSymbol, Addend) = *PairInfo;443          assert(TargetSymbol && "No target symbol from parsePairRelocation?");444          break;445        }446        }447 448        LLVM_DEBUG({449          dbgs() << "    ";450          Edge GE(Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol,451                  Addend);452          printEdge(dbgs(), *BlockToFix, GE, x86_64::getEdgeKindName(Kind));453          dbgs() << "\n";454        });455        BlockToFix->addEdge(Kind, FixupAddress - BlockToFix->getAddress(),456                            *TargetSymbol, Addend);457      }458    }459    return Error::success();460  }461};462 463Error buildGOTAndStubs_MachO_x86_64(LinkGraph &G) {464  x86_64::GOTTableManager GOT(G);465  x86_64::PLTTableManager PLT(G, GOT);466  visitExistingEdges(G, GOT, PLT);467  return Error::success();468}469 470} // namespace471 472namespace llvm {473namespace jitlink {474 475class MachOJITLinker_x86_64 : public JITLinker<MachOJITLinker_x86_64> {476  friend class JITLinker<MachOJITLinker_x86_64>;477 478public:479  MachOJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,480                        std::unique_ptr<LinkGraph> G,481                        PassConfiguration PassConfig)482      : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}483 484private:485  Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {486    return x86_64::applyFixup(G, B, E, nullptr);487  }488};489 490Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromMachOObject_x86_64(491    MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {492  auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer);493  if (!MachOObj)494    return MachOObj.takeError();495 496  auto Features = (*MachOObj)->getFeatures();497  if (!Features)498    return Features.takeError();499 500  return MachOLinkGraphBuilder_x86_64(**MachOObj, std::move(SSP),501                                      std::move(*Features))502      .buildGraph();503}504 505struct CompactUnwindTraits_MachO_x86_64506    : public CompactUnwindTraits<CompactUnwindTraits_MachO_x86_64,507                                 /* PointerSize = */ 8> {508  // FIXME: Reinstate once we no longer need the MSVC workaround. See509  //        FIXME for CompactUnwindTraits in CompactUnwindSupport.h.510  // constexpr static size_t PointerSize = 8;511 512  constexpr static endianness Endianness = endianness::little;513 514  constexpr static uint32_t EncodingModeMask = 0x0f000000;515  constexpr static uint32_t DWARFSectionOffsetMask = 0x00ffffff;516 517  using GOTManager = x86_64::GOTTableManager;518 519  static bool encodingSpecifiesDWARF(uint32_t Encoding) {520    constexpr uint32_t DWARFMode = 0x04000000;521    return (Encoding & EncodingModeMask) == DWARFMode;522  }523 524  static bool encodingCannotBeMerged(uint32_t Encoding) {525    constexpr uint32_t StackIndirectMode = 0x03000000;526    return (Encoding & EncodingModeMask) == StackIndirectMode;527  }528};529 530void link_MachO_x86_64(std::unique_ptr<LinkGraph> G,531                       std::unique_ptr<JITLinkContext> Ctx) {532 533  PassConfiguration Config;534 535  if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {536    // Add a mark-live pass.537    if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))538      Config.PrePrunePasses.push_back(std::move(MarkLive));539    else540      Config.PrePrunePasses.push_back(markAllSymbolsLive);541 542    // Add eh-frame passes.543    Config.PrePrunePasses.push_back(createEHFrameSplitterPass_MachO_x86_64());544    Config.PrePrunePasses.push_back(createEHFrameEdgeFixerPass_MachO_x86_64());545 546    // Create a compact-unwind manager for use in passes below.547    auto CompactUnwindMgr = std::make_shared<548        CompactUnwindManager<CompactUnwindTraits_MachO_x86_64>>(549        orc::MachOCompactUnwindSectionName, orc::MachOUnwindInfoSectionName,550        orc::MachOEHFrameSectionName);551 552    // Add compact unwind prepare pass.553    Config.PrePrunePasses.push_back([CompactUnwindMgr](LinkGraph &G) {554      return CompactUnwindMgr->prepareForPrune(G);555    });556 557    // Resolve any external section start / end symbols.558    Config.PostAllocationPasses.push_back(559        createDefineExternalSectionStartAndEndSymbolsPass(560            identifyMachOSectionStartAndEndSymbols));561 562    // Add an in-place GOT/Stubs pass.563    Config.PostPrunePasses.push_back(buildGOTAndStubs_MachO_x86_64);564 565    // Reserve space for unwind-info.566    Config.PostPrunePasses.push_back([CompactUnwindMgr](LinkGraph &G) {567      return CompactUnwindMgr->processAndReserveUnwindInfo(G);568    });569 570    // Translate compact-unwind to unwind-info.571    Config.PreFixupPasses.push_back([CompactUnwindMgr](LinkGraph &G) {572      return CompactUnwindMgr->writeUnwindInfo(G);573    });574 575    // Add GOT/Stubs optimizer pass.576    Config.PreFixupPasses.push_back(x86_64::optimizeGOTAndStubAccesses);577  }578 579  if (auto Err = Ctx->modifyPassConfig(*G, Config))580    return Ctx->notifyFailed(std::move(Err));581 582  // Construct a JITLinker and run the link function.583  MachOJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));584}585 586LinkGraphPassFunction createEHFrameSplitterPass_MachO_x86_64() {587  return DWARFRecordSectionSplitter(orc::MachOEHFrameSectionName);588}589 590LinkGraphPassFunction createEHFrameEdgeFixerPass_MachO_x86_64() {591  return EHFrameEdgeFixer(orc::MachOEHFrameSectionName, x86_64::PointerSize,592                          x86_64::Pointer32, x86_64::Pointer64, x86_64::Delta32,593                          x86_64::Delta64, x86_64::NegDelta32);594}595 596} // end namespace jitlink597} // end namespace llvm598