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 "BasicGOTAndStubsBuilder.h"
15 #include "JITLinkGeneric.h"
16 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
17 #include "llvm/Object/ELFObjectFile.h"
18 #include "llvm/Support/Endian.h"
19 
20 #define DEBUG_TYPE "jitlink"
21 
22 using namespace llvm;
23 using namespace llvm::jitlink;
24 using namespace llvm::jitlink::ELF_x86_64_Edges;
25 
26 namespace {
27 class ELF_x86_64_GOTAndStubsBuilder
28     : public BasicGOTAndStubsBuilder<ELF_x86_64_GOTAndStubsBuilder> {
29 public:
30   static const uint8_t NullGOTEntryContent[8];
31   static const uint8_t StubContent[6];
32 
33   ELF_x86_64_GOTAndStubsBuilder(LinkGraph &G)
34       : BasicGOTAndStubsBuilder<ELF_x86_64_GOTAndStubsBuilder>(G) {}
35 
36   bool isGOTEdge(Edge &E) const {
37     return E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad;
38   }
39 
40   Symbol &createGOTEntry(Symbol &Target) {
41     auto &GOTEntryBlock = G.createContentBlock(
42         getGOTSection(), getGOTEntryBlockContent(), 0, 8, 0);
43     GOTEntryBlock.addEdge(Pointer64, 0, Target, 0);
44     return G.addAnonymousSymbol(GOTEntryBlock, 0, 8, false, false);
45   }
46 
47   void fixGOTEdge(Edge &E, Symbol &GOTEntry) {
48     assert((E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad) &&
49            "Not a GOT edge?");
50     // If this is a PCRel32GOT then change it to an ordinary PCRel32. If it is
51     // a PCRel32GOTLoad then leave it as-is for now. We will use the kind to
52     // check for GOT optimization opportunities in the
53     // optimizeMachO_x86_64_GOTAndStubs pass below.
54     if (E.getKind() == PCRel32GOT)
55       E.setKind(PCRel32);
56 
57     E.setTarget(GOTEntry);
58     // Leave the edge addend as-is.
59   }
60 
61   bool isExternalBranchEdge(Edge &E) {
62     return E.getKind() == Branch32 && !E.getTarget().isDefined();
63   }
64 
65   Symbol &createStub(Symbol &Target) {
66     auto &StubContentBlock =
67         G.createContentBlock(getStubsSection(), getStubBlockContent(), 0, 1, 0);
68     // Re-use GOT entries for stub targets.
69     auto &GOTEntrySymbol = getGOTEntrySymbol(Target);
70     StubContentBlock.addEdge(PCRel32, 2, GOTEntrySymbol, 0);
71     return G.addAnonymousSymbol(StubContentBlock, 0, 6, true, false);
72   }
73 
74   void fixExternalBranchEdge(Edge &E, Symbol &Stub) {
75     assert(E.getKind() == Branch32 && "Not a Branch32 edge?");
76     assert(E.getAddend() == 0 && "Branch32 edge has non-zero addend?");
77 
78     // Set the edge kind to Branch32ToStub. We will use this to check for stub
79     // optimization opportunities in the optimize ELF_x86_64_GOTAndStubs pass
80     // below.
81     E.setKind(Branch32ToStub);
82     E.setTarget(Stub);
83   }
84 
85 private:
86   Section &getGOTSection() {
87     if (!GOTSection)
88       GOTSection = &G.createSection("$__GOT", sys::Memory::MF_READ);
89     return *GOTSection;
90   }
91 
92   Section &getStubsSection() {
93     if (!StubsSection) {
94       auto StubsProt = static_cast<sys::Memory::ProtectionFlags>(
95           sys::Memory::MF_READ | sys::Memory::MF_EXEC);
96       StubsSection = &G.createSection("$__STUBS", StubsProt);
97     }
98     return *StubsSection;
99   }
100 
101   StringRef getGOTEntryBlockContent() {
102     return StringRef(reinterpret_cast<const char *>(NullGOTEntryContent),
103                      sizeof(NullGOTEntryContent));
104   }
105 
106   StringRef getStubBlockContent() {
107     return StringRef(reinterpret_cast<const char *>(StubContent),
108                      sizeof(StubContent));
109   }
110 
111   Section *GOTSection = nullptr;
112   Section *StubsSection = nullptr;
113 };
114 } // namespace
115 
116 const uint8_t ELF_x86_64_GOTAndStubsBuilder::NullGOTEntryContent[8] = {
117     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
118 const uint8_t ELF_x86_64_GOTAndStubsBuilder::StubContent[6] = {
119     0xFF, 0x25, 0x00, 0x00, 0x00, 0x00};
120 
121 static const char *CommonSectionName = "__common";
122 static Error optimizeELF_x86_64_GOTAndStubs(LinkGraph &G) {
123   LLVM_DEBUG(dbgs() << "Optimizing GOT entries and stubs:\n");
124 
125   for (auto *B : G.blocks())
126     for (auto &E : B->edges())
127       if (E.getKind() == PCRel32GOTLoad) {
128         // Replace GOT load with LEA only for MOVQ instructions.
129         constexpr uint8_t MOVQRIPRel[] = {0x48, 0x8b};
130         if (E.getOffset() < 3 ||
131             strncmp(B->getContent().data() + E.getOffset() - 3,
132                     reinterpret_cast<const char *>(MOVQRIPRel), 2) != 0)
133           continue;
134 
135         auto &GOTBlock = E.getTarget().getBlock();
136         assert(GOTBlock.getSize() == G.getPointerSize() &&
137                "GOT entry block should be pointer sized");
138         assert(GOTBlock.edges_size() == 1 &&
139                "GOT entry should only have one outgoing edge");
140 
141         auto &GOTTarget = GOTBlock.edges().begin()->getTarget();
142         JITTargetAddress EdgeAddr = B->getAddress() + E.getOffset();
143         JITTargetAddress TargetAddr = GOTTarget.getAddress();
144 
145         int64_t Displacement = TargetAddr - EdgeAddr + 4;
146         if (Displacement >= std::numeric_limits<int32_t>::min() &&
147             Displacement <= std::numeric_limits<int32_t>::max()) {
148           // Change the edge kind as we don't go through GOT anymore. This is
149           // for formal correctness only. Technically, the two relocation kinds
150           // are resolved the same way.
151           E.setKind(PCRel32);
152           E.setTarget(GOTTarget);
153           auto *BlockData = reinterpret_cast<uint8_t *>(
154               const_cast<char *>(B->getContent().data()));
155           BlockData[E.getOffset() - 2] = 0x8d;
156           LLVM_DEBUG({
157             dbgs() << "  Replaced GOT load wih LEA:\n    ";
158             printEdge(dbgs(), *B, E, getELFX86RelocationKindName(E.getKind()));
159             dbgs() << "\n";
160           });
161         }
162       } else if (E.getKind() == Branch32ToStub) {
163 
164         // Switch the edge kind to PCRel32: Whether we change the edge target
165         // or not this will be the desired kind.
166         E.setKind(Branch32);
167 
168         auto &StubBlock = E.getTarget().getBlock();
169         assert(StubBlock.getSize() ==
170                    sizeof(ELF_x86_64_GOTAndStubsBuilder::StubContent) &&
171                "Stub block should be stub sized");
172         assert(StubBlock.edges_size() == 1 &&
173                "Stub block should only have one outgoing edge");
174 
175         auto &GOTBlock = StubBlock.edges().begin()->getTarget().getBlock();
176         assert(GOTBlock.getSize() == G.getPointerSize() &&
177                "GOT block should be pointer sized");
178         assert(GOTBlock.edges_size() == 1 &&
179                "GOT block should only have one outgoing edge");
180 
181         auto &GOTTarget = GOTBlock.edges().begin()->getTarget();
182         JITTargetAddress EdgeAddr = B->getAddress() + E.getOffset();
183         JITTargetAddress TargetAddr = GOTTarget.getAddress();
184 
185         int64_t Displacement = TargetAddr - EdgeAddr + 4;
186         if (Displacement >= std::numeric_limits<int32_t>::min() &&
187             Displacement <= std::numeric_limits<int32_t>::max()) {
188           E.setTarget(GOTTarget);
189           LLVM_DEBUG({
190             dbgs() << "  Replaced stub branch with direct branch:\n    ";
191             printEdge(dbgs(), *B, E, getELFX86RelocationKindName(E.getKind()));
192             dbgs() << "\n";
193           });
194         }
195       }
196 
197   return Error::success();
198 }
199 namespace llvm {
200 namespace jitlink {
201 
202 // This should become a template as the ELFFile is so a lot of this could become
203 // generic
204 class ELFLinkGraphBuilder_x86_64 {
205 
206 private:
207   Section *CommonSection = nullptr;
208   // TODO hack to get this working
209   // Find a better way
210   using SymbolTable = object::ELFFile<object::ELF64LE>::Elf_Shdr;
211   // For now we just assume
212   using SymbolMap = std::map<int32_t, Symbol *>;
213   SymbolMap JITSymbolTable;
214 
215   Section &getCommonSection() {
216     if (!CommonSection) {
217       auto Prot = static_cast<sys::Memory::ProtectionFlags>(
218           sys::Memory::MF_READ | sys::Memory::MF_WRITE);
219       CommonSection = &G->createSection(CommonSectionName, Prot);
220     }
221     return *CommonSection;
222   }
223 
224   static Expected<ELF_x86_64_Edges::ELFX86RelocationKind>
225   getRelocationKind(const uint32_t Type) {
226     switch (Type) {
227     case ELF::R_X86_64_PC32:
228       return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32;
229     case ELF::R_X86_64_64:
230       return ELF_x86_64_Edges::ELFX86RelocationKind::Pointer64;
231     case ELF::R_X86_64_GOTPCREL:
232     case ELF::R_X86_64_GOTPCRELX:
233     case ELF::R_X86_64_REX_GOTPCRELX:
234       return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32GOTLoad;
235     }
236     return make_error<JITLinkError>("Unsupported x86-64 relocation:" +
237                                     formatv("{0:d}", Type));
238   }
239 
240   std::unique_ptr<LinkGraph> G;
241   // This could be a template
242   const object::ELFFile<object::ELF64LE> &Obj;
243   object::ELFFile<object::ELF64LE>::Elf_Shdr_Range sections;
244   SymbolTable SymTab;
245 
246   bool isRelocatable() { return Obj.getHeader().e_type == llvm::ELF::ET_REL; }
247 
248   support::endianness
249   getEndianness(const object::ELFFile<object::ELF64LE> &Obj) {
250     return Obj.isLE() ? support::little : support::big;
251   }
252 
253   // This could also just become part of a template
254   unsigned getPointerSize(const object::ELFFile<object::ELF64LE> &Obj) {
255     return Obj.getHeader().getFileClass() == ELF::ELFCLASS64 ? 8 : 4;
256   }
257 
258   // We don't technically need this right now
259   // But for now going to keep it as it helps me to debug things
260 
261   Error createNormalizedSymbols() {
262     LLVM_DEBUG(dbgs() << "Creating normalized symbols...\n");
263 
264     for (auto SecRef : sections) {
265       if (SecRef.sh_type != ELF::SHT_SYMTAB &&
266           SecRef.sh_type != ELF::SHT_DYNSYM)
267         continue;
268 
269       auto Symbols = Obj.symbols(&SecRef);
270       // TODO: Currently I use this function to test things
271       // I also want to leave it to see if its common between MACH and elf
272       // so for now I just want to continue even if there is an error
273       if (errorToBool(Symbols.takeError()))
274         continue;
275 
276       auto StrTabSec = Obj.getSection(SecRef.sh_link);
277       if (!StrTabSec)
278         return StrTabSec.takeError();
279       auto StringTable = Obj.getStringTable(**StrTabSec);
280       if (!StringTable)
281         return StringTable.takeError();
282 
283       for (auto SymRef : *Symbols) {
284         Optional<StringRef> Name;
285 
286         if (auto NameOrErr = SymRef.getName(*StringTable))
287           Name = *NameOrErr;
288         else
289           return NameOrErr.takeError();
290 
291         LLVM_DEBUG({
292           dbgs() << "  ";
293           if (!Name)
294             dbgs() << "<anonymous symbol>";
295           else
296             dbgs() << *Name;
297           dbgs() << ": value = " << formatv("{0:x16}", SymRef.getValue())
298                  << ", type = " << formatv("{0:x2}", SymRef.getType())
299                  << ", binding = " << SymRef.getBinding()
300                  << ", size =" << SymRef.st_size
301                  << ", info =" << SymRef.st_info;
302           dbgs() << "\n";
303         });
304       }
305     }
306     return Error::success();
307   }
308 
309   Error createNormalizedSections() {
310     LLVM_DEBUG(dbgs() << "Creating normalized sections...\n");
311     for (auto &SecRef : sections) {
312       auto Name = Obj.getSectionName(SecRef);
313       if (!Name)
314         return Name.takeError();
315       sys::Memory::ProtectionFlags Prot;
316       if (SecRef.sh_flags & ELF::SHF_EXECINSTR) {
317         Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
318                                                          sys::Memory::MF_EXEC);
319       } else {
320         Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
321                                                          sys::Memory::MF_WRITE);
322       }
323       uint64_t Address = SecRef.sh_addr;
324       uint64_t Size = SecRef.sh_size;
325       uint64_t Flags = SecRef.sh_flags;
326       uint64_t Alignment = SecRef.sh_addralign;
327       const char *Data = nullptr;
328       // for now we just use this to skip the "undefined" section, probably need
329       // to revist
330       if (Size == 0)
331         continue;
332 
333       // FIXME: Use flags.
334       (void)Flags;
335 
336       LLVM_DEBUG({
337         dbgs() << "  " << *Name << ": " << formatv("{0:x16}", Address) << " -- "
338                << formatv("{0:x16}", Address + Size) << ", align: " << Alignment
339                << " Flags:" << Flags << "\n";
340       });
341 
342       if (SecRef.sh_type != ELF::SHT_NOBITS) {
343         // .sections() already checks that the data is not beyond the end of
344         // file
345         auto contents = Obj.getSectionContentsAsArray<char>(SecRef);
346         if (!contents)
347           return contents.takeError();
348 
349         Data = contents->data();
350         // TODO protection flags.
351         // for now everything is
352         auto &section = G->createSection(*Name, Prot);
353         // Do this here because we have it, but move it into graphify later
354         G->createContentBlock(section, StringRef(Data, Size), Address,
355                               Alignment, 0);
356         if (SecRef.sh_type == ELF::SHT_SYMTAB)
357           // TODO: Dynamic?
358           SymTab = SecRef;
359       } else {
360         auto &Section = G->createSection(*Name, Prot);
361         G->createZeroFillBlock(Section, Size, Address, Alignment, 0);
362       }
363     }
364 
365     return Error::success();
366   }
367 
368   Error addRelocations() {
369     LLVM_DEBUG(dbgs() << "Adding relocations\n");
370     // TODO a partern is forming of iterate some sections but only give me
371     // ones I am interested, i should abstract that concept some where
372     for (auto &SecRef : sections) {
373       if (SecRef.sh_type != ELF::SHT_RELA && SecRef.sh_type != ELF::SHT_REL)
374         continue;
375       // TODO can the elf obj file do this for me?
376       if (SecRef.sh_type == ELF::SHT_REL)
377         return make_error<llvm::StringError>("Shouldn't have REL in x64",
378                                              llvm::inconvertibleErrorCode());
379 
380       auto RelSectName = Obj.getSectionName(SecRef);
381       if (!RelSectName)
382         return RelSectName.takeError();
383       // Deal with .eh_frame later
384       if (*RelSectName == StringRef(".rela.eh_frame"))
385         continue;
386 
387       auto UpdateSection = Obj.getSection(SecRef.sh_info);
388       if (!UpdateSection)
389         return UpdateSection.takeError();
390 
391       auto UpdateSectionName = Obj.getSectionName(**UpdateSection);
392       if (!UpdateSectionName)
393         return UpdateSectionName.takeError();
394 
395       auto JITSection = G->findSectionByName(*UpdateSectionName);
396       if (!JITSection)
397         return make_error<llvm::StringError>(
398             "Refencing a a section that wasn't added to graph" +
399                 *UpdateSectionName,
400             llvm::inconvertibleErrorCode());
401 
402       auto Relocations = Obj.relas(SecRef);
403       if (!Relocations)
404         return Relocations.takeError();
405 
406       for (const auto &Rela : *Relocations) {
407         auto Type = Rela.getType(false);
408 
409         LLVM_DEBUG({
410           dbgs() << "Relocation Type: " << Type << "\n"
411                  << "Name: " << Obj.getRelocationTypeName(Type) << "\n";
412         });
413         auto SymbolIndex = Rela.getSymbol(false);
414         auto Symbol = Obj.getRelocationSymbol(Rela, &SymTab);
415         if (!Symbol)
416           return Symbol.takeError();
417 
418         auto BlockToFix = *(JITSection->blocks().begin());
419         auto *TargetSymbol = JITSymbolTable[SymbolIndex];
420 
421         if (!TargetSymbol) {
422           return make_error<llvm::StringError>(
423               "Could not find symbol at given index, did you add it to "
424               "JITSymbolTable? index: " +
425                   std::to_string((*Symbol)->st_shndx) +
426                   " Size of table: " + std::to_string(JITSymbolTable.size()),
427               llvm::inconvertibleErrorCode());
428         }
429         uint64_t Addend = Rela.r_addend;
430         JITTargetAddress FixupAddress =
431             (*UpdateSection)->sh_addr + Rela.r_offset;
432 
433         LLVM_DEBUG({
434           dbgs() << "Processing relocation at "
435                  << format("0x%016" PRIx64, FixupAddress) << "\n";
436         });
437         auto Kind = getRelocationKind(Type);
438         if (!Kind)
439           return Kind.takeError();
440 
441         LLVM_DEBUG({
442           Edge GE(*Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol,
443                   Addend);
444           printEdge(dbgs(), *BlockToFix, GE,
445                     getELFX86RelocationKindName(*Kind));
446           dbgs() << "\n";
447         });
448         BlockToFix->addEdge(*Kind, FixupAddress - BlockToFix->getAddress(),
449                             *TargetSymbol, Addend);
450       }
451     }
452     return Error::success();
453   }
454 
455   Error graphifyRegularSymbols() {
456 
457     // TODO: ELF supports beyond SHN_LORESERVE,
458     // need to perf test how a vector vs map handles those cases
459 
460     std::vector<std::vector<object::ELFFile<object::ELF64LE>::Elf_Shdr_Range *>>
461         SecIndexToSymbols;
462 
463     LLVM_DEBUG(dbgs() << "Creating graph symbols...\n");
464 
465     for (auto SecRef : sections) {
466 
467       if (SecRef.sh_type != ELF::SHT_SYMTAB &&
468           SecRef.sh_type != ELF::SHT_DYNSYM)
469         continue;
470       auto Symbols = Obj.symbols(&SecRef);
471       if (!Symbols)
472         return Symbols.takeError();
473 
474       auto StrTabSec = Obj.getSection(SecRef.sh_link);
475       if (!StrTabSec)
476         return StrTabSec.takeError();
477       auto StringTable = Obj.getStringTable(**StrTabSec);
478       if (!StringTable)
479         return StringTable.takeError();
480       auto Name = Obj.getSectionName(SecRef);
481       if (!Name)
482         return Name.takeError();
483       auto Section = G->findSectionByName(*Name);
484       if (!Section)
485         return make_error<llvm::StringError>("Could not find a section " +
486                                              *Name,
487                                              llvm::inconvertibleErrorCode());
488       // we only have one for now
489       auto blocks = Section->blocks();
490       if (blocks.empty())
491         return make_error<llvm::StringError>("Section has no block",
492                                              llvm::inconvertibleErrorCode());
493       int SymbolIndex = -1;
494       for (auto SymRef : *Symbols) {
495         ++SymbolIndex;
496         auto Type = SymRef.getType();
497 
498         if (Type == ELF::STT_FILE || SymbolIndex == 0)
499           continue;
500         // these should do it for now
501         // if(Type != ELF::STT_NOTYPE &&
502         //   Type != ELF::STT_OBJECT &&
503         //   Type != ELF::STT_FUNC    &&
504         //   Type != ELF::STT_SECTION &&
505         //   Type != ELF::STT_COMMON) {
506         //     continue;
507         //   }
508         std::pair<Linkage, Scope> bindings;
509         auto Name = SymRef.getName(*StringTable);
510         // I am not sure on If this is going to hold as an invariant. Revisit.
511         if (!Name)
512           return Name.takeError();
513 
514         if (SymRef.isCommon()) {
515           // Symbols in SHN_COMMON refer to uninitialized data. The st_value
516           // field holds alignment constraints.
517           Symbol &S =
518               G->addCommonSymbol(*Name, Scope::Default, getCommonSection(), 0,
519                                  SymRef.st_size, SymRef.getValue(), false);
520           JITSymbolTable[SymbolIndex] = &S;
521           continue;
522         }
523 
524         // TODO: weak and hidden
525         if (SymRef.isExternal())
526           bindings = {Linkage::Strong, Scope::Default};
527         else
528           bindings = {Linkage::Strong, Scope::Local};
529 
530         if (SymRef.isDefined() &&
531             (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT ||
532              Type == ELF::STT_SECTION)) {
533 
534           auto DefinedSection = Obj.getSection(SymRef.st_shndx);
535           if (!DefinedSection)
536             return DefinedSection.takeError();
537           auto sectName = Obj.getSectionName(**DefinedSection);
538           if (!sectName)
539             return Name.takeError();
540 
541           auto JitSection = G->findSectionByName(*sectName);
542           if (!JitSection)
543             return make_error<llvm::StringError>(
544                 "Could not find the JitSection " + *sectName,
545                 llvm::inconvertibleErrorCode());
546           auto bs = JitSection->blocks();
547           if (bs.empty())
548             return make_error<llvm::StringError>(
549                 "Section has no block", llvm::inconvertibleErrorCode());
550 
551           auto B = *bs.begin();
552           LLVM_DEBUG({ dbgs() << "  " << *Name << ": "; });
553           if (SymRef.getType() == ELF::STT_SECTION)
554             *Name = *sectName;
555           auto &S = G->addDefinedSymbol(
556               *B, SymRef.getValue(), *Name, SymRef.st_size, bindings.first,
557               bindings.second, SymRef.getType() == ELF::STT_FUNC, false);
558           JITSymbolTable[SymbolIndex] = &S;
559         } else if (SymRef.isUndefined() && SymRef.isExternal()) {
560           auto &S = G->addExternalSymbol(*Name, SymRef.st_size, bindings.first);
561           JITSymbolTable[SymbolIndex] = &S;
562         }
563 
564         // TODO: The following has to be implmented.
565         // leaving commented out to save time for future patchs
566         /*
567           G->addAbsoluteSymbol(*Name, SymRef.getValue(), SymRef.st_size,
568           Linkage::Strong, Scope::Default, false);
569         */
570       }
571     }
572     return Error::success();
573   }
574 
575 public:
576   ELFLinkGraphBuilder_x86_64(std::string filename,
577                              const object::ELFFile<object::ELF64LE> &Obj)
578       : G(std::make_unique<LinkGraph>(filename, getPointerSize(Obj),
579                                       getEndianness(Obj))),
580         Obj(Obj) {}
581 
582   Expected<std::unique_ptr<LinkGraph>> buildGraph() {
583     // Sanity check: we only operate on relocatable objects.
584     if (!isRelocatable())
585       return make_error<JITLinkError>("Object is not a relocatable ELF");
586 
587     auto Secs = Obj.sections();
588 
589     if (!Secs) {
590       return Secs.takeError();
591     }
592     sections = *Secs;
593 
594     if (auto Err = createNormalizedSections())
595       return std::move(Err);
596 
597     if (auto Err = createNormalizedSymbols())
598       return std::move(Err);
599 
600     if (auto Err = graphifyRegularSymbols())
601       return std::move(Err);
602 
603     if (auto Err = addRelocations())
604       return std::move(Err);
605 
606     return std::move(G);
607   }
608 };
609 
610 class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
611   friend class JITLinker<ELFJITLinker_x86_64>;
612 
613 public:
614   ELFJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
615                       PassConfiguration PassConfig)
616       : JITLinker(std::move(Ctx), std::move(PassConfig)) {}
617 
618 private:
619   StringRef getEdgeKindName(Edge::Kind R) const override {
620     return getELFX86RelocationKindName(R);
621   }
622 
623   Expected<std::unique_ptr<LinkGraph>>
624   buildGraph(MemoryBufferRef ObjBuffer) override {
625     auto ELFObj = object::ObjectFile::createELFObjectFile(ObjBuffer);
626     if (!ELFObj)
627       return ELFObj.takeError();
628 
629     auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
630     std::string fileName(ELFObj->get()->getFileName());
631     return ELFLinkGraphBuilder_x86_64(std::move(fileName),
632                                       *ELFObjFile.getELFFile())
633         .buildGraph();
634   }
635 
636   Error applyFixup(Block &B, const Edge &E, char *BlockWorkingMem) const {
637     using namespace ELF_x86_64_Edges;
638     using namespace llvm::support;
639     char *FixupPtr = BlockWorkingMem + E.getOffset();
640     JITTargetAddress FixupAddress = B.getAddress() + E.getOffset();
641     switch (E.getKind()) {
642     case ELFX86RelocationKind::PCRel32:
643     case ELFX86RelocationKind::PCRel32GOTLoad: {
644       int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
645       endian::write32le(FixupPtr, Value);
646       break;
647     }
648     case ELFX86RelocationKind::Pointer64: {
649       int64_t Value = E.getTarget().getAddress() + E.getAddend();
650       endian::write64le(FixupPtr, Value);
651       break;
652     }
653     }
654     return Error::success();
655   }
656 };
657 
658 void jitLink_ELF_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
659   PassConfiguration Config;
660   Triple TT("x86_64-linux");
661   // Construct a JITLinker and run the link function.
662   // Add a mark-live pass.
663   if (auto MarkLive = Ctx->getMarkLivePass(TT))
664     Config.PrePrunePasses.push_back(std::move(MarkLive));
665   else
666     Config.PrePrunePasses.push_back(markAllSymbolsLive);
667 
668   // Add an in-place GOT/Stubs pass.
669   Config.PostPrunePasses.push_back([](LinkGraph &G) -> Error {
670     ELF_x86_64_GOTAndStubsBuilder(G).run();
671     return Error::success();
672   });
673 
674   // Add GOT/Stubs optimizer pass.
675   Config.PostAllocationPasses.push_back(optimizeELF_x86_64_GOTAndStubs);
676 
677   if (auto Err = Ctx->modifyPassConfig(TT, Config))
678     return Ctx->notifyFailed(std::move(Err));
679 
680   ELFJITLinker_x86_64::link(std::move(Ctx), std::move(Config));
681 }
682 StringRef getELFX86RelocationKindName(Edge::Kind R) {
683   switch (R) {
684   case PCRel32:
685     return "PCRel32";
686   case Pointer64:
687     return "Pointer64";
688   case PCRel32GOTLoad:
689     return "PCRel32GOTLoad";
690   }
691   return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
692 }
693 } // end namespace jitlink
694 } // end namespace llvm
695