xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp (revision e92ffd9b626833ebdbf2742c8ffddc6cd94b963e)
1 //===---- ELF_x86_64.cpp -JIT linker implementation for ELF/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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // ELF/x86-64 jit-link implementation.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
14 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
15 #include "llvm/ExecutionEngine/JITLink/x86_64.h"
16 #include "llvm/Object/ELFObjectFile.h"
17 #include "llvm/Support/Endian.h"
18 
19 #include "DefineExternalSectionStartAndEndSymbols.h"
20 #include "EHFrameSupportImpl.h"
21 #include "ELFLinkGraphBuilder.h"
22 #include "JITLinkGeneric.h"
23 #include "PerGraphGOTAndPLTStubsBuilder.h"
24 
25 #define DEBUG_TYPE "jitlink"
26 
27 using namespace llvm;
28 using namespace llvm::jitlink;
29 using namespace llvm::jitlink::ELF_x86_64_Edges;
30 
31 namespace {
32 
33 constexpr StringRef ELFGOTSectionName = "$__GOT";
34 constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_";
35 
36 class PerGraphGOTAndPLTStubsBuilder_ELF_x86_64
37     : public PerGraphGOTAndPLTStubsBuilder<
38           PerGraphGOTAndPLTStubsBuilder_ELF_x86_64> {
39 public:
40   static const uint8_t NullGOTEntryContent[8];
41   static const uint8_t StubContent[6];
42 
43   using PerGraphGOTAndPLTStubsBuilder<
44       PerGraphGOTAndPLTStubsBuilder_ELF_x86_64>::PerGraphGOTAndPLTStubsBuilder;
45 
46   bool isGOTEdgeToFix(Edge &E) const {
47     if (E.getKind() == GOTOFF64) {
48       // We need to make sure that the GOT section exists, but don't otherwise
49       // need to fix up this edge.
50       getGOTSection();
51       return false;
52     }
53 
54     return E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad ||
55            E.getKind() == PCRel64GOT || E.getKind() == GOT64;
56   }
57 
58   Symbol &createGOTEntry(Symbol &Target) {
59     auto &GOTEntryBlock = G.createContentBlock(
60         getGOTSection(), getGOTEntryBlockContent(), 0, 8, 0);
61     GOTEntryBlock.addEdge(Pointer64, 0, Target, 0);
62     return G.addAnonymousSymbol(GOTEntryBlock, 0, 8, false, false);
63   }
64 
65   void fixGOTEdge(Edge &E, Symbol &GOTEntry) {
66     // If this is a PCRel32GOT/PCRel64GOT then change it to an ordinary
67     // PCRel32/PCRel64. If it is a PCRel32GOTLoad then leave it as-is for now:
68     // We will use the kind to check for GOT optimization opportunities in the
69     // optimizeMachO_x86_64_GOTAndStubs pass below.
70     // If it's a GOT64 leave it as is.
71     switch (E.getKind()) {
72     case PCRel32GOT:
73       E.setKind(PCRel32);
74       break;
75     case PCRel64GOT:
76       E.setKind(PCRel64);
77       break;
78     case GOT64:
79       break;
80     case PCRel32GOTLoad:
81       break;
82     default:
83       llvm_unreachable("Unexpected GOT edge kind");
84     }
85 
86     E.setTarget(GOTEntry);
87     // Leave the edge addend as-is.
88   }
89 
90   bool isExternalBranchEdge(Edge &E) {
91     return E.getKind() == Branch32 && !E.getTarget().isDefined();
92   }
93 
94   Symbol &createPLTStub(Symbol &Target) {
95     auto &StubContentBlock =
96         G.createContentBlock(getStubsSection(), getStubBlockContent(), 0, 1, 0);
97     // Re-use GOT entries for stub targets.
98     auto &GOTEntrySymbol = getGOTEntry(Target);
99     StubContentBlock.addEdge(PCRel32, 2, GOTEntrySymbol, -4);
100     return G.addAnonymousSymbol(StubContentBlock, 0, 6, true, false);
101   }
102 
103   void fixPLTEdge(Edge &E, Symbol &Stub) {
104     assert(E.getKind() == Branch32 && "Not a Branch32 edge?");
105 
106     // Set the edge kind to Branch32ToStub. We will use this to check for stub
107     // optimization opportunities in the optimize ELF_x86_64_GOTAndStubs pass
108     // below.
109     E.setKind(Branch32ToStub);
110     E.setTarget(Stub);
111   }
112 
113 private:
114   Section &getGOTSection() const {
115     if (!GOTSection)
116       GOTSection = &G.createSection(ELFGOTSectionName, sys::Memory::MF_READ);
117     return *GOTSection;
118   }
119 
120   Section &getStubsSection() const {
121     if (!StubsSection) {
122       auto StubsProt = static_cast<sys::Memory::ProtectionFlags>(
123           sys::Memory::MF_READ | sys::Memory::MF_EXEC);
124       StubsSection = &G.createSection("$__STUBS", StubsProt);
125     }
126     return *StubsSection;
127   }
128 
129   ArrayRef<char> getGOTEntryBlockContent() {
130     return {reinterpret_cast<const char *>(NullGOTEntryContent),
131             sizeof(NullGOTEntryContent)};
132   }
133 
134   ArrayRef<char> getStubBlockContent() {
135     return {reinterpret_cast<const char *>(StubContent), sizeof(StubContent)};
136   }
137 
138   mutable Section *GOTSection = nullptr;
139   mutable Section *StubsSection = nullptr;
140 };
141 
142 } // namespace
143 
144 const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_x86_64::NullGOTEntryContent[8] =
145     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
146 const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_x86_64::StubContent[6] = {
147     0xFF, 0x25, 0x00, 0x00, 0x00, 0x00};
148 
149 static Error optimizeELF_x86_64_GOTAndStubs(LinkGraph &G) {
150   LLVM_DEBUG(dbgs() << "Optimizing GOT entries and stubs:\n");
151 
152   for (auto *B : G.blocks())
153     for (auto &E : B->edges())
154       if (E.getKind() == PCRel32GOTLoad) {
155         // Replace GOT load with LEA only for MOVQ instructions.
156         constexpr uint8_t MOVQRIPRel[] = {0x48, 0x8b};
157         if (E.getOffset() < 3 ||
158             strncmp(B->getContent().data() + E.getOffset() - 3,
159                     reinterpret_cast<const char *>(MOVQRIPRel), 2) != 0)
160           continue;
161 
162         auto &GOTBlock = E.getTarget().getBlock();
163         assert(GOTBlock.getSize() == G.getPointerSize() &&
164                "GOT entry block should be pointer sized");
165         assert(GOTBlock.edges_size() == 1 &&
166                "GOT entry should only have one outgoing edge");
167 
168         auto &GOTTarget = GOTBlock.edges().begin()->getTarget();
169         JITTargetAddress EdgeAddr = B->getAddress() + E.getOffset();
170         JITTargetAddress TargetAddr = GOTTarget.getAddress();
171 
172         int64_t Displacement = TargetAddr - EdgeAddr + 4;
173         if (Displacement >= std::numeric_limits<int32_t>::min() &&
174             Displacement <= std::numeric_limits<int32_t>::max()) {
175           // Change the edge kind as we don't go through GOT anymore. This is
176           // for formal correctness only. Technically, the two relocation kinds
177           // are resolved the same way.
178           E.setKind(PCRel32);
179           E.setTarget(GOTTarget);
180           auto *BlockData = reinterpret_cast<uint8_t *>(
181               const_cast<char *>(B->getContent().data()));
182           BlockData[E.getOffset() - 2] = 0x8d;
183           LLVM_DEBUG({
184             dbgs() << "  Replaced GOT load wih LEA:\n    ";
185             printEdge(dbgs(), *B, E, getELFX86RelocationKindName(E.getKind()));
186             dbgs() << "\n";
187           });
188         }
189       } else if (E.getKind() == Branch32ToStub) {
190         auto &StubBlock = E.getTarget().getBlock();
191         assert(
192             StubBlock.getSize() ==
193                 sizeof(PerGraphGOTAndPLTStubsBuilder_ELF_x86_64::StubContent) &&
194             "Stub block should be stub sized");
195         assert(StubBlock.edges_size() == 1 &&
196                "Stub block should only have one outgoing edge");
197 
198         auto &GOTBlock = StubBlock.edges().begin()->getTarget().getBlock();
199         assert(GOTBlock.getSize() == G.getPointerSize() &&
200                "GOT block should be pointer sized");
201         assert(GOTBlock.edges_size() == 1 &&
202                "GOT block should only have one outgoing edge");
203 
204         auto &GOTTarget = GOTBlock.edges().begin()->getTarget();
205         JITTargetAddress EdgeAddr = B->getAddress() + E.getOffset();
206         JITTargetAddress TargetAddr = GOTTarget.getAddress();
207 
208         int64_t Displacement = TargetAddr - EdgeAddr + 4;
209         if (Displacement >= std::numeric_limits<int32_t>::min() &&
210             Displacement <= std::numeric_limits<int32_t>::max()) {
211           E.setKind(Branch32);
212           E.setTarget(GOTTarget);
213           LLVM_DEBUG({
214             dbgs() << "  Replaced stub branch with direct branch:\n    ";
215             printEdge(dbgs(), *B, E, getELFX86RelocationKindName(E.getKind()));
216             dbgs() << "\n";
217           });
218         }
219       }
220 
221   return Error::success();
222 }
223 
224 namespace llvm {
225 namespace jitlink {
226 
227 // This should become a template as the ELFFile is so a lot of this could become
228 // generic
229 class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> {
230 private:
231 
232   static Expected<ELF_x86_64_Edges::ELFX86RelocationKind>
233   getRelocationKind(const uint32_t Type) {
234     switch (Type) {
235     case ELF::R_X86_64_PC32:
236       return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32;
237     case ELF::R_X86_64_PC64:
238     case ELF::R_X86_64_GOTPC64:
239       return ELF_x86_64_Edges::ELFX86RelocationKind::Delta64;
240     case ELF::R_X86_64_64:
241       return ELF_x86_64_Edges::ELFX86RelocationKind::Pointer64;
242     case ELF::R_X86_64_GOTPCREL:
243     case ELF::R_X86_64_GOTPCRELX:
244     case ELF::R_X86_64_REX_GOTPCRELX:
245       return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32GOTLoad;
246     case ELF::R_X86_64_GOTPCREL64:
247       return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel64GOT;
248     case ELF::R_X86_64_GOT64:
249       return ELF_x86_64_Edges::ELFX86RelocationKind::GOT64;
250     case ELF::R_X86_64_GOTOFF64:
251       return ELF_x86_64_Edges::ELFX86RelocationKind::GOTOFF64;
252     case ELF::R_X86_64_PLT32:
253       return ELF_x86_64_Edges::ELFX86RelocationKind::Branch32;
254     }
255     return make_error<JITLinkError>("Unsupported x86-64 relocation:" +
256                                     formatv("{0:d}", Type));
257   }
258 
259   Error addRelocations() override {
260     LLVM_DEBUG(dbgs() << "Adding relocations\n");
261     // TODO a partern is forming of iterate some sections but only give me
262     // ones I am interested, i should abstract that concept some where
263     for (auto &SecRef : Sections) {
264       if (SecRef.sh_type != ELF::SHT_RELA && SecRef.sh_type != ELF::SHT_REL)
265         continue;
266       // TODO can the elf obj file do this for me?
267       if (SecRef.sh_type == ELF::SHT_REL)
268         return make_error<llvm::StringError>("Shouldn't have REL in x64",
269                                              llvm::inconvertibleErrorCode());
270 
271       auto RelSectName = Obj.getSectionName(SecRef);
272       if (!RelSectName)
273         return RelSectName.takeError();
274 
275       LLVM_DEBUG({
276         dbgs() << "Adding relocations from section " << *RelSectName << "\n";
277       });
278 
279       auto UpdateSection = Obj.getSection(SecRef.sh_info);
280       if (!UpdateSection)
281         return UpdateSection.takeError();
282 
283       auto UpdateSectionName = Obj.getSectionName(**UpdateSection);
284       if (!UpdateSectionName)
285         return UpdateSectionName.takeError();
286 
287       // Don't process relocations for debug sections.
288       if (isDwarfSection(*UpdateSectionName)) {
289         LLVM_DEBUG({
290           dbgs() << "  Target is dwarf section " << *UpdateSectionName
291                  << ". Skipping.\n";
292         });
293         continue;
294       } else
295         LLVM_DEBUG({
296           dbgs() << "  For target section " << *UpdateSectionName << "\n";
297         });
298 
299       auto JITSection = G->findSectionByName(*UpdateSectionName);
300       if (!JITSection)
301         return make_error<llvm::StringError>(
302             "Refencing a a section that wasn't added to graph" +
303                 *UpdateSectionName,
304             llvm::inconvertibleErrorCode());
305 
306       auto Relocations = Obj.relas(SecRef);
307       if (!Relocations)
308         return Relocations.takeError();
309 
310       for (const auto &Rela : *Relocations) {
311         auto Type = Rela.getType(false);
312 
313         LLVM_DEBUG({
314           dbgs() << "Relocation Type: " << Type << "\n"
315                  << "Name: " << Obj.getRelocationTypeName(Type) << "\n";
316         });
317         auto SymbolIndex = Rela.getSymbol(false);
318         auto Symbol = Obj.getRelocationSymbol(Rela, SymTabSec);
319         if (!Symbol)
320           return Symbol.takeError();
321 
322         auto BlockToFix = *(JITSection->blocks().begin());
323         auto *TargetSymbol = getGraphSymbol(SymbolIndex);
324 
325         if (!TargetSymbol) {
326           return make_error<llvm::StringError>(
327               "Could not find symbol at given index, did you add it to "
328               "JITSymbolTable? index: " +
329                   std::to_string(SymbolIndex) +
330                   ", shndx: " + std::to_string((*Symbol)->st_shndx) +
331                   " Size of table: " + std::to_string(GraphSymbols.size()),
332               llvm::inconvertibleErrorCode());
333         }
334         uint64_t Addend = Rela.r_addend;
335         JITTargetAddress FixupAddress =
336             (*UpdateSection)->sh_addr + Rela.r_offset;
337 
338         LLVM_DEBUG({
339           dbgs() << "Processing relocation at "
340                  << format("0x%016" PRIx64, FixupAddress) << "\n";
341         });
342         auto Kind = getRelocationKind(Type);
343         if (!Kind)
344           return Kind.takeError();
345 
346         LLVM_DEBUG({
347           Edge GE(*Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol,
348                   Addend);
349           printEdge(dbgs(), *BlockToFix, GE,
350                     getELFX86RelocationKindName(*Kind));
351           dbgs() << "\n";
352         });
353         BlockToFix->addEdge(*Kind, FixupAddress - BlockToFix->getAddress(),
354                             *TargetSymbol, Addend);
355       }
356     }
357     return Error::success();
358   }
359 
360 public:
361   ELFLinkGraphBuilder_x86_64(StringRef FileName,
362                              const object::ELFFile<object::ELF64LE> &Obj)
363       : ELFLinkGraphBuilder(Obj, Triple("x86_64-unknown-linux"), FileName,
364                             getELFX86RelocationKindName) {}
365 };
366 
367 class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
368   friend class JITLinker<ELFJITLinker_x86_64>;
369 
370 public:
371   ELFJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
372                       std::unique_ptr<LinkGraph> G,
373                       PassConfiguration PassConfig)
374       : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {
375     getPassConfig().PostAllocationPasses.push_back(
376         [this](LinkGraph &G) { return getOrCreateGOTSymbol(G); });
377   }
378 
379 private:
380   Symbol *GOTSymbol = nullptr;
381 
382   Error getOrCreateGOTSymbol(LinkGraph &G) {
383     auto DefineExternalGOTSymbolIfPresent =
384         createDefineExternalSectionStartAndEndSymbolsPass(
385             [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc {
386               if (Sym.getName() == ELFGOTSymbolName)
387                 if (auto *GOTSection = G.findSectionByName(ELFGOTSectionName)) {
388                   GOTSymbol = &Sym;
389                   return {*GOTSection, true};
390                 }
391               return {};
392             });
393 
394     // Try to attach _GLOBAL_OFFSET_TABLE_ to the GOT if it's defined as an
395     // external.
396     if (auto Err = DefineExternalGOTSymbolIfPresent(G))
397       return Err;
398 
399     // If we succeeded then we're done.
400     if (GOTSymbol)
401       return Error::success();
402 
403     // Otherwise look for a GOT section: If it already has a start symbol we'll
404     // record it, otherwise we'll create our own.
405     // If there's a GOT section but we didn't find an external GOT symbol...
406     if (auto *GOTSection = G.findSectionByName(ELFGOTSectionName)) {
407 
408       // Check for an existing defined symbol.
409       for (auto *Sym : GOTSection->symbols())
410         if (Sym->getName() == ELFGOTSymbolName) {
411           GOTSymbol = Sym;
412           return Error::success();
413         }
414 
415       // If there's no defined symbol then create one.
416       SectionRange SR(*GOTSection);
417       if (SR.empty())
418         GOTSymbol = &G.addAbsoluteSymbol(ELFGOTSymbolName, 0, 0,
419                                          Linkage::Strong, Scope::Local, true);
420       else
421         GOTSymbol =
422             &G.addDefinedSymbol(*SR.getFirstBlock(), 0, ELFGOTSymbolName, 0,
423                                 Linkage::Strong, Scope::Local, false, true);
424     }
425 
426     return Error::success();
427   }
428 
429   Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
430     using namespace ELF_x86_64_Edges;
431     using namespace llvm::support;
432 
433     char *BlockWorkingMem = B.getAlreadyMutableContent().data();
434     char *FixupPtr = BlockWorkingMem + E.getOffset();
435     JITTargetAddress FixupAddress = B.getAddress() + E.getOffset();
436     switch (E.getKind()) {
437     case ELFX86RelocationKind::Branch32:
438     case ELFX86RelocationKind::Branch32ToStub:
439     case ELFX86RelocationKind::PCRel32:
440     case ELFX86RelocationKind::PCRel32GOTLoad: {
441       int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
442       if (LLVM_LIKELY(x86_64::isInRangeForImmS32(Value)))
443         *(little32_t *)FixupPtr = Value;
444       else
445         return makeTargetOutOfRangeError(G, B, E);
446       break;
447     }
448     case ELFX86RelocationKind::PCRel64: {
449       int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
450       *(little64_t *)FixupPtr = Value;
451       break;
452     }
453     case ELFX86RelocationKind::Pointer64: {
454       int64_t Value = E.getTarget().getAddress() + E.getAddend();
455       *(ulittle64_t *)FixupPtr = Value;
456       break;
457     }
458     case ELFX86RelocationKind::Delta32: {
459       int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
460       if (LLVM_LIKELY(x86_64::isInRangeForImmS32(Value)))
461         *(little32_t *)FixupPtr = Value;
462       else
463         return makeTargetOutOfRangeError(G, B, E);
464       break;
465     }
466     case ELFX86RelocationKind::Delta64: {
467       int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
468       *(little64_t *)FixupPtr = Value;
469       break;
470     }
471     case ELFX86RelocationKind::NegDelta32: {
472       int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend();
473       if (LLVM_LIKELY(x86_64::isInRangeForImmS32(Value)))
474         *(little32_t *)FixupPtr = Value;
475       else
476         return makeTargetOutOfRangeError(G, B, E);
477       break;
478     }
479     case ELFX86RelocationKind::NegDelta64: {
480       int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend();
481       *(little64_t *)FixupPtr = Value;
482       break;
483     }
484     case ELFX86RelocationKind::GOT64:
485     case ELFX86RelocationKind::GOTOFF64: {
486       // GOT64: Offset of GOT entry within GOT.
487       // GOTOFF64: Offset from GOT base to target.
488       // The expressions are the same in both cases, but in the GOT64 case the
489       // edge will have been fixed to point at the GOT entry, and in the
490       // GOTOFF64 case it will still point at the original target.
491       assert(GOTSymbol && "No GOT section symbol");
492       int64_t Value =
493           E.getTarget().getAddress() - GOTSymbol->getAddress() + E.getAddend();
494       *(little64_t *)FixupPtr = Value;
495       break;
496     }
497     default:
498       LLVM_DEBUG({
499         dbgs() << "Bad edge: " << getELFX86RelocationKindName(E.getKind())
500                << "\n";
501       });
502       llvm_unreachable("Unsupported relocation");
503     }
504     return Error::success();
505   }
506 };
507 
508 Expected<std::unique_ptr<LinkGraph>>
509 createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer) {
510   LLVM_DEBUG({
511     dbgs() << "Building jitlink graph for new input "
512            << ObjectBuffer.getBufferIdentifier() << "...\n";
513   });
514 
515   auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
516   if (!ELFObj)
517     return ELFObj.takeError();
518 
519   auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
520   return ELFLinkGraphBuilder_x86_64((*ELFObj)->getFileName(),
521                                     ELFObjFile.getELFFile())
522       .buildGraph();
523 }
524 
525 static SectionRangeSymbolDesc
526 identifyELFSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym) {
527   constexpr StringRef StartSymbolPrefix = "__start";
528   constexpr StringRef EndSymbolPrefix = "__end";
529 
530   auto SymName = Sym.getName();
531   if (SymName.startswith(StartSymbolPrefix)) {
532     if (auto *Sec =
533             G.findSectionByName(SymName.drop_front(StartSymbolPrefix.size())))
534       return {*Sec, true};
535   } else if (SymName.startswith(EndSymbolPrefix)) {
536     if (auto *Sec =
537             G.findSectionByName(SymName.drop_front(EndSymbolPrefix.size())))
538       return {*Sec, false};
539   }
540   return {};
541 }
542 
543 void link_ELF_x86_64(std::unique_ptr<LinkGraph> G,
544                      std::unique_ptr<JITLinkContext> Ctx) {
545   PassConfiguration Config;
546 
547   if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
548 
549     Config.PrePrunePasses.push_back(EHFrameSplitter(".eh_frame"));
550     Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
551         ".eh_frame", G->getPointerSize(), Delta64, Delta32, NegDelta32));
552     Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
553 
554     // Construct a JITLinker and run the link function.
555     // Add a mark-live pass.
556     if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
557       Config.PrePrunePasses.push_back(std::move(MarkLive));
558     else
559       Config.PrePrunePasses.push_back(markAllSymbolsLive);
560 
561     // Add an in-place GOT/Stubs pass.
562     Config.PostPrunePasses.push_back(
563         PerGraphGOTAndPLTStubsBuilder_ELF_x86_64::asPass);
564 
565     // Resolve any external section start / end symbols.
566     Config.PostAllocationPasses.push_back(
567         createDefineExternalSectionStartAndEndSymbolsPass(
568             identifyELFSectionStartAndEndSymbols));
569 
570     // Add GOT/Stubs optimizer pass.
571     Config.PreFixupPasses.push_back(optimizeELF_x86_64_GOTAndStubs);
572   }
573 
574   if (auto Err = Ctx->modifyPassConfig(*G, Config))
575     return Ctx->notifyFailed(std::move(Err));
576 
577   ELFJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));
578 }
579 const char *getELFX86RelocationKindName(Edge::Kind R) {
580   switch (R) {
581   case Branch32:
582     return "Branch32";
583   case Branch32ToStub:
584     return "Branch32ToStub";
585   case Pointer32:
586     return "Pointer32";
587   case Pointer64:
588     return "Pointer64";
589   case Pointer64Anon:
590     return "Pointer64Anon";
591   case PCRel32:
592     return "PCRel32";
593   case PCRel32Minus1:
594     return "PCRel32Minus1";
595   case PCRel32Minus2:
596     return "PCRel32Minus2";
597   case PCRel32Minus4:
598     return "PCRel32Minus4";
599   case PCRel32Anon:
600     return "PCRel32Anon";
601   case PCRel32Minus1Anon:
602     return "PCRel32Minus1Anon";
603   case PCRel32Minus2Anon:
604     return "PCRel32Minus2Anon";
605   case PCRel32Minus4Anon:
606     return "PCRel32Minus4Anon";
607   case PCRel32GOTLoad:
608     return "PCRel32GOTLoad";
609   case PCRel32GOT:
610     return "PCRel32GOT";
611   case PCRel32TLV:
612     return "PCRel32TLV";
613   case Delta32:
614     return "Delta32";
615   case Delta64:
616     return "Delta64";
617   case NegDelta32:
618     return "NegDelta32";
619   case NegDelta64:
620     return "NegDelta64";
621   }
622   return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
623 }
624 } // end namespace jitlink
625 } // end namespace llvm
626