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