xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1fe6060f1SDimitry Andric //===------- ELFLinkGraphBuilder.h - ELF LinkGraph builder ------*- C++ -*-===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric //
9fe6060f1SDimitry Andric // Generic ELF LinkGraph building code.
10fe6060f1SDimitry Andric //
11fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
12fe6060f1SDimitry Andric 
13fe6060f1SDimitry Andric #ifndef LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
14fe6060f1SDimitry Andric #define LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
15fe6060f1SDimitry Andric 
16fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLink.h"
17fe6060f1SDimitry Andric #include "llvm/Object/ELF.h"
18fe6060f1SDimitry Andric #include "llvm/Support/Debug.h"
19fe6060f1SDimitry Andric #include "llvm/Support/Error.h"
20fe6060f1SDimitry Andric #include "llvm/Support/FormatVariadic.h"
21fe6060f1SDimitry Andric 
22fe6060f1SDimitry Andric #define DEBUG_TYPE "jitlink"
23fe6060f1SDimitry Andric 
24fe6060f1SDimitry Andric namespace llvm {
25fe6060f1SDimitry Andric namespace jitlink {
26fe6060f1SDimitry Andric 
27fe6060f1SDimitry Andric /// Common link-graph building code shared between all ELFFiles.
28fe6060f1SDimitry Andric class ELFLinkGraphBuilderBase {
29fe6060f1SDimitry Andric public:
30fe6060f1SDimitry Andric   ELFLinkGraphBuilderBase(std::unique_ptr<LinkGraph> G) : G(std::move(G)) {}
31fe6060f1SDimitry Andric   virtual ~ELFLinkGraphBuilderBase();
32fe6060f1SDimitry Andric 
33fe6060f1SDimitry Andric protected:
34fe6060f1SDimitry Andric   static bool isDwarfSection(StringRef SectionName) {
35fe6060f1SDimitry Andric     return llvm::is_contained(DwarfSectionNames, SectionName);
36fe6060f1SDimitry Andric   }
37fe6060f1SDimitry Andric 
38fe6060f1SDimitry Andric   Section &getCommonSection() {
39349cc55cSDimitry Andric     if (!CommonSection)
40bdd1243dSDimitry Andric       CommonSection = &G->createSection(
41bdd1243dSDimitry Andric           CommonSectionName, orc::MemProt::Read | orc::MemProt::Write);
42fe6060f1SDimitry Andric     return *CommonSection;
43fe6060f1SDimitry Andric   }
44fe6060f1SDimitry Andric 
45fe6060f1SDimitry Andric   std::unique_ptr<LinkGraph> G;
46fe6060f1SDimitry Andric 
47fe6060f1SDimitry Andric private:
48fe6060f1SDimitry Andric   static StringRef CommonSectionName;
49fe6060f1SDimitry Andric   static ArrayRef<const char *> DwarfSectionNames;
50fe6060f1SDimitry Andric 
51fe6060f1SDimitry Andric   Section *CommonSection = nullptr;
52fe6060f1SDimitry Andric };
53fe6060f1SDimitry Andric 
54fe6060f1SDimitry Andric /// Ling-graph building code that's specific to the given ELFT, but common
55fe6060f1SDimitry Andric /// across all architectures.
56fe6060f1SDimitry Andric template <typename ELFT>
57fe6060f1SDimitry Andric class ELFLinkGraphBuilder : public ELFLinkGraphBuilderBase {
58fe6060f1SDimitry Andric   using ELFFile = object::ELFFile<ELFT>;
59fe6060f1SDimitry Andric 
60fe6060f1SDimitry Andric public:
61fe6060f1SDimitry Andric   ELFLinkGraphBuilder(const object::ELFFile<ELFT> &Obj, Triple TT,
62*06c3fb27SDimitry Andric                       SubtargetFeatures Features, StringRef FileName,
63fe6060f1SDimitry Andric                       LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
64fe6060f1SDimitry Andric 
65*06c3fb27SDimitry Andric   /// Debug sections are included in the graph by default. Use
66*06c3fb27SDimitry Andric   /// setProcessDebugSections(false) to ignore them if debug info is not
67*06c3fb27SDimitry Andric   /// needed.
68*06c3fb27SDimitry Andric   ELFLinkGraphBuilder &setProcessDebugSections(bool ProcessDebugSections) {
69*06c3fb27SDimitry Andric     this->ProcessDebugSections = ProcessDebugSections;
70*06c3fb27SDimitry Andric     return *this;
71*06c3fb27SDimitry Andric   }
72*06c3fb27SDimitry Andric 
73fe6060f1SDimitry Andric   /// Attempt to construct and return the LinkGraph.
74fe6060f1SDimitry Andric   Expected<std::unique_ptr<LinkGraph>> buildGraph();
75fe6060f1SDimitry Andric 
76fe6060f1SDimitry Andric   /// Call to derived class to handle relocations. These require
77fe6060f1SDimitry Andric   /// architecture specific knowledge to map to JITLink edge kinds.
78fe6060f1SDimitry Andric   virtual Error addRelocations() = 0;
79fe6060f1SDimitry Andric 
80fe6060f1SDimitry Andric protected:
81fe6060f1SDimitry Andric   using ELFSectionIndex = unsigned;
82fe6060f1SDimitry Andric   using ELFSymbolIndex = unsigned;
83fe6060f1SDimitry Andric 
84fe6060f1SDimitry Andric   bool isRelocatable() const {
85fe6060f1SDimitry Andric     return Obj.getHeader().e_type == llvm::ELF::ET_REL;
86fe6060f1SDimitry Andric   }
87fe6060f1SDimitry Andric 
8804eeddc0SDimitry Andric   void setGraphBlock(ELFSectionIndex SecIndex, Block *B) {
8904eeddc0SDimitry Andric     assert(!GraphBlocks.count(SecIndex) && "Duplicate section at index");
9004eeddc0SDimitry Andric     GraphBlocks[SecIndex] = B;
91fe6060f1SDimitry Andric   }
92fe6060f1SDimitry Andric 
9304eeddc0SDimitry Andric   Block *getGraphBlock(ELFSectionIndex SecIndex) {
94*06c3fb27SDimitry Andric     return GraphBlocks.lookup(SecIndex);
95fe6060f1SDimitry Andric   }
96fe6060f1SDimitry Andric 
97fe6060f1SDimitry Andric   void setGraphSymbol(ELFSymbolIndex SymIndex, Symbol &Sym) {
98fe6060f1SDimitry Andric     assert(!GraphSymbols.count(SymIndex) && "Duplicate symbol at index");
99fe6060f1SDimitry Andric     GraphSymbols[SymIndex] = &Sym;
100fe6060f1SDimitry Andric   }
101fe6060f1SDimitry Andric 
102fe6060f1SDimitry Andric   Symbol *getGraphSymbol(ELFSymbolIndex SymIndex) {
103*06c3fb27SDimitry Andric     return GraphSymbols.lookup(SymIndex);
104fe6060f1SDimitry Andric   }
105fe6060f1SDimitry Andric 
106fe6060f1SDimitry Andric   Expected<std::pair<Linkage, Scope>>
107fe6060f1SDimitry Andric   getSymbolLinkageAndScope(const typename ELFT::Sym &Sym, StringRef Name);
108fe6060f1SDimitry Andric 
109*06c3fb27SDimitry Andric   /// Set the target flags on the given Symbol.
110*06c3fb27SDimitry Andric   virtual TargetFlagsType makeTargetFlags(const typename ELFT::Sym &Sym) {
111*06c3fb27SDimitry Andric     return TargetFlagsType{};
112*06c3fb27SDimitry Andric   }
113*06c3fb27SDimitry Andric 
114*06c3fb27SDimitry Andric   /// Get the physical offset of the symbol on the target platform.
115*06c3fb27SDimitry Andric   virtual orc::ExecutorAddrDiff getRawOffset(const typename ELFT::Sym &Sym,
116*06c3fb27SDimitry Andric                                              TargetFlagsType Flags) {
117*06c3fb27SDimitry Andric     return Sym.getValue();
118*06c3fb27SDimitry Andric   }
119*06c3fb27SDimitry Andric 
120fe6060f1SDimitry Andric   Error prepare();
121fe6060f1SDimitry Andric   Error graphifySections();
122fe6060f1SDimitry Andric   Error graphifySymbols();
123fe6060f1SDimitry Andric 
124*06c3fb27SDimitry Andric   /// Override in derived classes to suppress certain sections in the link
125*06c3fb27SDimitry Andric   /// graph.
126*06c3fb27SDimitry Andric   virtual bool excludeSection(const typename ELFT::Shdr &Sect) const {
127*06c3fb27SDimitry Andric     return false;
128*06c3fb27SDimitry Andric   }
129*06c3fb27SDimitry Andric 
130bdd1243dSDimitry Andric   /// Traverse all matching ELFT::Rela relocation records in the given section.
131bdd1243dSDimitry Andric   /// The handler function Func should be callable with this signature:
132349cc55cSDimitry Andric   ///   Error(const typename ELFT::Rela &,
133349cc55cSDimitry Andric   ///         const typename ELFT::Shdr &, Section &)
134349cc55cSDimitry Andric   ///
135bdd1243dSDimitry Andric   template <typename RelocHandlerMethod>
136bdd1243dSDimitry Andric   Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,
137*06c3fb27SDimitry Andric                               RelocHandlerMethod &&Func);
138349cc55cSDimitry Andric 
139bdd1243dSDimitry Andric   /// Traverse all matching ELFT::Rel relocation records in the given section.
140bdd1243dSDimitry Andric   /// The handler function Func should be callable with this signature:
141bdd1243dSDimitry Andric   ///   Error(const typename ELFT::Rel &,
142bdd1243dSDimitry Andric   ///         const typename ELFT::Shdr &, Section &)
143bdd1243dSDimitry Andric   ///
144bdd1243dSDimitry Andric   template <typename RelocHandlerMethod>
145bdd1243dSDimitry Andric   Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,
146*06c3fb27SDimitry Andric                              RelocHandlerMethod &&Func);
147bdd1243dSDimitry Andric 
148bdd1243dSDimitry Andric   /// Traverse all matching rela relocation records in the given section.
149bdd1243dSDimitry Andric   /// Convenience wrapper to allow passing a member function for the handler.
150349cc55cSDimitry Andric   ///
151349cc55cSDimitry Andric   template <typename ClassT, typename RelocHandlerMethod>
152bdd1243dSDimitry Andric   Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,
153*06c3fb27SDimitry Andric                               ClassT *Instance, RelocHandlerMethod &&Method) {
154bdd1243dSDimitry Andric     return forEachRelaRelocation(
155bdd1243dSDimitry Andric         RelSect,
156bdd1243dSDimitry Andric         [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
157bdd1243dSDimitry Andric           return (Instance->*Method)(Rel, Target, GS);
158*06c3fb27SDimitry Andric         });
159bdd1243dSDimitry Andric   }
160bdd1243dSDimitry Andric 
161bdd1243dSDimitry Andric   /// Traverse all matching rel relocation records in the given section.
162bdd1243dSDimitry Andric   /// Convenience wrapper to allow passing a member function for the handler.
163bdd1243dSDimitry Andric   ///
164bdd1243dSDimitry Andric   template <typename ClassT, typename RelocHandlerMethod>
165bdd1243dSDimitry Andric   Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,
166*06c3fb27SDimitry Andric                              ClassT *Instance, RelocHandlerMethod &&Method) {
167bdd1243dSDimitry Andric     return forEachRelRelocation(
168349cc55cSDimitry Andric         RelSect,
169349cc55cSDimitry Andric         [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
170349cc55cSDimitry Andric           return (Instance->*Method)(Rel, Target, GS);
171*06c3fb27SDimitry Andric         });
172349cc55cSDimitry Andric   }
173349cc55cSDimitry Andric 
174fe6060f1SDimitry Andric   const ELFFile &Obj;
175fe6060f1SDimitry Andric 
176fe6060f1SDimitry Andric   typename ELFFile::Elf_Shdr_Range Sections;
177fe6060f1SDimitry Andric   const typename ELFFile::Elf_Shdr *SymTabSec = nullptr;
178fe6060f1SDimitry Andric   StringRef SectionStringTab;
179*06c3fb27SDimitry Andric   bool ProcessDebugSections = true;
180fe6060f1SDimitry Andric 
18104eeddc0SDimitry Andric   // Maps ELF section indexes to LinkGraph Blocks.
18204eeddc0SDimitry Andric   // Only SHF_ALLOC sections will have graph blocks.
18304eeddc0SDimitry Andric   DenseMap<ELFSectionIndex, Block *> GraphBlocks;
184fe6060f1SDimitry Andric   DenseMap<ELFSymbolIndex, Symbol *> GraphSymbols;
1854824e7fdSDimitry Andric   DenseMap<const typename ELFFile::Elf_Shdr *,
1864824e7fdSDimitry Andric            ArrayRef<typename ELFFile::Elf_Word>>
1874824e7fdSDimitry Andric       ShndxTables;
188fe6060f1SDimitry Andric };
189fe6060f1SDimitry Andric 
190fe6060f1SDimitry Andric template <typename ELFT>
191fe6060f1SDimitry Andric ELFLinkGraphBuilder<ELFT>::ELFLinkGraphBuilder(
192*06c3fb27SDimitry Andric     const ELFFile &Obj, Triple TT, SubtargetFeatures Features,
193*06c3fb27SDimitry Andric     StringRef FileName, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
194fe6060f1SDimitry Andric     : ELFLinkGraphBuilderBase(std::make_unique<LinkGraph>(
195*06c3fb27SDimitry Andric           FileName.str(), Triple(std::move(TT)), std::move(Features),
196*06c3fb27SDimitry Andric           ELFT::Is64Bits ? 8 : 4, support::endianness(ELFT::TargetEndianness),
197fe6060f1SDimitry Andric           std::move(GetEdgeKindName))),
198fe6060f1SDimitry Andric       Obj(Obj) {
199fe6060f1SDimitry Andric   LLVM_DEBUG(
200fe6060f1SDimitry Andric       { dbgs() << "Created ELFLinkGraphBuilder for \"" << FileName << "\""; });
201fe6060f1SDimitry Andric }
202fe6060f1SDimitry Andric 
203fe6060f1SDimitry Andric template <typename ELFT>
204fe6060f1SDimitry Andric Expected<std::unique_ptr<LinkGraph>> ELFLinkGraphBuilder<ELFT>::buildGraph() {
205fe6060f1SDimitry Andric   if (!isRelocatable())
206fe6060f1SDimitry Andric     return make_error<JITLinkError>("Object is not a relocatable ELF file");
207fe6060f1SDimitry Andric 
208fe6060f1SDimitry Andric   if (auto Err = prepare())
209fe6060f1SDimitry Andric     return std::move(Err);
210fe6060f1SDimitry Andric 
211fe6060f1SDimitry Andric   if (auto Err = graphifySections())
212fe6060f1SDimitry Andric     return std::move(Err);
213fe6060f1SDimitry Andric 
214fe6060f1SDimitry Andric   if (auto Err = graphifySymbols())
215fe6060f1SDimitry Andric     return std::move(Err);
216fe6060f1SDimitry Andric 
217fe6060f1SDimitry Andric   if (auto Err = addRelocations())
218fe6060f1SDimitry Andric     return std::move(Err);
219fe6060f1SDimitry Andric 
220fe6060f1SDimitry Andric   return std::move(G);
221fe6060f1SDimitry Andric }
222fe6060f1SDimitry Andric 
223fe6060f1SDimitry Andric template <typename ELFT>
224fe6060f1SDimitry Andric Expected<std::pair<Linkage, Scope>>
225fe6060f1SDimitry Andric ELFLinkGraphBuilder<ELFT>::getSymbolLinkageAndScope(
226fe6060f1SDimitry Andric     const typename ELFT::Sym &Sym, StringRef Name) {
227fe6060f1SDimitry Andric   Linkage L = Linkage::Strong;
228fe6060f1SDimitry Andric   Scope S = Scope::Default;
229fe6060f1SDimitry Andric 
230fe6060f1SDimitry Andric   switch (Sym.getBinding()) {
231fe6060f1SDimitry Andric   case ELF::STB_LOCAL:
232fe6060f1SDimitry Andric     S = Scope::Local;
233fe6060f1SDimitry Andric     break;
234fe6060f1SDimitry Andric   case ELF::STB_GLOBAL:
235fe6060f1SDimitry Andric     // Nothing to do here.
236fe6060f1SDimitry Andric     break;
237fe6060f1SDimitry Andric   case ELF::STB_WEAK:
238349cc55cSDimitry Andric   case ELF::STB_GNU_UNIQUE:
239fe6060f1SDimitry Andric     L = Linkage::Weak;
240fe6060f1SDimitry Andric     break;
241fe6060f1SDimitry Andric   default:
242349cc55cSDimitry Andric     return make_error<StringError>(
243349cc55cSDimitry Andric         "Unrecognized symbol binding " +
244349cc55cSDimitry Andric             Twine(static_cast<int>(Sym.getBinding())) + " for " + Name,
245fe6060f1SDimitry Andric         inconvertibleErrorCode());
246fe6060f1SDimitry Andric   }
247fe6060f1SDimitry Andric 
248fe6060f1SDimitry Andric   switch (Sym.getVisibility()) {
249fe6060f1SDimitry Andric   case ELF::STV_DEFAULT:
250fe6060f1SDimitry Andric   case ELF::STV_PROTECTED:
251fe6060f1SDimitry Andric     // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs
252fe6060f1SDimitry Andric     // Orc support.
253fe6060f1SDimitry Andric     // Otherwise nothing to do here.
254fe6060f1SDimitry Andric     break;
255fe6060f1SDimitry Andric   case ELF::STV_HIDDEN:
256fe6060f1SDimitry Andric     // Default scope -> Hidden scope. No effect on local scope.
257fe6060f1SDimitry Andric     if (S == Scope::Default)
258fe6060f1SDimitry Andric       S = Scope::Hidden;
259fe6060f1SDimitry Andric     break;
260fe6060f1SDimitry Andric   case ELF::STV_INTERNAL:
261349cc55cSDimitry Andric     return make_error<StringError>(
262349cc55cSDimitry Andric         "Unrecognized symbol visibility " +
263349cc55cSDimitry Andric             Twine(static_cast<int>(Sym.getVisibility())) + " for " + Name,
264fe6060f1SDimitry Andric         inconvertibleErrorCode());
265fe6060f1SDimitry Andric   }
266fe6060f1SDimitry Andric 
267fe6060f1SDimitry Andric   return std::make_pair(L, S);
268fe6060f1SDimitry Andric }
269fe6060f1SDimitry Andric 
270fe6060f1SDimitry Andric template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::prepare() {
271fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "  Preparing to build...\n");
272fe6060f1SDimitry Andric 
273fe6060f1SDimitry Andric   // Get the sections array.
274fe6060f1SDimitry Andric   if (auto SectionsOrErr = Obj.sections())
275fe6060f1SDimitry Andric     Sections = *SectionsOrErr;
276fe6060f1SDimitry Andric   else
277fe6060f1SDimitry Andric     return SectionsOrErr.takeError();
278fe6060f1SDimitry Andric 
279fe6060f1SDimitry Andric   // Get the section string table.
280fe6060f1SDimitry Andric   if (auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))
281fe6060f1SDimitry Andric     SectionStringTab = *SectionStringTabOrErr;
282fe6060f1SDimitry Andric   else
283fe6060f1SDimitry Andric     return SectionStringTabOrErr.takeError();
284fe6060f1SDimitry Andric 
285fe6060f1SDimitry Andric   // Get the SHT_SYMTAB section.
2864824e7fdSDimitry Andric   for (auto &Sec : Sections) {
287fe6060f1SDimitry Andric     if (Sec.sh_type == ELF::SHT_SYMTAB) {
288fe6060f1SDimitry Andric       if (!SymTabSec)
289fe6060f1SDimitry Andric         SymTabSec = &Sec;
290fe6060f1SDimitry Andric       else
291fe6060f1SDimitry Andric         return make_error<JITLinkError>("Multiple SHT_SYMTAB sections in " +
292fe6060f1SDimitry Andric                                         G->getName());
293fe6060f1SDimitry Andric     }
294fe6060f1SDimitry Andric 
2954824e7fdSDimitry Andric     // Extended table.
2964824e7fdSDimitry Andric     if (Sec.sh_type == ELF::SHT_SYMTAB_SHNDX) {
2974824e7fdSDimitry Andric       uint32_t SymtabNdx = Sec.sh_link;
2984824e7fdSDimitry Andric       if (SymtabNdx >= Sections.size())
2994824e7fdSDimitry Andric         return make_error<JITLinkError>("sh_link is out of bound");
3004824e7fdSDimitry Andric 
3014824e7fdSDimitry Andric       auto ShndxTable = Obj.getSHNDXTable(Sec);
3024824e7fdSDimitry Andric       if (!ShndxTable)
3034824e7fdSDimitry Andric         return ShndxTable.takeError();
3044824e7fdSDimitry Andric 
3054824e7fdSDimitry Andric       ShndxTables.insert({&Sections[SymtabNdx], *ShndxTable});
3064824e7fdSDimitry Andric     }
3074824e7fdSDimitry Andric   }
3084824e7fdSDimitry Andric 
309fe6060f1SDimitry Andric   return Error::success();
310fe6060f1SDimitry Andric }
311fe6060f1SDimitry Andric 
312fe6060f1SDimitry Andric template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() {
313fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "  Creating graph sections...\n");
314fe6060f1SDimitry Andric 
315fe6060f1SDimitry Andric   // For each section...
316fe6060f1SDimitry Andric   for (ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {
317fe6060f1SDimitry Andric 
318fe6060f1SDimitry Andric     auto &Sec = Sections[SecIndex];
319fe6060f1SDimitry Andric 
320fe6060f1SDimitry Andric     // Start by getting the section name.
321fe6060f1SDimitry Andric     auto Name = Obj.getSectionName(Sec, SectionStringTab);
322fe6060f1SDimitry Andric     if (!Name)
323fe6060f1SDimitry Andric       return Name.takeError();
324*06c3fb27SDimitry Andric     if (excludeSection(Sec)) {
325fe6060f1SDimitry Andric       LLVM_DEBUG({
326*06c3fb27SDimitry Andric         dbgs() << "    " << SecIndex << ": Skipping section \"" << *Name
327*06c3fb27SDimitry Andric                << "\" explicitly\n";
328fe6060f1SDimitry Andric       });
329fe6060f1SDimitry Andric       continue;
330fe6060f1SDimitry Andric     }
331fe6060f1SDimitry Andric 
332*06c3fb27SDimitry Andric     // Skip null sections.
333*06c3fb27SDimitry Andric     if (Sec.sh_type == ELF::SHT_NULL) {
334*06c3fb27SDimitry Andric       LLVM_DEBUG({
335*06c3fb27SDimitry Andric         dbgs() << "    " << SecIndex << ": has type SHT_NULL. Skipping.\n";
336*06c3fb27SDimitry Andric       });
337*06c3fb27SDimitry Andric       continue;
338*06c3fb27SDimitry Andric     }
339*06c3fb27SDimitry Andric 
340*06c3fb27SDimitry Andric     // If the name indicates that it's a debug section then skip it: We don't
341*06c3fb27SDimitry Andric     // support those yet.
342*06c3fb27SDimitry Andric     if (!ProcessDebugSections && isDwarfSection(*Name)) {
343fe6060f1SDimitry Andric       LLVM_DEBUG({
344fe6060f1SDimitry Andric         dbgs() << "    " << SecIndex << ": \"" << *Name
345*06c3fb27SDimitry Andric                << "\" is a debug section: "
346fe6060f1SDimitry Andric                   "No graph section will be created.\n";
347fe6060f1SDimitry Andric       });
348fe6060f1SDimitry Andric       continue;
349fe6060f1SDimitry Andric     }
350fe6060f1SDimitry Andric 
351fe6060f1SDimitry Andric     LLVM_DEBUG({
352fe6060f1SDimitry Andric       dbgs() << "    " << SecIndex << ": Creating section for \"" << *Name
353fe6060f1SDimitry Andric              << "\"\n";
354fe6060f1SDimitry Andric     });
355fe6060f1SDimitry Andric 
356fe6060f1SDimitry Andric     // Get the section's memory protection flags.
357*06c3fb27SDimitry Andric     orc::MemProt Prot = orc::MemProt::Read;
358fe6060f1SDimitry Andric     if (Sec.sh_flags & ELF::SHF_EXECINSTR)
359*06c3fb27SDimitry Andric       Prot |= orc::MemProt::Exec;
360*06c3fb27SDimitry Andric     if (Sec.sh_flags & ELF::SHF_WRITE)
361*06c3fb27SDimitry Andric       Prot |= orc::MemProt::Write;
362fe6060f1SDimitry Andric 
36304eeddc0SDimitry Andric     // Look for existing sections first.
36404eeddc0SDimitry Andric     auto *GraphSec = G->findSectionByName(*Name);
365*06c3fb27SDimitry Andric     if (!GraphSec) {
36604eeddc0SDimitry Andric       GraphSec = &G->createSection(*Name, Prot);
367*06c3fb27SDimitry Andric       // Non-SHF_ALLOC sections get NoAlloc memory lifetimes.
368*06c3fb27SDimitry Andric       if (!(Sec.sh_flags & ELF::SHF_ALLOC)) {
369*06c3fb27SDimitry Andric         GraphSec->setMemLifetimePolicy(orc::MemLifetimePolicy::NoAlloc);
370*06c3fb27SDimitry Andric         LLVM_DEBUG({
371*06c3fb27SDimitry Andric           dbgs() << "      " << SecIndex << ": \"" << *Name
372*06c3fb27SDimitry Andric                  << "\" is not a SHF_ALLOC section. Using NoAlloc lifetime.\n";
373*06c3fb27SDimitry Andric         });
374*06c3fb27SDimitry Andric       }
375*06c3fb27SDimitry Andric     }
376*06c3fb27SDimitry Andric 
37704eeddc0SDimitry Andric     assert(GraphSec->getMemProt() == Prot && "MemProt should match");
37804eeddc0SDimitry Andric 
37904eeddc0SDimitry Andric     Block *B = nullptr;
380fe6060f1SDimitry Andric     if (Sec.sh_type != ELF::SHT_NOBITS) {
381fe6060f1SDimitry Andric       auto Data = Obj.template getSectionContentsAsArray<char>(Sec);
382fe6060f1SDimitry Andric       if (!Data)
383fe6060f1SDimitry Andric         return Data.takeError();
384fe6060f1SDimitry Andric 
38504eeddc0SDimitry Andric       B = &G->createContentBlock(*GraphSec, *Data,
38604eeddc0SDimitry Andric                                  orc::ExecutorAddr(Sec.sh_addr),
38704eeddc0SDimitry Andric                                  Sec.sh_addralign, 0);
388fe6060f1SDimitry Andric     } else
38904eeddc0SDimitry Andric       B = &G->createZeroFillBlock(*GraphSec, Sec.sh_size,
39004eeddc0SDimitry Andric                                   orc::ExecutorAddr(Sec.sh_addr),
391fe6060f1SDimitry Andric                                   Sec.sh_addralign, 0);
392fe6060f1SDimitry Andric 
39304eeddc0SDimitry Andric     setGraphBlock(SecIndex, B);
394fe6060f1SDimitry Andric   }
395fe6060f1SDimitry Andric 
396fe6060f1SDimitry Andric   return Error::success();
397fe6060f1SDimitry Andric }
398fe6060f1SDimitry Andric 
399fe6060f1SDimitry Andric template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
400fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "  Creating graph symbols...\n");
401fe6060f1SDimitry Andric 
402fe6060f1SDimitry Andric   // No SYMTAB -- Bail out early.
403fe6060f1SDimitry Andric   if (!SymTabSec)
404fe6060f1SDimitry Andric     return Error::success();
405fe6060f1SDimitry Andric 
406fe6060f1SDimitry Andric   // Get the section content as a Symbols array.
407fe6060f1SDimitry Andric   auto Symbols = Obj.symbols(SymTabSec);
408fe6060f1SDimitry Andric   if (!Symbols)
409fe6060f1SDimitry Andric     return Symbols.takeError();
410fe6060f1SDimitry Andric 
411fe6060f1SDimitry Andric   // Get the string table for this section.
412fe6060f1SDimitry Andric   auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
413fe6060f1SDimitry Andric   if (!StringTab)
414fe6060f1SDimitry Andric     return StringTab.takeError();
415fe6060f1SDimitry Andric 
416fe6060f1SDimitry Andric   LLVM_DEBUG({
417fe6060f1SDimitry Andric     StringRef SymTabName;
418fe6060f1SDimitry Andric 
419fe6060f1SDimitry Andric     if (auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
420fe6060f1SDimitry Andric       SymTabName = *SymTabNameOrErr;
421fe6060f1SDimitry Andric     else {
422fe6060f1SDimitry Andric       dbgs() << "Could not get ELF SHT_SYMTAB section name for logging: "
423fe6060f1SDimitry Andric              << toString(SymTabNameOrErr.takeError()) << "\n";
424fe6060f1SDimitry Andric       SymTabName = "<SHT_SYMTAB section with invalid name>";
425fe6060f1SDimitry Andric     }
426fe6060f1SDimitry Andric 
427fe6060f1SDimitry Andric     dbgs() << "    Adding symbols from symtab section \"" << SymTabName
428fe6060f1SDimitry Andric            << "\"\n";
429fe6060f1SDimitry Andric   });
430fe6060f1SDimitry Andric 
431fe6060f1SDimitry Andric   for (ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
432fe6060f1SDimitry Andric     auto &Sym = (*Symbols)[SymIndex];
433fe6060f1SDimitry Andric 
434fe6060f1SDimitry Andric     // Check symbol type.
435fe6060f1SDimitry Andric     switch (Sym.getType()) {
436fe6060f1SDimitry Andric     case ELF::STT_FILE:
437fe6060f1SDimitry Andric       LLVM_DEBUG({
438fe6060f1SDimitry Andric         if (auto Name = Sym.getName(*StringTab))
439fe6060f1SDimitry Andric           dbgs() << "      " << SymIndex << ": Skipping STT_FILE symbol \""
440fe6060f1SDimitry Andric                  << *Name << "\"\n";
441fe6060f1SDimitry Andric         else {
442fe6060f1SDimitry Andric           dbgs() << "Could not get STT_FILE symbol name: "
443fe6060f1SDimitry Andric                  << toString(Name.takeError()) << "\n";
444fe6060f1SDimitry Andric           dbgs() << "     " << SymIndex
445fe6060f1SDimitry Andric                  << ": Skipping STT_FILE symbol with invalid name\n";
446fe6060f1SDimitry Andric         }
447fe6060f1SDimitry Andric       });
448fe6060f1SDimitry Andric       continue;
449fe6060f1SDimitry Andric       break;
450fe6060f1SDimitry Andric     }
451fe6060f1SDimitry Andric 
452fe6060f1SDimitry Andric     // Get the symbol name.
453fe6060f1SDimitry Andric     auto Name = Sym.getName(*StringTab);
454fe6060f1SDimitry Andric     if (!Name)
455fe6060f1SDimitry Andric       return Name.takeError();
456fe6060f1SDimitry Andric 
457fe6060f1SDimitry Andric     // Handle common symbols specially.
458fe6060f1SDimitry Andric     if (Sym.isCommon()) {
459bdd1243dSDimitry Andric       Symbol &GSym = G->addDefinedSymbol(
460bdd1243dSDimitry Andric           G->createZeroFillBlock(getCommonSection(), Sym.st_size,
461bdd1243dSDimitry Andric                                  orc::ExecutorAddr(), Sym.getValue(), 0),
462bdd1243dSDimitry Andric           0, *Name, Sym.st_size, Linkage::Strong, Scope::Default, false, false);
463fe6060f1SDimitry Andric       setGraphSymbol(SymIndex, GSym);
464fe6060f1SDimitry Andric       continue;
465fe6060f1SDimitry Andric     }
466fe6060f1SDimitry Andric 
467fe6060f1SDimitry Andric     if (Sym.isDefined() &&
468fe6060f1SDimitry Andric         (Sym.getType() == ELF::STT_NOTYPE || Sym.getType() == ELF::STT_FUNC ||
469fe6060f1SDimitry Andric          Sym.getType() == ELF::STT_OBJECT ||
470349cc55cSDimitry Andric          Sym.getType() == ELF::STT_SECTION || Sym.getType() == ELF::STT_TLS)) {
471bdd1243dSDimitry Andric 
472bdd1243dSDimitry Andric       // Map Visibility and Binding to Scope and Linkage:
473bdd1243dSDimitry Andric       Linkage L;
474bdd1243dSDimitry Andric       Scope S;
475bdd1243dSDimitry Andric       if (auto LSOrErr = getSymbolLinkageAndScope(Sym, *Name))
476bdd1243dSDimitry Andric         std::tie(L, S) = *LSOrErr;
477bdd1243dSDimitry Andric       else
478bdd1243dSDimitry Andric         return LSOrErr.takeError();
479bdd1243dSDimitry Andric 
4804824e7fdSDimitry Andric       // Handle extended tables.
4814824e7fdSDimitry Andric       unsigned Shndx = Sym.st_shndx;
4824824e7fdSDimitry Andric       if (Shndx == ELF::SHN_XINDEX) {
4834824e7fdSDimitry Andric         auto ShndxTable = ShndxTables.find(SymTabSec);
4844824e7fdSDimitry Andric         if (ShndxTable == ShndxTables.end())
4854824e7fdSDimitry Andric           continue;
4864824e7fdSDimitry Andric         auto NdxOrErr = object::getExtendedSymbolTableIndex<ELFT>(
4874824e7fdSDimitry Andric             Sym, SymIndex, ShndxTable->second);
4884824e7fdSDimitry Andric         if (!NdxOrErr)
4894824e7fdSDimitry Andric           return NdxOrErr.takeError();
4904824e7fdSDimitry Andric         Shndx = *NdxOrErr;
4914824e7fdSDimitry Andric       }
49204eeddc0SDimitry Andric       if (auto *B = getGraphBlock(Shndx)) {
493fe6060f1SDimitry Andric         LLVM_DEBUG({
494fe6060f1SDimitry Andric           dbgs() << "      " << SymIndex
495fe6060f1SDimitry Andric                  << ": Creating defined graph symbol for ELF symbol \"" << *Name
496fe6060f1SDimitry Andric                  << "\"\n";
497fe6060f1SDimitry Andric         });
498fe6060f1SDimitry Andric 
499*06c3fb27SDimitry Andric         TargetFlagsType Flags = makeTargetFlags(Sym);
500*06c3fb27SDimitry Andric         orc::ExecutorAddrDiff Offset = getRawOffset(Sym, Flags);
501*06c3fb27SDimitry Andric 
50204eeddc0SDimitry Andric         // In RISCV, temporary symbols (Used to generate dwarf, eh_frame
50304eeddc0SDimitry Andric         // sections...) will appear in object code's symbol table, and LLVM does
50404eeddc0SDimitry Andric         // not use names on these temporary symbols (RISCV gnu toolchain uses
50504eeddc0SDimitry Andric         // names on these temporary symbols). If the symbol is unnamed, add an
50604eeddc0SDimitry Andric         // anonymous symbol.
507fe6060f1SDimitry Andric         auto &GSym =
50804eeddc0SDimitry Andric             Name->empty()
509*06c3fb27SDimitry Andric                 ? G->addAnonymousSymbol(*B, Offset, Sym.st_size,
51004eeddc0SDimitry Andric                                         false, false)
511*06c3fb27SDimitry Andric                 : G->addDefinedSymbol(*B, Offset, *Name, Sym.st_size, L,
512*06c3fb27SDimitry Andric                                       S, Sym.getType() == ELF::STT_FUNC,
513*06c3fb27SDimitry Andric                                       false);
514*06c3fb27SDimitry Andric 
515*06c3fb27SDimitry Andric         GSym.setTargetFlags(Flags);
516fe6060f1SDimitry Andric         setGraphSymbol(SymIndex, GSym);
517fe6060f1SDimitry Andric       }
518fe6060f1SDimitry Andric     } else if (Sym.isUndefined() && Sym.isExternal()) {
519fe6060f1SDimitry Andric       LLVM_DEBUG({
520fe6060f1SDimitry Andric         dbgs() << "      " << SymIndex
521fe6060f1SDimitry Andric                << ": Creating external graph symbol for ELF symbol \"" << *Name
522fe6060f1SDimitry Andric                << "\"\n";
523fe6060f1SDimitry Andric       });
524bdd1243dSDimitry Andric 
525bdd1243dSDimitry Andric       if (Sym.getBinding() != ELF::STB_GLOBAL &&
526bdd1243dSDimitry Andric           Sym.getBinding() != ELF::STB_WEAK)
527bdd1243dSDimitry Andric         return make_error<StringError>(
528bdd1243dSDimitry Andric             "Invalid symbol binding " +
529bdd1243dSDimitry Andric                 Twine(static_cast<int>(Sym.getBinding())) +
530bdd1243dSDimitry Andric                 " for external symbol " + *Name,
531bdd1243dSDimitry Andric             inconvertibleErrorCode());
532bdd1243dSDimitry Andric 
533bdd1243dSDimitry Andric       // If L is Linkage::Weak that means this is a weakly referenced symbol.
534bdd1243dSDimitry Andric       auto &GSym = G->addExternalSymbol(*Name, Sym.st_size,
535bdd1243dSDimitry Andric                                         Sym.getBinding() == ELF::STB_WEAK);
536fe6060f1SDimitry Andric       setGraphSymbol(SymIndex, GSym);
537*06c3fb27SDimitry Andric     } else if (Sym.isUndefined() && Sym.st_value == 0 && Sym.st_size == 0 &&
538*06c3fb27SDimitry Andric                Sym.getType() == ELF::STT_NOTYPE &&
539*06c3fb27SDimitry Andric                Sym.getBinding() == ELF::STB_LOCAL && Name->empty()) {
540*06c3fb27SDimitry Andric       // Some relocations (e.g., R_RISCV_ALIGN) don't have a target symbol and
541*06c3fb27SDimitry Andric       // use this kind of null symbol as a placeholder.
542*06c3fb27SDimitry Andric       LLVM_DEBUG({
543*06c3fb27SDimitry Andric         dbgs() << "      " << SymIndex << ": Creating null graph symbol\n";
544*06c3fb27SDimitry Andric       });
545*06c3fb27SDimitry Andric 
546*06c3fb27SDimitry Andric       auto SymName =
547*06c3fb27SDimitry Andric           G->allocateContent("__jitlink_ELF_SYM_UND_" + Twine(SymIndex));
548*06c3fb27SDimitry Andric       auto SymNameRef = StringRef(SymName.data(), SymName.size());
549*06c3fb27SDimitry Andric       auto &GSym = G->addAbsoluteSymbol(SymNameRef, orc::ExecutorAddr(0), 0,
550*06c3fb27SDimitry Andric                                         Linkage::Strong, Scope::Local, false);
551*06c3fb27SDimitry Andric       setGraphSymbol(SymIndex, GSym);
552fe6060f1SDimitry Andric     } else {
553fe6060f1SDimitry Andric       LLVM_DEBUG({
554fe6060f1SDimitry Andric         dbgs() << "      " << SymIndex
555fe6060f1SDimitry Andric                << ": Not creating graph symbol for ELF symbol \"" << *Name
556fe6060f1SDimitry Andric                << "\" with unrecognized type\n";
557fe6060f1SDimitry Andric       });
558fe6060f1SDimitry Andric     }
559fe6060f1SDimitry Andric   }
560fe6060f1SDimitry Andric 
561fe6060f1SDimitry Andric   return Error::success();
562fe6060f1SDimitry Andric }
563fe6060f1SDimitry Andric 
564349cc55cSDimitry Andric template <typename ELFT>
565349cc55cSDimitry Andric template <typename RelocHandlerFunction>
566bdd1243dSDimitry Andric Error ELFLinkGraphBuilder<ELFT>::forEachRelaRelocation(
567*06c3fb27SDimitry Andric     const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
568349cc55cSDimitry Andric   // Only look into sections that store relocation entries.
569bdd1243dSDimitry Andric   if (RelSect.sh_type != ELF::SHT_RELA)
570349cc55cSDimitry Andric     return Error::success();
571349cc55cSDimitry Andric 
572349cc55cSDimitry Andric   // sh_info contains the section header index of the target (FixupSection),
573349cc55cSDimitry Andric   // which is the section to which all relocations in RelSect apply.
574349cc55cSDimitry Andric   auto FixupSection = Obj.getSection(RelSect.sh_info);
575349cc55cSDimitry Andric   if (!FixupSection)
576349cc55cSDimitry Andric     return FixupSection.takeError();
577349cc55cSDimitry Andric 
578349cc55cSDimitry Andric   // Target sections have names in valid ELF object files.
579349cc55cSDimitry Andric   Expected<StringRef> Name = Obj.getSectionName(**FixupSection);
580349cc55cSDimitry Andric   if (!Name)
581349cc55cSDimitry Andric     return Name.takeError();
582349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "  " << *Name << ":\n");
583349cc55cSDimitry Andric 
584349cc55cSDimitry Andric   // Consider skipping these relocations.
585349cc55cSDimitry Andric   if (!ProcessDebugSections && isDwarfSection(*Name)) {
586349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "    skipped (dwarf section)\n\n");
587349cc55cSDimitry Andric     return Error::success();
588349cc55cSDimitry Andric   }
589*06c3fb27SDimitry Andric   if (excludeSection(**FixupSection)) {
590*06c3fb27SDimitry Andric     LLVM_DEBUG(dbgs() << "    skipped (fixup section excluded explicitly)\n\n");
591*06c3fb27SDimitry Andric     return Error::success();
592*06c3fb27SDimitry Andric   }
593349cc55cSDimitry Andric 
594349cc55cSDimitry Andric   // Lookup the link-graph node corresponding to the target section name.
59504eeddc0SDimitry Andric   auto *BlockToFix = getGraphBlock(RelSect.sh_info);
59604eeddc0SDimitry Andric   if (!BlockToFix)
597349cc55cSDimitry Andric     return make_error<StringError>(
598349cc55cSDimitry Andric         "Refencing a section that wasn't added to the graph: " + *Name,
599349cc55cSDimitry Andric         inconvertibleErrorCode());
600349cc55cSDimitry Andric 
601349cc55cSDimitry Andric   auto RelEntries = Obj.relas(RelSect);
602349cc55cSDimitry Andric   if (!RelEntries)
603349cc55cSDimitry Andric     return RelEntries.takeError();
604349cc55cSDimitry Andric 
605349cc55cSDimitry Andric   // Let the callee process relocation entries one by one.
606349cc55cSDimitry Andric   for (const typename ELFT::Rela &R : *RelEntries)
60704eeddc0SDimitry Andric     if (Error Err = Func(R, **FixupSection, *BlockToFix))
608349cc55cSDimitry Andric       return Err;
609349cc55cSDimitry Andric 
610349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "\n");
611349cc55cSDimitry Andric   return Error::success();
612349cc55cSDimitry Andric }
613349cc55cSDimitry Andric 
614bdd1243dSDimitry Andric template <typename ELFT>
615bdd1243dSDimitry Andric template <typename RelocHandlerFunction>
616bdd1243dSDimitry Andric Error ELFLinkGraphBuilder<ELFT>::forEachRelRelocation(
617*06c3fb27SDimitry Andric     const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
618bdd1243dSDimitry Andric   // Only look into sections that store relocation entries.
619bdd1243dSDimitry Andric   if (RelSect.sh_type != ELF::SHT_REL)
620bdd1243dSDimitry Andric     return Error::success();
621bdd1243dSDimitry Andric 
622bdd1243dSDimitry Andric   // sh_info contains the section header index of the target (FixupSection),
623bdd1243dSDimitry Andric   // which is the section to which all relocations in RelSect apply.
624bdd1243dSDimitry Andric   auto FixupSection = Obj.getSection(RelSect.sh_info);
625bdd1243dSDimitry Andric   if (!FixupSection)
626bdd1243dSDimitry Andric     return FixupSection.takeError();
627bdd1243dSDimitry Andric 
628bdd1243dSDimitry Andric   // Target sections have names in valid ELF object files.
629bdd1243dSDimitry Andric   Expected<StringRef> Name = Obj.getSectionName(**FixupSection);
630bdd1243dSDimitry Andric   if (!Name)
631bdd1243dSDimitry Andric     return Name.takeError();
632bdd1243dSDimitry Andric   LLVM_DEBUG(dbgs() << "  " << *Name << ":\n");
633bdd1243dSDimitry Andric 
634bdd1243dSDimitry Andric   // Consider skipping these relocations.
635bdd1243dSDimitry Andric   if (!ProcessDebugSections && isDwarfSection(*Name)) {
636bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "    skipped (dwarf section)\n\n");
637bdd1243dSDimitry Andric     return Error::success();
638bdd1243dSDimitry Andric   }
639*06c3fb27SDimitry Andric   if (excludeSection(**FixupSection)) {
640*06c3fb27SDimitry Andric     LLVM_DEBUG(dbgs() << "    skipped (fixup section excluded explicitly)\n\n");
641*06c3fb27SDimitry Andric     return Error::success();
642*06c3fb27SDimitry Andric   }
643bdd1243dSDimitry Andric 
644bdd1243dSDimitry Andric   // Lookup the link-graph node corresponding to the target section name.
645bdd1243dSDimitry Andric   auto *BlockToFix = getGraphBlock(RelSect.sh_info);
646bdd1243dSDimitry Andric   if (!BlockToFix)
647bdd1243dSDimitry Andric     return make_error<StringError>(
648bdd1243dSDimitry Andric         "Refencing a section that wasn't added to the graph: " + *Name,
649bdd1243dSDimitry Andric         inconvertibleErrorCode());
650bdd1243dSDimitry Andric 
651bdd1243dSDimitry Andric   auto RelEntries = Obj.rels(RelSect);
652bdd1243dSDimitry Andric   if (!RelEntries)
653bdd1243dSDimitry Andric     return RelEntries.takeError();
654bdd1243dSDimitry Andric 
655bdd1243dSDimitry Andric   // Let the callee process relocation entries one by one.
656bdd1243dSDimitry Andric   for (const typename ELFT::Rel &R : *RelEntries)
657bdd1243dSDimitry Andric     if (Error Err = Func(R, **FixupSection, *BlockToFix))
658bdd1243dSDimitry Andric       return Err;
659bdd1243dSDimitry Andric 
660bdd1243dSDimitry Andric   LLVM_DEBUG(dbgs() << "\n");
661bdd1243dSDimitry Andric   return Error::success();
662bdd1243dSDimitry Andric }
663bdd1243dSDimitry Andric 
664fe6060f1SDimitry Andric } // end namespace jitlink
665fe6060f1SDimitry Andric } // end namespace llvm
666fe6060f1SDimitry Andric 
667fe6060f1SDimitry Andric #undef DEBUG_TYPE
668fe6060f1SDimitry Andric 
669fe6060f1SDimitry Andric #endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
670