xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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)
40*bdd1243dSDimitry Andric       CommonSection = &G->createSection(
41*bdd1243dSDimitry 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,
62fe6060f1SDimitry Andric                       StringRef FileName,
63fe6060f1SDimitry Andric                       LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
64fe6060f1SDimitry Andric 
65fe6060f1SDimitry Andric   /// Attempt to construct and return the LinkGraph.
66fe6060f1SDimitry Andric   Expected<std::unique_ptr<LinkGraph>> buildGraph();
67fe6060f1SDimitry Andric 
68fe6060f1SDimitry Andric   /// Call to derived class to handle relocations. These require
69fe6060f1SDimitry Andric   /// architecture specific knowledge to map to JITLink edge kinds.
70fe6060f1SDimitry Andric   virtual Error addRelocations() = 0;
71fe6060f1SDimitry Andric 
72fe6060f1SDimitry Andric protected:
73fe6060f1SDimitry Andric   using ELFSectionIndex = unsigned;
74fe6060f1SDimitry Andric   using ELFSymbolIndex = unsigned;
75fe6060f1SDimitry Andric 
76fe6060f1SDimitry Andric   bool isRelocatable() const {
77fe6060f1SDimitry Andric     return Obj.getHeader().e_type == llvm::ELF::ET_REL;
78fe6060f1SDimitry Andric   }
79fe6060f1SDimitry Andric 
8004eeddc0SDimitry Andric   void setGraphBlock(ELFSectionIndex SecIndex, Block *B) {
8104eeddc0SDimitry Andric     assert(!GraphBlocks.count(SecIndex) && "Duplicate section at index");
8204eeddc0SDimitry Andric     GraphBlocks[SecIndex] = B;
83fe6060f1SDimitry Andric   }
84fe6060f1SDimitry Andric 
8504eeddc0SDimitry Andric   Block *getGraphBlock(ELFSectionIndex SecIndex) {
8604eeddc0SDimitry Andric     auto I = GraphBlocks.find(SecIndex);
8704eeddc0SDimitry Andric     if (I == GraphBlocks.end())
88fe6060f1SDimitry Andric       return nullptr;
89fe6060f1SDimitry Andric     return I->second;
90fe6060f1SDimitry Andric   }
91fe6060f1SDimitry Andric 
92fe6060f1SDimitry Andric   void setGraphSymbol(ELFSymbolIndex SymIndex, Symbol &Sym) {
93fe6060f1SDimitry Andric     assert(!GraphSymbols.count(SymIndex) && "Duplicate symbol at index");
94fe6060f1SDimitry Andric     GraphSymbols[SymIndex] = &Sym;
95fe6060f1SDimitry Andric   }
96fe6060f1SDimitry Andric 
97fe6060f1SDimitry Andric   Symbol *getGraphSymbol(ELFSymbolIndex SymIndex) {
98fe6060f1SDimitry Andric     auto I = GraphSymbols.find(SymIndex);
99fe6060f1SDimitry Andric     if (I == GraphSymbols.end())
100fe6060f1SDimitry Andric       return nullptr;
101fe6060f1SDimitry Andric     return I->second;
102fe6060f1SDimitry Andric   }
103fe6060f1SDimitry Andric 
104fe6060f1SDimitry Andric   Expected<std::pair<Linkage, Scope>>
105fe6060f1SDimitry Andric   getSymbolLinkageAndScope(const typename ELFT::Sym &Sym, StringRef Name);
106fe6060f1SDimitry Andric 
107fe6060f1SDimitry Andric   Error prepare();
108fe6060f1SDimitry Andric   Error graphifySections();
109fe6060f1SDimitry Andric   Error graphifySymbols();
110fe6060f1SDimitry Andric 
111*bdd1243dSDimitry Andric   /// Traverse all matching ELFT::Rela relocation records in the given section.
112*bdd1243dSDimitry Andric   /// The handler function Func should be callable with this signature:
113349cc55cSDimitry Andric   ///   Error(const typename ELFT::Rela &,
114349cc55cSDimitry Andric   ///         const typename ELFT::Shdr &, Section &)
115349cc55cSDimitry Andric   ///
116*bdd1243dSDimitry Andric   template <typename RelocHandlerMethod>
117*bdd1243dSDimitry Andric   Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,
118*bdd1243dSDimitry Andric                               RelocHandlerMethod &&Func,
119349cc55cSDimitry Andric                               bool ProcessDebugSections = false);
120349cc55cSDimitry Andric 
121*bdd1243dSDimitry Andric   /// Traverse all matching ELFT::Rel relocation records in the given section.
122*bdd1243dSDimitry Andric   /// The handler function Func should be callable with this signature:
123*bdd1243dSDimitry Andric   ///   Error(const typename ELFT::Rel &,
124*bdd1243dSDimitry Andric   ///         const typename ELFT::Shdr &, Section &)
125*bdd1243dSDimitry Andric   ///
126*bdd1243dSDimitry Andric   template <typename RelocHandlerMethod>
127*bdd1243dSDimitry Andric   Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,
128*bdd1243dSDimitry Andric                              RelocHandlerMethod &&Func,
129*bdd1243dSDimitry Andric                              bool ProcessDebugSections = false);
130*bdd1243dSDimitry Andric 
131*bdd1243dSDimitry Andric   /// Traverse all matching rela relocation records in the given section.
132*bdd1243dSDimitry Andric   /// Convenience wrapper to allow passing a member function for the handler.
133349cc55cSDimitry Andric   ///
134349cc55cSDimitry Andric   template <typename ClassT, typename RelocHandlerMethod>
135*bdd1243dSDimitry Andric   Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,
136*bdd1243dSDimitry Andric                               ClassT *Instance, RelocHandlerMethod &&Method,
137349cc55cSDimitry Andric                               bool ProcessDebugSections = false) {
138*bdd1243dSDimitry Andric     return forEachRelaRelocation(
139*bdd1243dSDimitry Andric         RelSect,
140*bdd1243dSDimitry Andric         [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
141*bdd1243dSDimitry Andric           return (Instance->*Method)(Rel, Target, GS);
142*bdd1243dSDimitry Andric         },
143*bdd1243dSDimitry Andric         ProcessDebugSections);
144*bdd1243dSDimitry Andric   }
145*bdd1243dSDimitry Andric 
146*bdd1243dSDimitry Andric   /// Traverse all matching rel relocation records in the given section.
147*bdd1243dSDimitry Andric   /// Convenience wrapper to allow passing a member function for the handler.
148*bdd1243dSDimitry Andric   ///
149*bdd1243dSDimitry Andric   template <typename ClassT, typename RelocHandlerMethod>
150*bdd1243dSDimitry Andric   Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,
151*bdd1243dSDimitry Andric                              ClassT *Instance, RelocHandlerMethod &&Method,
152*bdd1243dSDimitry Andric                              bool ProcessDebugSections = false) {
153*bdd1243dSDimitry Andric     return forEachRelRelocation(
154349cc55cSDimitry Andric         RelSect,
155349cc55cSDimitry Andric         [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
156349cc55cSDimitry Andric           return (Instance->*Method)(Rel, Target, GS);
157349cc55cSDimitry Andric         },
158349cc55cSDimitry Andric         ProcessDebugSections);
159349cc55cSDimitry Andric   }
160349cc55cSDimitry Andric 
161fe6060f1SDimitry Andric   const ELFFile &Obj;
162fe6060f1SDimitry Andric 
163fe6060f1SDimitry Andric   typename ELFFile::Elf_Shdr_Range Sections;
164fe6060f1SDimitry Andric   const typename ELFFile::Elf_Shdr *SymTabSec = nullptr;
165fe6060f1SDimitry Andric   StringRef SectionStringTab;
166fe6060f1SDimitry Andric 
16704eeddc0SDimitry Andric   // Maps ELF section indexes to LinkGraph Blocks.
16804eeddc0SDimitry Andric   // Only SHF_ALLOC sections will have graph blocks.
16904eeddc0SDimitry Andric   DenseMap<ELFSectionIndex, Block *> GraphBlocks;
170fe6060f1SDimitry Andric   DenseMap<ELFSymbolIndex, Symbol *> GraphSymbols;
1714824e7fdSDimitry Andric   DenseMap<const typename ELFFile::Elf_Shdr *,
1724824e7fdSDimitry Andric            ArrayRef<typename ELFFile::Elf_Word>>
1734824e7fdSDimitry Andric       ShndxTables;
174fe6060f1SDimitry Andric };
175fe6060f1SDimitry Andric 
176fe6060f1SDimitry Andric template <typename ELFT>
177fe6060f1SDimitry Andric ELFLinkGraphBuilder<ELFT>::ELFLinkGraphBuilder(
178fe6060f1SDimitry Andric     const ELFFile &Obj, Triple TT, StringRef FileName,
179fe6060f1SDimitry Andric     LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
180fe6060f1SDimitry Andric     : ELFLinkGraphBuilderBase(std::make_unique<LinkGraph>(
181fe6060f1SDimitry Andric           FileName.str(), Triple(std::move(TT)), ELFT::Is64Bits ? 8 : 4,
182fe6060f1SDimitry Andric           support::endianness(ELFT::TargetEndianness),
183fe6060f1SDimitry Andric           std::move(GetEdgeKindName))),
184fe6060f1SDimitry Andric       Obj(Obj) {
185fe6060f1SDimitry Andric   LLVM_DEBUG(
186fe6060f1SDimitry Andric       { dbgs() << "Created ELFLinkGraphBuilder for \"" << FileName << "\""; });
187fe6060f1SDimitry Andric }
188fe6060f1SDimitry Andric 
189fe6060f1SDimitry Andric template <typename ELFT>
190fe6060f1SDimitry Andric Expected<std::unique_ptr<LinkGraph>> ELFLinkGraphBuilder<ELFT>::buildGraph() {
191fe6060f1SDimitry Andric   if (!isRelocatable())
192fe6060f1SDimitry Andric     return make_error<JITLinkError>("Object is not a relocatable ELF file");
193fe6060f1SDimitry Andric 
194fe6060f1SDimitry Andric   if (auto Err = prepare())
195fe6060f1SDimitry Andric     return std::move(Err);
196fe6060f1SDimitry Andric 
197fe6060f1SDimitry Andric   if (auto Err = graphifySections())
198fe6060f1SDimitry Andric     return std::move(Err);
199fe6060f1SDimitry Andric 
200fe6060f1SDimitry Andric   if (auto Err = graphifySymbols())
201fe6060f1SDimitry Andric     return std::move(Err);
202fe6060f1SDimitry Andric 
203fe6060f1SDimitry Andric   if (auto Err = addRelocations())
204fe6060f1SDimitry Andric     return std::move(Err);
205fe6060f1SDimitry Andric 
206fe6060f1SDimitry Andric   return std::move(G);
207fe6060f1SDimitry Andric }
208fe6060f1SDimitry Andric 
209fe6060f1SDimitry Andric template <typename ELFT>
210fe6060f1SDimitry Andric Expected<std::pair<Linkage, Scope>>
211fe6060f1SDimitry Andric ELFLinkGraphBuilder<ELFT>::getSymbolLinkageAndScope(
212fe6060f1SDimitry Andric     const typename ELFT::Sym &Sym, StringRef Name) {
213fe6060f1SDimitry Andric   Linkage L = Linkage::Strong;
214fe6060f1SDimitry Andric   Scope S = Scope::Default;
215fe6060f1SDimitry Andric 
216fe6060f1SDimitry Andric   switch (Sym.getBinding()) {
217fe6060f1SDimitry Andric   case ELF::STB_LOCAL:
218fe6060f1SDimitry Andric     S = Scope::Local;
219fe6060f1SDimitry Andric     break;
220fe6060f1SDimitry Andric   case ELF::STB_GLOBAL:
221fe6060f1SDimitry Andric     // Nothing to do here.
222fe6060f1SDimitry Andric     break;
223fe6060f1SDimitry Andric   case ELF::STB_WEAK:
224349cc55cSDimitry Andric   case ELF::STB_GNU_UNIQUE:
225fe6060f1SDimitry Andric     L = Linkage::Weak;
226fe6060f1SDimitry Andric     break;
227fe6060f1SDimitry Andric   default:
228349cc55cSDimitry Andric     return make_error<StringError>(
229349cc55cSDimitry Andric         "Unrecognized symbol binding " +
230349cc55cSDimitry Andric             Twine(static_cast<int>(Sym.getBinding())) + " for " + Name,
231fe6060f1SDimitry Andric         inconvertibleErrorCode());
232fe6060f1SDimitry Andric   }
233fe6060f1SDimitry Andric 
234fe6060f1SDimitry Andric   switch (Sym.getVisibility()) {
235fe6060f1SDimitry Andric   case ELF::STV_DEFAULT:
236fe6060f1SDimitry Andric   case ELF::STV_PROTECTED:
237fe6060f1SDimitry Andric     // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs
238fe6060f1SDimitry Andric     // Orc support.
239fe6060f1SDimitry Andric     // Otherwise nothing to do here.
240fe6060f1SDimitry Andric     break;
241fe6060f1SDimitry Andric   case ELF::STV_HIDDEN:
242fe6060f1SDimitry Andric     // Default scope -> Hidden scope. No effect on local scope.
243fe6060f1SDimitry Andric     if (S == Scope::Default)
244fe6060f1SDimitry Andric       S = Scope::Hidden;
245fe6060f1SDimitry Andric     break;
246fe6060f1SDimitry Andric   case ELF::STV_INTERNAL:
247349cc55cSDimitry Andric     return make_error<StringError>(
248349cc55cSDimitry Andric         "Unrecognized symbol visibility " +
249349cc55cSDimitry Andric             Twine(static_cast<int>(Sym.getVisibility())) + " for " + Name,
250fe6060f1SDimitry Andric         inconvertibleErrorCode());
251fe6060f1SDimitry Andric   }
252fe6060f1SDimitry Andric 
253fe6060f1SDimitry Andric   return std::make_pair(L, S);
254fe6060f1SDimitry Andric }
255fe6060f1SDimitry Andric 
256fe6060f1SDimitry Andric template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::prepare() {
257fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "  Preparing to build...\n");
258fe6060f1SDimitry Andric 
259fe6060f1SDimitry Andric   // Get the sections array.
260fe6060f1SDimitry Andric   if (auto SectionsOrErr = Obj.sections())
261fe6060f1SDimitry Andric     Sections = *SectionsOrErr;
262fe6060f1SDimitry Andric   else
263fe6060f1SDimitry Andric     return SectionsOrErr.takeError();
264fe6060f1SDimitry Andric 
265fe6060f1SDimitry Andric   // Get the section string table.
266fe6060f1SDimitry Andric   if (auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))
267fe6060f1SDimitry Andric     SectionStringTab = *SectionStringTabOrErr;
268fe6060f1SDimitry Andric   else
269fe6060f1SDimitry Andric     return SectionStringTabOrErr.takeError();
270fe6060f1SDimitry Andric 
271fe6060f1SDimitry Andric   // Get the SHT_SYMTAB section.
2724824e7fdSDimitry Andric   for (auto &Sec : Sections) {
273fe6060f1SDimitry Andric     if (Sec.sh_type == ELF::SHT_SYMTAB) {
274fe6060f1SDimitry Andric       if (!SymTabSec)
275fe6060f1SDimitry Andric         SymTabSec = &Sec;
276fe6060f1SDimitry Andric       else
277fe6060f1SDimitry Andric         return make_error<JITLinkError>("Multiple SHT_SYMTAB sections in " +
278fe6060f1SDimitry Andric                                         G->getName());
279fe6060f1SDimitry Andric     }
280fe6060f1SDimitry Andric 
2814824e7fdSDimitry Andric     // Extended table.
2824824e7fdSDimitry Andric     if (Sec.sh_type == ELF::SHT_SYMTAB_SHNDX) {
2834824e7fdSDimitry Andric       uint32_t SymtabNdx = Sec.sh_link;
2844824e7fdSDimitry Andric       if (SymtabNdx >= Sections.size())
2854824e7fdSDimitry Andric         return make_error<JITLinkError>("sh_link is out of bound");
2864824e7fdSDimitry Andric 
2874824e7fdSDimitry Andric       auto ShndxTable = Obj.getSHNDXTable(Sec);
2884824e7fdSDimitry Andric       if (!ShndxTable)
2894824e7fdSDimitry Andric         return ShndxTable.takeError();
2904824e7fdSDimitry Andric 
2914824e7fdSDimitry Andric       ShndxTables.insert({&Sections[SymtabNdx], *ShndxTable});
2924824e7fdSDimitry Andric     }
2934824e7fdSDimitry Andric   }
2944824e7fdSDimitry Andric 
295fe6060f1SDimitry Andric   return Error::success();
296fe6060f1SDimitry Andric }
297fe6060f1SDimitry Andric 
298fe6060f1SDimitry Andric template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() {
299fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "  Creating graph sections...\n");
300fe6060f1SDimitry Andric 
301fe6060f1SDimitry Andric   // For each section...
302fe6060f1SDimitry Andric   for (ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {
303fe6060f1SDimitry Andric 
304fe6060f1SDimitry Andric     auto &Sec = Sections[SecIndex];
305fe6060f1SDimitry Andric 
306fe6060f1SDimitry Andric     // Start by getting the section name.
307fe6060f1SDimitry Andric     auto Name = Obj.getSectionName(Sec, SectionStringTab);
308fe6060f1SDimitry Andric     if (!Name)
309fe6060f1SDimitry Andric       return Name.takeError();
310fe6060f1SDimitry Andric 
311fe6060f1SDimitry Andric     // If the name indicates that it's a debug section then skip it: We don't
312fe6060f1SDimitry Andric     // support those yet.
313fe6060f1SDimitry Andric     if (isDwarfSection(*Name)) {
314fe6060f1SDimitry Andric       LLVM_DEBUG({
315fe6060f1SDimitry Andric         dbgs() << "    " << SecIndex << ": \"" << *Name
316fe6060f1SDimitry Andric                << "\" is a debug section: "
317fe6060f1SDimitry Andric                   "No graph section will be created.\n";
318fe6060f1SDimitry Andric       });
319fe6060f1SDimitry Andric       continue;
320fe6060f1SDimitry Andric     }
321fe6060f1SDimitry Andric 
322fe6060f1SDimitry Andric     // Skip non-SHF_ALLOC sections
323fe6060f1SDimitry Andric     if (!(Sec.sh_flags & ELF::SHF_ALLOC)) {
324fe6060f1SDimitry Andric       LLVM_DEBUG({
325fe6060f1SDimitry Andric         dbgs() << "    " << SecIndex << ": \"" << *Name
326fe6060f1SDimitry Andric                << "\" is not an SHF_ALLOC section: "
327fe6060f1SDimitry Andric                   "No graph section will be created.\n";
328fe6060f1SDimitry Andric       });
329fe6060f1SDimitry Andric       continue;
330fe6060f1SDimitry Andric     }
331fe6060f1SDimitry Andric 
332fe6060f1SDimitry Andric     LLVM_DEBUG({
333fe6060f1SDimitry Andric       dbgs() << "    " << SecIndex << ": Creating section for \"" << *Name
334fe6060f1SDimitry Andric              << "\"\n";
335fe6060f1SDimitry Andric     });
336fe6060f1SDimitry Andric 
337fe6060f1SDimitry Andric     // Get the section's memory protection flags.
338*bdd1243dSDimitry Andric     orc::MemProt Prot;
339fe6060f1SDimitry Andric     if (Sec.sh_flags & ELF::SHF_EXECINSTR)
340*bdd1243dSDimitry Andric       Prot = orc::MemProt::Read | orc::MemProt::Exec;
341fe6060f1SDimitry Andric     else
342*bdd1243dSDimitry Andric       Prot = orc::MemProt::Read | orc::MemProt::Write;
343fe6060f1SDimitry Andric 
34404eeddc0SDimitry Andric     // Look for existing sections first.
34504eeddc0SDimitry Andric     auto *GraphSec = G->findSectionByName(*Name);
34604eeddc0SDimitry Andric     if (!GraphSec)
34704eeddc0SDimitry Andric       GraphSec = &G->createSection(*Name, Prot);
34804eeddc0SDimitry Andric     assert(GraphSec->getMemProt() == Prot && "MemProt should match");
34904eeddc0SDimitry Andric 
35004eeddc0SDimitry Andric     Block *B = nullptr;
351fe6060f1SDimitry Andric     if (Sec.sh_type != ELF::SHT_NOBITS) {
352fe6060f1SDimitry Andric       auto Data = Obj.template getSectionContentsAsArray<char>(Sec);
353fe6060f1SDimitry Andric       if (!Data)
354fe6060f1SDimitry Andric         return Data.takeError();
355fe6060f1SDimitry Andric 
35604eeddc0SDimitry Andric       B = &G->createContentBlock(*GraphSec, *Data,
35704eeddc0SDimitry Andric                                  orc::ExecutorAddr(Sec.sh_addr),
35804eeddc0SDimitry Andric                                  Sec.sh_addralign, 0);
359fe6060f1SDimitry Andric     } else
36004eeddc0SDimitry Andric       B = &G->createZeroFillBlock(*GraphSec, Sec.sh_size,
36104eeddc0SDimitry Andric                                   orc::ExecutorAddr(Sec.sh_addr),
362fe6060f1SDimitry Andric                                   Sec.sh_addralign, 0);
363fe6060f1SDimitry Andric 
36404eeddc0SDimitry Andric     setGraphBlock(SecIndex, B);
365fe6060f1SDimitry Andric   }
366fe6060f1SDimitry Andric 
367fe6060f1SDimitry Andric   return Error::success();
368fe6060f1SDimitry Andric }
369fe6060f1SDimitry Andric 
370fe6060f1SDimitry Andric template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
371fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "  Creating graph symbols...\n");
372fe6060f1SDimitry Andric 
373fe6060f1SDimitry Andric   // No SYMTAB -- Bail out early.
374fe6060f1SDimitry Andric   if (!SymTabSec)
375fe6060f1SDimitry Andric     return Error::success();
376fe6060f1SDimitry Andric 
377fe6060f1SDimitry Andric   // Get the section content as a Symbols array.
378fe6060f1SDimitry Andric   auto Symbols = Obj.symbols(SymTabSec);
379fe6060f1SDimitry Andric   if (!Symbols)
380fe6060f1SDimitry Andric     return Symbols.takeError();
381fe6060f1SDimitry Andric 
382fe6060f1SDimitry Andric   // Get the string table for this section.
383fe6060f1SDimitry Andric   auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
384fe6060f1SDimitry Andric   if (!StringTab)
385fe6060f1SDimitry Andric     return StringTab.takeError();
386fe6060f1SDimitry Andric 
387fe6060f1SDimitry Andric   LLVM_DEBUG({
388fe6060f1SDimitry Andric     StringRef SymTabName;
389fe6060f1SDimitry Andric 
390fe6060f1SDimitry Andric     if (auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
391fe6060f1SDimitry Andric       SymTabName = *SymTabNameOrErr;
392fe6060f1SDimitry Andric     else {
393fe6060f1SDimitry Andric       dbgs() << "Could not get ELF SHT_SYMTAB section name for logging: "
394fe6060f1SDimitry Andric              << toString(SymTabNameOrErr.takeError()) << "\n";
395fe6060f1SDimitry Andric       SymTabName = "<SHT_SYMTAB section with invalid name>";
396fe6060f1SDimitry Andric     }
397fe6060f1SDimitry Andric 
398fe6060f1SDimitry Andric     dbgs() << "    Adding symbols from symtab section \"" << SymTabName
399fe6060f1SDimitry Andric            << "\"\n";
400fe6060f1SDimitry Andric   });
401fe6060f1SDimitry Andric 
402fe6060f1SDimitry Andric   for (ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
403fe6060f1SDimitry Andric     auto &Sym = (*Symbols)[SymIndex];
404fe6060f1SDimitry Andric 
405fe6060f1SDimitry Andric     // Check symbol type.
406fe6060f1SDimitry Andric     switch (Sym.getType()) {
407fe6060f1SDimitry Andric     case ELF::STT_FILE:
408fe6060f1SDimitry Andric       LLVM_DEBUG({
409fe6060f1SDimitry Andric         if (auto Name = Sym.getName(*StringTab))
410fe6060f1SDimitry Andric           dbgs() << "      " << SymIndex << ": Skipping STT_FILE symbol \""
411fe6060f1SDimitry Andric                  << *Name << "\"\n";
412fe6060f1SDimitry Andric         else {
413fe6060f1SDimitry Andric           dbgs() << "Could not get STT_FILE symbol name: "
414fe6060f1SDimitry Andric                  << toString(Name.takeError()) << "\n";
415fe6060f1SDimitry Andric           dbgs() << "     " << SymIndex
416fe6060f1SDimitry Andric                  << ": Skipping STT_FILE symbol with invalid name\n";
417fe6060f1SDimitry Andric         }
418fe6060f1SDimitry Andric       });
419fe6060f1SDimitry Andric       continue;
420fe6060f1SDimitry Andric       break;
421fe6060f1SDimitry Andric     }
422fe6060f1SDimitry Andric 
423fe6060f1SDimitry Andric     // Get the symbol name.
424fe6060f1SDimitry Andric     auto Name = Sym.getName(*StringTab);
425fe6060f1SDimitry Andric     if (!Name)
426fe6060f1SDimitry Andric       return Name.takeError();
427fe6060f1SDimitry Andric 
428fe6060f1SDimitry Andric     // Handle common symbols specially.
429fe6060f1SDimitry Andric     if (Sym.isCommon()) {
430*bdd1243dSDimitry Andric       Symbol &GSym = G->addDefinedSymbol(
431*bdd1243dSDimitry Andric           G->createZeroFillBlock(getCommonSection(), Sym.st_size,
432*bdd1243dSDimitry Andric                                  orc::ExecutorAddr(), Sym.getValue(), 0),
433*bdd1243dSDimitry Andric           0, *Name, Sym.st_size, Linkage::Strong, Scope::Default, false, false);
434fe6060f1SDimitry Andric       setGraphSymbol(SymIndex, GSym);
435fe6060f1SDimitry Andric       continue;
436fe6060f1SDimitry Andric     }
437fe6060f1SDimitry Andric 
438fe6060f1SDimitry Andric     if (Sym.isDefined() &&
439fe6060f1SDimitry Andric         (Sym.getType() == ELF::STT_NOTYPE || Sym.getType() == ELF::STT_FUNC ||
440fe6060f1SDimitry Andric          Sym.getType() == ELF::STT_OBJECT ||
441349cc55cSDimitry Andric          Sym.getType() == ELF::STT_SECTION || Sym.getType() == ELF::STT_TLS)) {
442*bdd1243dSDimitry Andric 
443*bdd1243dSDimitry Andric       // Map Visibility and Binding to Scope and Linkage:
444*bdd1243dSDimitry Andric       Linkage L;
445*bdd1243dSDimitry Andric       Scope S;
446*bdd1243dSDimitry Andric       if (auto LSOrErr = getSymbolLinkageAndScope(Sym, *Name))
447*bdd1243dSDimitry Andric         std::tie(L, S) = *LSOrErr;
448*bdd1243dSDimitry Andric       else
449*bdd1243dSDimitry Andric         return LSOrErr.takeError();
450*bdd1243dSDimitry Andric 
4514824e7fdSDimitry Andric       // Handle extended tables.
4524824e7fdSDimitry Andric       unsigned Shndx = Sym.st_shndx;
4534824e7fdSDimitry Andric       if (Shndx == ELF::SHN_XINDEX) {
4544824e7fdSDimitry Andric         auto ShndxTable = ShndxTables.find(SymTabSec);
4554824e7fdSDimitry Andric         if (ShndxTable == ShndxTables.end())
4564824e7fdSDimitry Andric           continue;
4574824e7fdSDimitry Andric         auto NdxOrErr = object::getExtendedSymbolTableIndex<ELFT>(
4584824e7fdSDimitry Andric             Sym, SymIndex, ShndxTable->second);
4594824e7fdSDimitry Andric         if (!NdxOrErr)
4604824e7fdSDimitry Andric           return NdxOrErr.takeError();
4614824e7fdSDimitry Andric         Shndx = *NdxOrErr;
4624824e7fdSDimitry Andric       }
46304eeddc0SDimitry Andric       if (auto *B = getGraphBlock(Shndx)) {
464fe6060f1SDimitry Andric         LLVM_DEBUG({
465fe6060f1SDimitry Andric           dbgs() << "      " << SymIndex
466fe6060f1SDimitry Andric                  << ": Creating defined graph symbol for ELF symbol \"" << *Name
467fe6060f1SDimitry Andric                  << "\"\n";
468fe6060f1SDimitry Andric         });
469fe6060f1SDimitry Andric 
47004eeddc0SDimitry Andric         // In RISCV, temporary symbols (Used to generate dwarf, eh_frame
47104eeddc0SDimitry Andric         // sections...) will appear in object code's symbol table, and LLVM does
47204eeddc0SDimitry Andric         // not use names on these temporary symbols (RISCV gnu toolchain uses
47304eeddc0SDimitry Andric         // names on these temporary symbols). If the symbol is unnamed, add an
47404eeddc0SDimitry Andric         // anonymous symbol.
475fe6060f1SDimitry Andric         auto &GSym =
47604eeddc0SDimitry Andric             Name->empty()
47704eeddc0SDimitry Andric                 ? G->addAnonymousSymbol(*B, Sym.getValue(), Sym.st_size,
47804eeddc0SDimitry Andric                                         false, false)
47904eeddc0SDimitry Andric                 : G->addDefinedSymbol(*B, Sym.getValue(), *Name, Sym.st_size, L,
48004eeddc0SDimitry Andric                                       S, Sym.getType() == ELF::STT_FUNC, false);
481fe6060f1SDimitry Andric         setGraphSymbol(SymIndex, GSym);
482fe6060f1SDimitry Andric       }
483fe6060f1SDimitry Andric     } else if (Sym.isUndefined() && Sym.isExternal()) {
484fe6060f1SDimitry Andric       LLVM_DEBUG({
485fe6060f1SDimitry Andric         dbgs() << "      " << SymIndex
486fe6060f1SDimitry Andric                << ": Creating external graph symbol for ELF symbol \"" << *Name
487fe6060f1SDimitry Andric                << "\"\n";
488fe6060f1SDimitry Andric       });
489*bdd1243dSDimitry Andric 
490*bdd1243dSDimitry Andric       if (Sym.getBinding() != ELF::STB_GLOBAL &&
491*bdd1243dSDimitry Andric           Sym.getBinding() != ELF::STB_WEAK)
492*bdd1243dSDimitry Andric         return make_error<StringError>(
493*bdd1243dSDimitry Andric             "Invalid symbol binding " +
494*bdd1243dSDimitry Andric                 Twine(static_cast<int>(Sym.getBinding())) +
495*bdd1243dSDimitry Andric                 " for external symbol " + *Name,
496*bdd1243dSDimitry Andric             inconvertibleErrorCode());
497*bdd1243dSDimitry Andric 
498*bdd1243dSDimitry Andric       // If L is Linkage::Weak that means this is a weakly referenced symbol.
499*bdd1243dSDimitry Andric       auto &GSym = G->addExternalSymbol(*Name, Sym.st_size,
500*bdd1243dSDimitry Andric                                         Sym.getBinding() == ELF::STB_WEAK);
501fe6060f1SDimitry Andric       setGraphSymbol(SymIndex, GSym);
502fe6060f1SDimitry Andric     } else {
503fe6060f1SDimitry Andric       LLVM_DEBUG({
504fe6060f1SDimitry Andric         dbgs() << "      " << SymIndex
505fe6060f1SDimitry Andric                << ": Not creating graph symbol for ELF symbol \"" << *Name
506fe6060f1SDimitry Andric                << "\" with unrecognized type\n";
507fe6060f1SDimitry Andric       });
508fe6060f1SDimitry Andric     }
509fe6060f1SDimitry Andric   }
510fe6060f1SDimitry Andric 
511fe6060f1SDimitry Andric   return Error::success();
512fe6060f1SDimitry Andric }
513fe6060f1SDimitry Andric 
514349cc55cSDimitry Andric template <typename ELFT>
515349cc55cSDimitry Andric template <typename RelocHandlerFunction>
516*bdd1243dSDimitry Andric Error ELFLinkGraphBuilder<ELFT>::forEachRelaRelocation(
517349cc55cSDimitry Andric     const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func,
518349cc55cSDimitry Andric     bool ProcessDebugSections) {
519349cc55cSDimitry Andric   // Only look into sections that store relocation entries.
520*bdd1243dSDimitry Andric   if (RelSect.sh_type != ELF::SHT_RELA)
521349cc55cSDimitry Andric     return Error::success();
522349cc55cSDimitry Andric 
523349cc55cSDimitry Andric   // sh_info contains the section header index of the target (FixupSection),
524349cc55cSDimitry Andric   // which is the section to which all relocations in RelSect apply.
525349cc55cSDimitry Andric   auto FixupSection = Obj.getSection(RelSect.sh_info);
526349cc55cSDimitry Andric   if (!FixupSection)
527349cc55cSDimitry Andric     return FixupSection.takeError();
528349cc55cSDimitry Andric 
529349cc55cSDimitry Andric   // Target sections have names in valid ELF object files.
530349cc55cSDimitry Andric   Expected<StringRef> Name = Obj.getSectionName(**FixupSection);
531349cc55cSDimitry Andric   if (!Name)
532349cc55cSDimitry Andric     return Name.takeError();
533349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "  " << *Name << ":\n");
534349cc55cSDimitry Andric 
535349cc55cSDimitry Andric   // Consider skipping these relocations.
536349cc55cSDimitry Andric   if (!ProcessDebugSections && isDwarfSection(*Name)) {
537349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "    skipped (dwarf section)\n\n");
538349cc55cSDimitry Andric     return Error::success();
539349cc55cSDimitry Andric   }
540349cc55cSDimitry Andric 
541349cc55cSDimitry Andric   // Lookup the link-graph node corresponding to the target section name.
54204eeddc0SDimitry Andric   auto *BlockToFix = getGraphBlock(RelSect.sh_info);
54304eeddc0SDimitry Andric   if (!BlockToFix)
544349cc55cSDimitry Andric     return make_error<StringError>(
545349cc55cSDimitry Andric         "Refencing a section that wasn't added to the graph: " + *Name,
546349cc55cSDimitry Andric         inconvertibleErrorCode());
547349cc55cSDimitry Andric 
548349cc55cSDimitry Andric   auto RelEntries = Obj.relas(RelSect);
549349cc55cSDimitry Andric   if (!RelEntries)
550349cc55cSDimitry Andric     return RelEntries.takeError();
551349cc55cSDimitry Andric 
552349cc55cSDimitry Andric   // Let the callee process relocation entries one by one.
553349cc55cSDimitry Andric   for (const typename ELFT::Rela &R : *RelEntries)
55404eeddc0SDimitry Andric     if (Error Err = Func(R, **FixupSection, *BlockToFix))
555349cc55cSDimitry Andric       return Err;
556349cc55cSDimitry Andric 
557349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "\n");
558349cc55cSDimitry Andric   return Error::success();
559349cc55cSDimitry Andric }
560349cc55cSDimitry Andric 
561*bdd1243dSDimitry Andric template <typename ELFT>
562*bdd1243dSDimitry Andric template <typename RelocHandlerFunction>
563*bdd1243dSDimitry Andric Error ELFLinkGraphBuilder<ELFT>::forEachRelRelocation(
564*bdd1243dSDimitry Andric     const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func,
565*bdd1243dSDimitry Andric     bool ProcessDebugSections) {
566*bdd1243dSDimitry Andric   // Only look into sections that store relocation entries.
567*bdd1243dSDimitry Andric   if (RelSect.sh_type != ELF::SHT_REL)
568*bdd1243dSDimitry Andric     return Error::success();
569*bdd1243dSDimitry Andric 
570*bdd1243dSDimitry Andric   // sh_info contains the section header index of the target (FixupSection),
571*bdd1243dSDimitry Andric   // which is the section to which all relocations in RelSect apply.
572*bdd1243dSDimitry Andric   auto FixupSection = Obj.getSection(RelSect.sh_info);
573*bdd1243dSDimitry Andric   if (!FixupSection)
574*bdd1243dSDimitry Andric     return FixupSection.takeError();
575*bdd1243dSDimitry Andric 
576*bdd1243dSDimitry Andric   // Target sections have names in valid ELF object files.
577*bdd1243dSDimitry Andric   Expected<StringRef> Name = Obj.getSectionName(**FixupSection);
578*bdd1243dSDimitry Andric   if (!Name)
579*bdd1243dSDimitry Andric     return Name.takeError();
580*bdd1243dSDimitry Andric   LLVM_DEBUG(dbgs() << "  " << *Name << ":\n");
581*bdd1243dSDimitry Andric 
582*bdd1243dSDimitry Andric   // Consider skipping these relocations.
583*bdd1243dSDimitry Andric   if (!ProcessDebugSections && isDwarfSection(*Name)) {
584*bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "    skipped (dwarf section)\n\n");
585*bdd1243dSDimitry Andric     return Error::success();
586*bdd1243dSDimitry Andric   }
587*bdd1243dSDimitry Andric 
588*bdd1243dSDimitry Andric   // Lookup the link-graph node corresponding to the target section name.
589*bdd1243dSDimitry Andric   auto *BlockToFix = getGraphBlock(RelSect.sh_info);
590*bdd1243dSDimitry Andric   if (!BlockToFix)
591*bdd1243dSDimitry Andric     return make_error<StringError>(
592*bdd1243dSDimitry Andric         "Refencing a section that wasn't added to the graph: " + *Name,
593*bdd1243dSDimitry Andric         inconvertibleErrorCode());
594*bdd1243dSDimitry Andric 
595*bdd1243dSDimitry Andric   auto RelEntries = Obj.rels(RelSect);
596*bdd1243dSDimitry Andric   if (!RelEntries)
597*bdd1243dSDimitry Andric     return RelEntries.takeError();
598*bdd1243dSDimitry Andric 
599*bdd1243dSDimitry Andric   // Let the callee process relocation entries one by one.
600*bdd1243dSDimitry Andric   for (const typename ELFT::Rel &R : *RelEntries)
601*bdd1243dSDimitry Andric     if (Error Err = Func(R, **FixupSection, *BlockToFix))
602*bdd1243dSDimitry Andric       return Err;
603*bdd1243dSDimitry Andric 
604*bdd1243dSDimitry Andric   LLVM_DEBUG(dbgs() << "\n");
605*bdd1243dSDimitry Andric   return Error::success();
606*bdd1243dSDimitry Andric }
607*bdd1243dSDimitry Andric 
608fe6060f1SDimitry Andric } // end namespace jitlink
609fe6060f1SDimitry Andric } // end namespace llvm
610fe6060f1SDimitry Andric 
611fe6060f1SDimitry Andric #undef DEBUG_TYPE
612fe6060f1SDimitry Andric 
613fe6060f1SDimitry Andric #endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
614