xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===------- ELFLinkGraphBuilder.h - ELF LinkGraph builder ------*- C++ -*-===//
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 // Generic ELF LinkGraph building code.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
14 #define LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
15 
16 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
17 #include "llvm/Object/ELF.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/Error.h"
20 #include "llvm/Support/FormatVariadic.h"
21 
22 #define DEBUG_TYPE "jitlink"
23 
24 namespace llvm {
25 namespace jitlink {
26 
27 /// Common link-graph building code shared between all ELFFiles.
28 class ELFLinkGraphBuilderBase {
29 public:
ELFLinkGraphBuilderBase(std::unique_ptr<LinkGraph> G)30   ELFLinkGraphBuilderBase(std::unique_ptr<LinkGraph> G) : G(std::move(G)) {}
31   virtual ~ELFLinkGraphBuilderBase();
32 
33 protected:
isDwarfSection(StringRef SectionName)34   static bool isDwarfSection(StringRef SectionName) {
35     return llvm::is_contained(DwarfSectionNames, SectionName);
36   }
37 
getCommonSection()38   Section &getCommonSection() {
39     if (!CommonSection)
40       CommonSection = &G->createSection(
41           CommonSectionName, orc::MemProt::Read | orc::MemProt::Write);
42     return *CommonSection;
43   }
44 
45   std::unique_ptr<LinkGraph> G;
46 
47 private:
48   static StringRef CommonSectionName;
49   static ArrayRef<const char *> DwarfSectionNames;
50 
51   Section *CommonSection = nullptr;
52 };
53 
54 /// LinkGraph building code that's specific to the given ELFT, but common
55 /// across all architectures.
56 template <typename ELFT>
57 class ELFLinkGraphBuilder : public ELFLinkGraphBuilderBase {
58   using ELFFile = object::ELFFile<ELFT>;
59 
60 public:
61   ELFLinkGraphBuilder(const object::ELFFile<ELFT> &Obj, Triple TT,
62                       SubtargetFeatures Features, StringRef FileName,
63                       LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
64 
65   /// Debug sections are included in the graph by default. Use
66   /// setProcessDebugSections(false) to ignore them if debug info is not
67   /// needed.
setProcessDebugSections(bool ProcessDebugSections)68   ELFLinkGraphBuilder &setProcessDebugSections(bool ProcessDebugSections) {
69     this->ProcessDebugSections = ProcessDebugSections;
70     return *this;
71   }
72 
73   /// Attempt to construct and return the LinkGraph.
74   Expected<std::unique_ptr<LinkGraph>> buildGraph();
75 
76   /// Call to derived class to handle relocations. These require
77   /// architecture specific knowledge to map to JITLink edge kinds.
78   virtual Error addRelocations() = 0;
79 
80 protected:
81   using ELFSectionIndex = unsigned;
82   using ELFSymbolIndex = unsigned;
83 
isRelocatable()84   bool isRelocatable() const {
85     return Obj.getHeader().e_type == llvm::ELF::ET_REL;
86   }
87 
setGraphBlock(ELFSectionIndex SecIndex,Block * B)88   void setGraphBlock(ELFSectionIndex SecIndex, Block *B) {
89     assert(!GraphBlocks.count(SecIndex) && "Duplicate section at index");
90     GraphBlocks[SecIndex] = B;
91   }
92 
getGraphBlock(ELFSectionIndex SecIndex)93   Block *getGraphBlock(ELFSectionIndex SecIndex) {
94     return GraphBlocks.lookup(SecIndex);
95   }
96 
setGraphSymbol(ELFSymbolIndex SymIndex,Symbol & Sym)97   void setGraphSymbol(ELFSymbolIndex SymIndex, Symbol &Sym) {
98     assert(!GraphSymbols.count(SymIndex) && "Duplicate symbol at index");
99     GraphSymbols[SymIndex] = &Sym;
100   }
101 
getGraphSymbol(ELFSymbolIndex SymIndex)102   Symbol *getGraphSymbol(ELFSymbolIndex SymIndex) {
103     return GraphSymbols.lookup(SymIndex);
104   }
105 
106   Expected<std::pair<Linkage, Scope>>
107   getSymbolLinkageAndScope(const typename ELFT::Sym &Sym, StringRef Name);
108 
109   /// Set the target flags on the given Symbol.
makeTargetFlags(const typename ELFT::Sym & Sym)110   virtual TargetFlagsType makeTargetFlags(const typename ELFT::Sym &Sym) {
111     return TargetFlagsType{};
112   }
113 
114   /// Get the physical offset of the symbol on the target platform.
getRawOffset(const typename ELFT::Sym & Sym,TargetFlagsType Flags)115   virtual orc::ExecutorAddrDiff getRawOffset(const typename ELFT::Sym &Sym,
116                                              TargetFlagsType Flags) {
117     return Sym.getValue();
118   }
119 
120   Error prepare();
121   Error graphifySections();
122   Error graphifySymbols();
123 
124   /// Override in derived classes to suppress certain sections in the link
125   /// graph.
excludeSection(const typename ELFT::Shdr & Sect)126   virtual bool excludeSection(const typename ELFT::Shdr &Sect) const {
127     return false;
128   }
129 
130   /// Traverse all matching ELFT::Rela relocation records in the given section.
131   /// The handler function Func should be callable with this signature:
132   ///   Error(const typename ELFT::Rela &,
133   ///         const typename ELFT::Shdr &, Section &)
134   ///
135   template <typename RelocHandlerMethod>
136   Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,
137                               RelocHandlerMethod &&Func);
138 
139   /// Traverse all matching ELFT::Rel relocation records in the given section.
140   /// The handler function Func should be callable with this signature:
141   ///   Error(const typename ELFT::Rel &,
142   ///         const typename ELFT::Shdr &, Section &)
143   ///
144   template <typename RelocHandlerMethod>
145   Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,
146                              RelocHandlerMethod &&Func);
147 
148   /// Traverse all matching rela relocation records in the given section.
149   /// Convenience wrapper to allow passing a member function for the handler.
150   ///
151   template <typename ClassT, typename RelocHandlerMethod>
forEachRelaRelocation(const typename ELFT::Shdr & RelSect,ClassT * Instance,RelocHandlerMethod && Method)152   Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,
153                               ClassT *Instance, RelocHandlerMethod &&Method) {
154     return forEachRelaRelocation(
155         RelSect,
156         [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
157           return (Instance->*Method)(Rel, Target, GS);
158         });
159   }
160 
161   /// Traverse all matching rel relocation records in the given section.
162   /// Convenience wrapper to allow passing a member function for the handler.
163   ///
164   template <typename ClassT, typename RelocHandlerMethod>
forEachRelRelocation(const typename ELFT::Shdr & RelSect,ClassT * Instance,RelocHandlerMethod && Method)165   Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,
166                              ClassT *Instance, RelocHandlerMethod &&Method) {
167     return forEachRelRelocation(
168         RelSect,
169         [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
170           return (Instance->*Method)(Rel, Target, GS);
171         });
172   }
173 
174   const ELFFile &Obj;
175 
176   typename ELFFile::Elf_Shdr_Range Sections;
177   const typename ELFFile::Elf_Shdr *SymTabSec = nullptr;
178   StringRef SectionStringTab;
179   bool ProcessDebugSections = true;
180 
181   // Maps ELF section indexes to LinkGraph Blocks.
182   // Only SHF_ALLOC sections will have graph blocks.
183   DenseMap<ELFSectionIndex, Block *> GraphBlocks;
184   DenseMap<ELFSymbolIndex, Symbol *> GraphSymbols;
185   DenseMap<const typename ELFFile::Elf_Shdr *,
186            ArrayRef<typename ELFFile::Elf_Word>>
187       ShndxTables;
188 };
189 
190 template <typename ELFT>
ELFLinkGraphBuilder(const ELFFile & Obj,Triple TT,SubtargetFeatures Features,StringRef FileName,LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)191 ELFLinkGraphBuilder<ELFT>::ELFLinkGraphBuilder(
192     const ELFFile &Obj, Triple TT, SubtargetFeatures Features,
193     StringRef FileName, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
194     : ELFLinkGraphBuilderBase(std::make_unique<LinkGraph>(
195           FileName.str(), Triple(std::move(TT)), std::move(Features),
196           ELFT::Is64Bits ? 8 : 4, llvm::endianness(ELFT::Endianness),
197           std::move(GetEdgeKindName))),
198       Obj(Obj) {
199   LLVM_DEBUG(
200       { dbgs() << "Created ELFLinkGraphBuilder for \"" << FileName << "\""; });
201 }
202 
203 template <typename ELFT>
buildGraph()204 Expected<std::unique_ptr<LinkGraph>> ELFLinkGraphBuilder<ELFT>::buildGraph() {
205   if (!isRelocatable())
206     return make_error<JITLinkError>("Object is not a relocatable ELF file");
207 
208   if (auto Err = prepare())
209     return std::move(Err);
210 
211   if (auto Err = graphifySections())
212     return std::move(Err);
213 
214   if (auto Err = graphifySymbols())
215     return std::move(Err);
216 
217   if (auto Err = addRelocations())
218     return std::move(Err);
219 
220   return std::move(G);
221 }
222 
223 template <typename ELFT>
224 Expected<std::pair<Linkage, Scope>>
getSymbolLinkageAndScope(const typename ELFT::Sym & Sym,StringRef Name)225 ELFLinkGraphBuilder<ELFT>::getSymbolLinkageAndScope(
226     const typename ELFT::Sym &Sym, StringRef Name) {
227   Linkage L = Linkage::Strong;
228   Scope S = Scope::Default;
229 
230   switch (Sym.getBinding()) {
231   case ELF::STB_LOCAL:
232     S = Scope::Local;
233     break;
234   case ELF::STB_GLOBAL:
235     // Nothing to do here.
236     break;
237   case ELF::STB_WEAK:
238   case ELF::STB_GNU_UNIQUE:
239     L = Linkage::Weak;
240     break;
241   default:
242     return make_error<StringError>(
243         "Unrecognized symbol binding " +
244             Twine(static_cast<int>(Sym.getBinding())) + " for " + Name,
245         inconvertibleErrorCode());
246   }
247 
248   switch (Sym.getVisibility()) {
249   case ELF::STV_DEFAULT:
250   case ELF::STV_PROTECTED:
251     // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs
252     // Orc support.
253     // Otherwise nothing to do here.
254     break;
255   case ELF::STV_HIDDEN:
256     // Default scope -> Hidden scope. No effect on local scope.
257     if (S == Scope::Default)
258       S = Scope::Hidden;
259     break;
260   case ELF::STV_INTERNAL:
261     return make_error<StringError>(
262         "Unrecognized symbol visibility " +
263             Twine(static_cast<int>(Sym.getVisibility())) + " for " + Name,
264         inconvertibleErrorCode());
265   }
266 
267   return std::make_pair(L, S);
268 }
269 
prepare()270 template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::prepare() {
271   LLVM_DEBUG(dbgs() << "  Preparing to build...\n");
272 
273   // Get the sections array.
274   if (auto SectionsOrErr = Obj.sections())
275     Sections = *SectionsOrErr;
276   else
277     return SectionsOrErr.takeError();
278 
279   // Get the section string table.
280   if (auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))
281     SectionStringTab = *SectionStringTabOrErr;
282   else
283     return SectionStringTabOrErr.takeError();
284 
285   // Get the SHT_SYMTAB section.
286   for (auto &Sec : Sections) {
287     if (Sec.sh_type == ELF::SHT_SYMTAB) {
288       if (!SymTabSec)
289         SymTabSec = &Sec;
290       else
291         return make_error<JITLinkError>("Multiple SHT_SYMTAB sections in " +
292                                         G->getName());
293     }
294 
295     // Extended table.
296     if (Sec.sh_type == ELF::SHT_SYMTAB_SHNDX) {
297       uint32_t SymtabNdx = Sec.sh_link;
298       if (SymtabNdx >= Sections.size())
299         return make_error<JITLinkError>("sh_link is out of bound");
300 
301       auto ShndxTable = Obj.getSHNDXTable(Sec);
302       if (!ShndxTable)
303         return ShndxTable.takeError();
304 
305       ShndxTables.insert({&Sections[SymtabNdx], *ShndxTable});
306     }
307   }
308 
309   return Error::success();
310 }
311 
graphifySections()312 template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() {
313   LLVM_DEBUG(dbgs() << "  Creating graph sections...\n");
314 
315   // For each section...
316   for (ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {
317 
318     auto &Sec = Sections[SecIndex];
319 
320     // Start by getting the section name.
321     auto Name = Obj.getSectionName(Sec, SectionStringTab);
322     if (!Name)
323       return Name.takeError();
324     if (excludeSection(Sec)) {
325       LLVM_DEBUG({
326         dbgs() << "    " << SecIndex << ": Skipping section \"" << *Name
327                << "\" explicitly\n";
328       });
329       continue;
330     }
331 
332     // Skip null sections.
333     if (Sec.sh_type == ELF::SHT_NULL) {
334       LLVM_DEBUG({
335         dbgs() << "    " << SecIndex << ": has type SHT_NULL. Skipping.\n";
336       });
337       continue;
338     }
339 
340     // If the name indicates that it's a debug section then skip it: We don't
341     // support those yet.
342     if (!ProcessDebugSections && isDwarfSection(*Name)) {
343       LLVM_DEBUG({
344         dbgs() << "    " << SecIndex << ": \"" << *Name
345                << "\" is a debug section: "
346                   "No graph section will be created.\n";
347       });
348       continue;
349     }
350 
351     LLVM_DEBUG({
352       dbgs() << "    " << SecIndex << ": Creating section for \"" << *Name
353              << "\"\n";
354     });
355 
356     // Get the section's memory protection flags.
357     orc::MemProt Prot = orc::MemProt::Read;
358     if (Sec.sh_flags & ELF::SHF_EXECINSTR)
359       Prot |= orc::MemProt::Exec;
360     if (Sec.sh_flags & ELF::SHF_WRITE)
361       Prot |= orc::MemProt::Write;
362 
363     // Look for existing sections first.
364     auto *GraphSec = G->findSectionByName(*Name);
365     if (!GraphSec) {
366       GraphSec = &G->createSection(*Name, Prot);
367       // Non-SHF_ALLOC sections get NoAlloc memory lifetimes.
368       if (!(Sec.sh_flags & ELF::SHF_ALLOC)) {
369         GraphSec->setMemLifetime(orc::MemLifetime::NoAlloc);
370         LLVM_DEBUG({
371           dbgs() << "      " << SecIndex << ": \"" << *Name
372                  << "\" is not a SHF_ALLOC section. Using NoAlloc lifetime.\n";
373         });
374       }
375     }
376 
377     if (GraphSec->getMemProt() != Prot) {
378       std::string ErrMsg;
379       raw_string_ostream(ErrMsg)
380           << "In " << G->getName() << ", section " << *Name
381           << " is present more than once with different permissions: "
382           << GraphSec->getMemProt() << " vs " << Prot;
383       return make_error<JITLinkError>(std::move(ErrMsg));
384     }
385 
386     Block *B = nullptr;
387     if (Sec.sh_type != ELF::SHT_NOBITS) {
388       auto Data = Obj.template getSectionContentsAsArray<char>(Sec);
389       if (!Data)
390         return Data.takeError();
391 
392       B = &G->createContentBlock(*GraphSec, *Data,
393                                  orc::ExecutorAddr(Sec.sh_addr),
394                                  Sec.sh_addralign, 0);
395     } else
396       B = &G->createZeroFillBlock(*GraphSec, Sec.sh_size,
397                                   orc::ExecutorAddr(Sec.sh_addr),
398                                   Sec.sh_addralign, 0);
399 
400     if (Sec.sh_type == ELF::SHT_ARM_EXIDX) {
401       // Add live symbol to avoid dead-stripping for .ARM.exidx sections
402       G->addAnonymousSymbol(*B, orc::ExecutorAddrDiff(),
403                             orc::ExecutorAddrDiff(), false, true);
404     }
405 
406     setGraphBlock(SecIndex, B);
407   }
408 
409   return Error::success();
410 }
411 
graphifySymbols()412 template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
413   LLVM_DEBUG(dbgs() << "  Creating graph symbols...\n");
414 
415   // No SYMTAB -- Bail out early.
416   if (!SymTabSec)
417     return Error::success();
418 
419   // Get the section content as a Symbols array.
420   auto Symbols = Obj.symbols(SymTabSec);
421   if (!Symbols)
422     return Symbols.takeError();
423 
424   // Get the string table for this section.
425   auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
426   if (!StringTab)
427     return StringTab.takeError();
428 
429   LLVM_DEBUG({
430     StringRef SymTabName;
431 
432     if (auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
433       SymTabName = *SymTabNameOrErr;
434     else {
435       dbgs() << "Could not get ELF SHT_SYMTAB section name for logging: "
436              << toString(SymTabNameOrErr.takeError()) << "\n";
437       SymTabName = "<SHT_SYMTAB section with invalid name>";
438     }
439 
440     dbgs() << "    Adding symbols from symtab section \"" << SymTabName
441            << "\"\n";
442   });
443 
444   for (ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
445     auto &Sym = (*Symbols)[SymIndex];
446 
447     // Check symbol type.
448     switch (Sym.getType()) {
449     case ELF::STT_FILE:
450       LLVM_DEBUG({
451         if (auto Name = Sym.getName(*StringTab))
452           dbgs() << "      " << SymIndex << ": Skipping STT_FILE symbol \""
453                  << *Name << "\"\n";
454         else {
455           dbgs() << "Could not get STT_FILE symbol name: "
456                  << toString(Name.takeError()) << "\n";
457           dbgs() << "     " << SymIndex
458                  << ": Skipping STT_FILE symbol with invalid name\n";
459         }
460       });
461       continue;
462       break;
463     }
464 
465     // Get the symbol name.
466     auto Name = Sym.getName(*StringTab);
467     if (!Name)
468       return Name.takeError();
469 
470     // Handle common symbols specially.
471     if (Sym.isCommon()) {
472       Symbol &GSym = G->addDefinedSymbol(
473           G->createZeroFillBlock(getCommonSection(), Sym.st_size,
474                                  orc::ExecutorAddr(), Sym.getValue(), 0),
475           0, *Name, Sym.st_size, Linkage::Strong, Scope::Default, false, false);
476       setGraphSymbol(SymIndex, GSym);
477       continue;
478     }
479 
480     if (Sym.isDefined() &&
481         (Sym.getType() == ELF::STT_NOTYPE || Sym.getType() == ELF::STT_FUNC ||
482          Sym.getType() == ELF::STT_OBJECT ||
483          Sym.getType() == ELF::STT_SECTION || Sym.getType() == ELF::STT_TLS)) {
484 
485       // Map Visibility and Binding to Scope and Linkage:
486       Linkage L;
487       Scope S;
488       if (auto LSOrErr = getSymbolLinkageAndScope(Sym, *Name))
489         std::tie(L, S) = *LSOrErr;
490       else
491         return LSOrErr.takeError();
492 
493       // Handle extended tables.
494       unsigned Shndx = Sym.st_shndx;
495       if (Shndx == ELF::SHN_XINDEX) {
496         auto ShndxTable = ShndxTables.find(SymTabSec);
497         if (ShndxTable == ShndxTables.end())
498           continue;
499         auto NdxOrErr = object::getExtendedSymbolTableIndex<ELFT>(
500             Sym, SymIndex, ShndxTable->second);
501         if (!NdxOrErr)
502           return NdxOrErr.takeError();
503         Shndx = *NdxOrErr;
504       }
505       if (auto *B = getGraphBlock(Shndx)) {
506         LLVM_DEBUG({
507           dbgs() << "      " << SymIndex
508                  << ": Creating defined graph symbol for ELF symbol \"" << *Name
509                  << "\"\n";
510         });
511 
512         TargetFlagsType Flags = makeTargetFlags(Sym);
513         orc::ExecutorAddrDiff Offset = getRawOffset(Sym, Flags);
514 
515         if (Offset + Sym.st_size > B->getSize()) {
516           std::string ErrMsg;
517           raw_string_ostream ErrStream(ErrMsg);
518           ErrStream << "In " << G->getName() << ", symbol ";
519           if (!Name->empty())
520             ErrStream << *Name;
521           else
522             ErrStream << "<anon>";
523           ErrStream << " (" << (B->getAddress() + Offset) << " -- "
524                     << (B->getAddress() + Offset + Sym.st_size) << ") extends "
525                     << formatv("{0:x}", Offset + Sym.st_size - B->getSize())
526                     << " bytes past the end of its containing block ("
527                     << B->getRange() << ")";
528           return make_error<JITLinkError>(std::move(ErrMsg));
529         }
530 
531         // In RISCV, temporary symbols (Used to generate dwarf, eh_frame
532         // sections...) will appear in object code's symbol table, and LLVM does
533         // not use names on these temporary symbols (RISCV gnu toolchain uses
534         // names on these temporary symbols). If the symbol is unnamed, add an
535         // anonymous symbol.
536         auto &GSym =
537             Name->empty()
538                 ? G->addAnonymousSymbol(*B, Offset, Sym.st_size,
539                                         false, false)
540                 : G->addDefinedSymbol(*B, Offset, *Name, Sym.st_size, L,
541                                       S, Sym.getType() == ELF::STT_FUNC,
542                                       false);
543 
544         GSym.setTargetFlags(Flags);
545         setGraphSymbol(SymIndex, GSym);
546       }
547     } else if (Sym.isUndefined() && Sym.isExternal()) {
548       LLVM_DEBUG({
549         dbgs() << "      " << SymIndex
550                << ": Creating external graph symbol for ELF symbol \"" << *Name
551                << "\"\n";
552       });
553 
554       if (Sym.getBinding() != ELF::STB_GLOBAL &&
555           Sym.getBinding() != ELF::STB_WEAK)
556         return make_error<StringError>(
557             "Invalid symbol binding " +
558                 Twine(static_cast<int>(Sym.getBinding())) +
559                 " for external symbol " + *Name,
560             inconvertibleErrorCode());
561 
562       // If L is Linkage::Weak that means this is a weakly referenced symbol.
563       auto &GSym = G->addExternalSymbol(*Name, Sym.st_size,
564                                         Sym.getBinding() == ELF::STB_WEAK);
565       setGraphSymbol(SymIndex, GSym);
566     } else if (Sym.isUndefined() && Sym.st_value == 0 && Sym.st_size == 0 &&
567                Sym.getType() == ELF::STT_NOTYPE &&
568                Sym.getBinding() == ELF::STB_LOCAL && Name->empty()) {
569       // Some relocations (e.g., R_RISCV_ALIGN) don't have a target symbol and
570       // use this kind of null symbol as a placeholder.
571       LLVM_DEBUG({
572         dbgs() << "      " << SymIndex << ": Creating null graph symbol\n";
573       });
574 
575       auto SymName =
576           G->allocateContent("__jitlink_ELF_SYM_UND_" + Twine(SymIndex));
577       auto SymNameRef = StringRef(SymName.data(), SymName.size());
578       auto &GSym = G->addAbsoluteSymbol(SymNameRef, orc::ExecutorAddr(0), 0,
579                                         Linkage::Strong, Scope::Local, false);
580       setGraphSymbol(SymIndex, GSym);
581     } else {
582       LLVM_DEBUG({
583         dbgs() << "      " << SymIndex
584                << ": Not creating graph symbol for ELF symbol \"" << *Name
585                << "\" with unrecognized type\n";
586       });
587     }
588   }
589 
590   return Error::success();
591 }
592 
593 template <typename ELFT>
594 template <typename RelocHandlerFunction>
forEachRelaRelocation(const typename ELFT::Shdr & RelSect,RelocHandlerFunction && Func)595 Error ELFLinkGraphBuilder<ELFT>::forEachRelaRelocation(
596     const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
597   // Only look into sections that store relocation entries.
598   if (RelSect.sh_type != ELF::SHT_RELA)
599     return Error::success();
600 
601   // sh_info contains the section header index of the target (FixupSection),
602   // which is the section to which all relocations in RelSect apply.
603   auto FixupSection = Obj.getSection(RelSect.sh_info);
604   if (!FixupSection)
605     return FixupSection.takeError();
606 
607   // Target sections have names in valid ELF object files.
608   Expected<StringRef> Name = Obj.getSectionName(**FixupSection);
609   if (!Name)
610     return Name.takeError();
611   LLVM_DEBUG(dbgs() << "  " << *Name << ":\n");
612 
613   // Consider skipping these relocations.
614   if (!ProcessDebugSections && isDwarfSection(*Name)) {
615     LLVM_DEBUG(dbgs() << "    skipped (dwarf section)\n\n");
616     return Error::success();
617   }
618   if (excludeSection(**FixupSection)) {
619     LLVM_DEBUG(dbgs() << "    skipped (fixup section excluded explicitly)\n\n");
620     return Error::success();
621   }
622 
623   // Lookup the link-graph node corresponding to the target section name.
624   auto *BlockToFix = getGraphBlock(RelSect.sh_info);
625   if (!BlockToFix)
626     return make_error<StringError>(
627         "Refencing a section that wasn't added to the graph: " + *Name,
628         inconvertibleErrorCode());
629 
630   auto RelEntries = Obj.relas(RelSect);
631   if (!RelEntries)
632     return RelEntries.takeError();
633 
634   // Let the callee process relocation entries one by one.
635   for (const typename ELFT::Rela &R : *RelEntries)
636     if (Error Err = Func(R, **FixupSection, *BlockToFix))
637       return Err;
638 
639   LLVM_DEBUG(dbgs() << "\n");
640   return Error::success();
641 }
642 
643 template <typename ELFT>
644 template <typename RelocHandlerFunction>
forEachRelRelocation(const typename ELFT::Shdr & RelSect,RelocHandlerFunction && Func)645 Error ELFLinkGraphBuilder<ELFT>::forEachRelRelocation(
646     const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
647   // Only look into sections that store relocation entries.
648   if (RelSect.sh_type != ELF::SHT_REL)
649     return Error::success();
650 
651   // sh_info contains the section header index of the target (FixupSection),
652   // which is the section to which all relocations in RelSect apply.
653   auto FixupSection = Obj.getSection(RelSect.sh_info);
654   if (!FixupSection)
655     return FixupSection.takeError();
656 
657   // Target sections have names in valid ELF object files.
658   Expected<StringRef> Name = Obj.getSectionName(**FixupSection);
659   if (!Name)
660     return Name.takeError();
661   LLVM_DEBUG(dbgs() << "  " << *Name << ":\n");
662 
663   // Consider skipping these relocations.
664   if (!ProcessDebugSections && isDwarfSection(*Name)) {
665     LLVM_DEBUG(dbgs() << "    skipped (dwarf section)\n\n");
666     return Error::success();
667   }
668   if (excludeSection(**FixupSection)) {
669     LLVM_DEBUG(dbgs() << "    skipped (fixup section excluded explicitly)\n\n");
670     return Error::success();
671   }
672 
673   // Lookup the link-graph node corresponding to the target section name.
674   auto *BlockToFix = getGraphBlock(RelSect.sh_info);
675   if (!BlockToFix)
676     return make_error<StringError>(
677         "Refencing a section that wasn't added to the graph: " + *Name,
678         inconvertibleErrorCode());
679 
680   auto RelEntries = Obj.rels(RelSect);
681   if (!RelEntries)
682     return RelEntries.takeError();
683 
684   // Let the callee process relocation entries one by one.
685   for (const typename ELFT::Rel &R : *RelEntries)
686     if (Error Err = Func(R, **FixupSection, *BlockToFix))
687       return Err;
688 
689   LLVM_DEBUG(dbgs() << "\n");
690   return Error::success();
691 }
692 
693 } // end namespace jitlink
694 } // end namespace llvm
695 
696 #undef DEBUG_TYPE
697 
698 #endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
699