xref: /llvm-project/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h (revision 4eaff6c58ae2f130ac8d63cf2c87bbb483114876)
1aff57ff2SLang Hames //===------- ELFLinkGraphBuilder.h - ELF LinkGraph builder ------*- C++ -*-===//
2aff57ff2SLang Hames //
3aff57ff2SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4aff57ff2SLang Hames // See https://llvm.org/LICENSE.txt for license information.
5aff57ff2SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6aff57ff2SLang Hames //
7aff57ff2SLang Hames //===----------------------------------------------------------------------===//
8aff57ff2SLang Hames //
9aff57ff2SLang Hames // Generic ELF LinkGraph building code.
10aff57ff2SLang Hames //
11aff57ff2SLang Hames //===----------------------------------------------------------------------===//
12aff57ff2SLang Hames 
13aff57ff2SLang Hames #ifndef LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
14aff57ff2SLang Hames #define LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
15aff57ff2SLang Hames 
16aff57ff2SLang Hames #include "llvm/ExecutionEngine/JITLink/JITLink.h"
17aff57ff2SLang Hames #include "llvm/Object/ELF.h"
188e66fc43SLang Hames #include "llvm/Support/Debug.h"
19aff57ff2SLang Hames #include "llvm/Support/Error.h"
208e66fc43SLang Hames #include "llvm/Support/FormatVariadic.h"
218e66fc43SLang Hames 
228e66fc43SLang Hames #define DEBUG_TYPE "jitlink"
23aff57ff2SLang Hames 
24aff57ff2SLang Hames namespace llvm {
25aff57ff2SLang Hames namespace jitlink {
26aff57ff2SLang Hames 
27aff57ff2SLang Hames /// Common link-graph building code shared between all ELFFiles.
28aff57ff2SLang Hames class ELFLinkGraphBuilderBase {
29aff57ff2SLang Hames public:
308e66fc43SLang Hames   ELFLinkGraphBuilderBase(std::unique_ptr<LinkGraph> G) : G(std::move(G)) {}
31aff57ff2SLang Hames   virtual ~ELFLinkGraphBuilderBase();
328e66fc43SLang Hames 
338e66fc43SLang Hames protected:
348e66fc43SLang Hames   static bool isDwarfSection(StringRef SectionName) {
358e66fc43SLang Hames     return llvm::is_contained(DwarfSectionNames, SectionName);
368e66fc43SLang Hames   }
378e66fc43SLang Hames 
388e66fc43SLang Hames   Section &getCommonSection() {
39962a2479SLang Hames     if (!CommonSection)
40d3d9f7caSLang Hames       CommonSection = &G->createSection(
41d3d9f7caSLang Hames           CommonSectionName, orc::MemProt::Read | orc::MemProt::Write);
428e66fc43SLang Hames     return *CommonSection;
438e66fc43SLang Hames   }
448e66fc43SLang Hames 
458e66fc43SLang Hames   std::unique_ptr<LinkGraph> G;
468e66fc43SLang Hames 
478e66fc43SLang Hames private:
488e66fc43SLang Hames   static StringRef CommonSectionName;
498e66fc43SLang Hames   static ArrayRef<const char *> DwarfSectionNames;
508e66fc43SLang Hames 
518e66fc43SLang Hames   Section *CommonSection = nullptr;
52aff57ff2SLang Hames };
53aff57ff2SLang Hames 
5494239712SEymen Ünay /// LinkGraph building code that's specific to the given ELFT, but common
55aff57ff2SLang Hames /// across all architectures.
56aff57ff2SLang Hames template <typename ELFT>
57aff57ff2SLang Hames class ELFLinkGraphBuilder : public ELFLinkGraphBuilderBase {
588e66fc43SLang Hames   using ELFFile = object::ELFFile<ELFT>;
598e66fc43SLang Hames 
60aff57ff2SLang Hames public:
612ccf7ed2SJared Wyles   ELFLinkGraphBuilder(const object::ELFFile<ELFT> &Obj,
622ccf7ed2SJared Wyles                       std::shared_ptr<orc::SymbolStringPool> SSP, Triple TT,
6352b88457SJob Noorman                       SubtargetFeatures Features, StringRef FileName,
64aff57ff2SLang Hames                       LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
65aff57ff2SLang Hames 
66f05ac803SLang Hames   /// Debug sections are included in the graph by default. Use
67f05ac803SLang Hames   /// setProcessDebugSections(false) to ignore them if debug info is not
68f05ac803SLang Hames   /// needed.
69f05ac803SLang Hames   ELFLinkGraphBuilder &setProcessDebugSections(bool ProcessDebugSections) {
70f05ac803SLang Hames     this->ProcessDebugSections = ProcessDebugSections;
71f05ac803SLang Hames     return *this;
72f05ac803SLang Hames   }
73f05ac803SLang Hames 
748e66fc43SLang Hames   /// Attempt to construct and return the LinkGraph.
758e66fc43SLang Hames   Expected<std::unique_ptr<LinkGraph>> buildGraph();
768e66fc43SLang Hames 
778e66fc43SLang Hames   /// Call to derived class to handle relocations. These require
788e66fc43SLang Hames   /// architecture specific knowledge to map to JITLink edge kinds.
798e66fc43SLang Hames   virtual Error addRelocations() = 0;
808e66fc43SLang Hames 
81aff57ff2SLang Hames protected:
828e66fc43SLang Hames   using ELFSectionIndex = unsigned;
838e66fc43SLang Hames   using ELFSymbolIndex = unsigned;
848e66fc43SLang Hames 
858e66fc43SLang Hames   bool isRelocatable() const {
868e66fc43SLang Hames     return Obj.getHeader().e_type == llvm::ELF::ET_REL;
878e66fc43SLang Hames   }
888e66fc43SLang Hames 
89091e3648SSteven Wu   void setGraphBlock(ELFSectionIndex SecIndex, Block *B) {
90091e3648SSteven Wu     assert(!GraphBlocks.count(SecIndex) && "Duplicate section at index");
91091e3648SSteven Wu     GraphBlocks[SecIndex] = B;
928e66fc43SLang Hames   }
938e66fc43SLang Hames 
94091e3648SSteven Wu   Block *getGraphBlock(ELFSectionIndex SecIndex) {
95c963892aSKazu Hirata     return GraphBlocks.lookup(SecIndex);
968e66fc43SLang Hames   }
978e66fc43SLang Hames 
988e66fc43SLang Hames   void setGraphSymbol(ELFSymbolIndex SymIndex, Symbol &Sym) {
998e66fc43SLang Hames     assert(!GraphSymbols.count(SymIndex) && "Duplicate symbol at index");
1008e66fc43SLang Hames     GraphSymbols[SymIndex] = &Sym;
1018e66fc43SLang Hames   }
1028e66fc43SLang Hames 
1038e66fc43SLang Hames   Symbol *getGraphSymbol(ELFSymbolIndex SymIndex) {
104c963892aSKazu Hirata     return GraphSymbols.lookup(SymIndex);
1058e66fc43SLang Hames   }
1068e66fc43SLang Hames 
1078e66fc43SLang Hames   Expected<std::pair<Linkage, Scope>>
1088e66fc43SLang Hames   getSymbolLinkageAndScope(const typename ELFT::Sym &Sym, StringRef Name);
1098e66fc43SLang Hames 
110cf8dc9dfSStefan Gränitz   /// Set the target flags on the given Symbol.
111cf8dc9dfSStefan Gränitz   virtual TargetFlagsType makeTargetFlags(const typename ELFT::Sym &Sym) {
112cf8dc9dfSStefan Gränitz     return TargetFlagsType{};
113cf8dc9dfSStefan Gränitz   }
114cf8dc9dfSStefan Gränitz 
115cf8dc9dfSStefan Gränitz   /// Get the physical offset of the symbol on the target platform.
116cf8dc9dfSStefan Gränitz   virtual orc::ExecutorAddrDiff getRawOffset(const typename ELFT::Sym &Sym,
117cf8dc9dfSStefan Gränitz                                              TargetFlagsType Flags) {
118cf8dc9dfSStefan Gränitz     return Sym.getValue();
119cf8dc9dfSStefan Gränitz   }
120cf8dc9dfSStefan Gränitz 
1218e66fc43SLang Hames   Error prepare();
1228e66fc43SLang Hames   Error graphifySections();
1238e66fc43SLang Hames   Error graphifySymbols();
1248e66fc43SLang Hames 
1255c1d160cSStefan Gränitz   /// Override in derived classes to suppress certain sections in the link
1265c1d160cSStefan Gränitz   /// graph.
1275c1d160cSStefan Gränitz   virtual bool excludeSection(const typename ELFT::Shdr &Sect) const {
1285c1d160cSStefan Gränitz     return false;
1295c1d160cSStefan Gränitz   }
1305c1d160cSStefan Gränitz 
1312a3b257aSKshitij Jain   /// Traverse all matching ELFT::Rela relocation records in the given section.
1322a3b257aSKshitij Jain   /// The handler function Func should be callable with this signature:
13396918515SStefan Gränitz   ///   Error(const typename ELFT::Rela &,
13496918515SStefan Gränitz   ///         const typename ELFT::Shdr &, Section &)
13596918515SStefan Gränitz   ///
1362a3b257aSKshitij Jain   template <typename RelocHandlerMethod>
1372a3b257aSKshitij Jain   Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,
138f05ac803SLang Hames                               RelocHandlerMethod &&Func);
13996918515SStefan Gränitz 
1402a3b257aSKshitij Jain   /// Traverse all matching ELFT::Rel relocation records in the given section.
1412a3b257aSKshitij Jain   /// The handler function Func should be callable with this signature:
1422a3b257aSKshitij Jain   ///   Error(const typename ELFT::Rel &,
1432a3b257aSKshitij Jain   ///         const typename ELFT::Shdr &, Section &)
1442a3b257aSKshitij Jain   ///
1452a3b257aSKshitij Jain   template <typename RelocHandlerMethod>
1462a3b257aSKshitij Jain   Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,
147f05ac803SLang Hames                              RelocHandlerMethod &&Func);
1482a3b257aSKshitij Jain 
1492a3b257aSKshitij Jain   /// Traverse all matching rela relocation records in the given section.
1502a3b257aSKshitij Jain   /// Convenience wrapper to allow passing a member function for the handler.
15196918515SStefan Gränitz   ///
15296918515SStefan Gränitz   template <typename ClassT, typename RelocHandlerMethod>
1532a3b257aSKshitij Jain   Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,
154f05ac803SLang Hames                               ClassT *Instance, RelocHandlerMethod &&Method) {
1552a3b257aSKshitij Jain     return forEachRelaRelocation(
1562a3b257aSKshitij Jain         RelSect,
1572a3b257aSKshitij Jain         [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
1582a3b257aSKshitij Jain           return (Instance->*Method)(Rel, Target, GS);
159f05ac803SLang Hames         });
1602a3b257aSKshitij Jain   }
1612a3b257aSKshitij Jain 
1622a3b257aSKshitij Jain   /// Traverse all matching rel relocation records in the given section.
1632a3b257aSKshitij Jain   /// Convenience wrapper to allow passing a member function for the handler.
1642a3b257aSKshitij Jain   ///
1652a3b257aSKshitij Jain   template <typename ClassT, typename RelocHandlerMethod>
1662a3b257aSKshitij Jain   Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,
167f05ac803SLang Hames                              ClassT *Instance, RelocHandlerMethod &&Method) {
1682a3b257aSKshitij Jain     return forEachRelRelocation(
16996918515SStefan Gränitz         RelSect,
17096918515SStefan Gränitz         [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
17196918515SStefan Gränitz           return (Instance->*Method)(Rel, Target, GS);
172f05ac803SLang Hames         });
17396918515SStefan Gränitz   }
17496918515SStefan Gränitz 
1758e66fc43SLang Hames   const ELFFile &Obj;
1768e66fc43SLang Hames 
1778e66fc43SLang Hames   typename ELFFile::Elf_Shdr_Range Sections;
1788e66fc43SLang Hames   const typename ELFFile::Elf_Shdr *SymTabSec = nullptr;
1798e66fc43SLang Hames   StringRef SectionStringTab;
180f05ac803SLang Hames   bool ProcessDebugSections = true;
1818e66fc43SLang Hames 
182091e3648SSteven Wu   // Maps ELF section indexes to LinkGraph Blocks.
183091e3648SSteven Wu   // Only SHF_ALLOC sections will have graph blocks.
184091e3648SSteven Wu   DenseMap<ELFSectionIndex, Block *> GraphBlocks;
1858e66fc43SLang Hames   DenseMap<ELFSymbolIndex, Symbol *> GraphSymbols;
1865e3200f3SSteven Wu   DenseMap<const typename ELFFile::Elf_Shdr *,
1875e3200f3SSteven Wu            ArrayRef<typename ELFFile::Elf_Word>>
1885e3200f3SSteven Wu       ShndxTables;
189aff57ff2SLang Hames };
190aff57ff2SLang Hames 
191aff57ff2SLang Hames template <typename ELFT>
192aff57ff2SLang Hames ELFLinkGraphBuilder<ELFT>::ELFLinkGraphBuilder(
1932ccf7ed2SJared Wyles     const ELFFile &Obj, std::shared_ptr<orc::SymbolStringPool> SSP, Triple TT,
1942ccf7ed2SJared Wyles     SubtargetFeatures Features, StringRef FileName,
1952ccf7ed2SJared Wyles     LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
1968e66fc43SLang Hames     : ELFLinkGraphBuilderBase(std::make_unique<LinkGraph>(
197*4eaff6c5SLang Hames           FileName.str(), std::move(SSP), std::move(TT), std::move(Features),
198*4eaff6c5SLang Hames           std::move(GetEdgeKindName))),
1998e66fc43SLang Hames       Obj(Obj) {
2008e66fc43SLang Hames   LLVM_DEBUG(
2018e66fc43SLang Hames       { dbgs() << "Created ELFLinkGraphBuilder for \"" << FileName << "\""; });
2028e66fc43SLang Hames }
2038e66fc43SLang Hames 
2048e66fc43SLang Hames template <typename ELFT>
2058e66fc43SLang Hames Expected<std::unique_ptr<LinkGraph>> ELFLinkGraphBuilder<ELFT>::buildGraph() {
2068e66fc43SLang Hames   if (!isRelocatable())
2078e66fc43SLang Hames     return make_error<JITLinkError>("Object is not a relocatable ELF file");
2088e66fc43SLang Hames 
2098e66fc43SLang Hames   if (auto Err = prepare())
2108e66fc43SLang Hames     return std::move(Err);
2118e66fc43SLang Hames 
2128e66fc43SLang Hames   if (auto Err = graphifySections())
2138e66fc43SLang Hames     return std::move(Err);
2148e66fc43SLang Hames 
2158e66fc43SLang Hames   if (auto Err = graphifySymbols())
2168e66fc43SLang Hames     return std::move(Err);
2178e66fc43SLang Hames 
2188e66fc43SLang Hames   if (auto Err = addRelocations())
2198e66fc43SLang Hames     return std::move(Err);
2208e66fc43SLang Hames 
2218e66fc43SLang Hames   return std::move(G);
2228e66fc43SLang Hames }
2238e66fc43SLang Hames 
2248e66fc43SLang Hames template <typename ELFT>
2258e66fc43SLang Hames Expected<std::pair<Linkage, Scope>>
2268e66fc43SLang Hames ELFLinkGraphBuilder<ELFT>::getSymbolLinkageAndScope(
2278e66fc43SLang Hames     const typename ELFT::Sym &Sym, StringRef Name) {
2288e66fc43SLang Hames   Linkage L = Linkage::Strong;
2298e66fc43SLang Hames   Scope S = Scope::Default;
2308e66fc43SLang Hames 
2318e66fc43SLang Hames   switch (Sym.getBinding()) {
2328e66fc43SLang Hames   case ELF::STB_LOCAL:
2338e66fc43SLang Hames     S = Scope::Local;
2348e66fc43SLang Hames     break;
2358e66fc43SLang Hames   case ELF::STB_GLOBAL:
2368e66fc43SLang Hames     // Nothing to do here.
2378e66fc43SLang Hames     break;
2388e66fc43SLang Hames   case ELF::STB_WEAK:
2392e6a4fceSLang Hames   case ELF::STB_GNU_UNIQUE:
2408e66fc43SLang Hames     L = Linkage::Weak;
2418e66fc43SLang Hames     break;
2428e66fc43SLang Hames   default:
24329ff2e87SLang Hames     return make_error<StringError>(
24429ff2e87SLang Hames         "Unrecognized symbol binding " +
24529ff2e87SLang Hames             Twine(static_cast<int>(Sym.getBinding())) + " for " + Name,
2468e66fc43SLang Hames         inconvertibleErrorCode());
2478e66fc43SLang Hames   }
2488e66fc43SLang Hames 
2498e66fc43SLang Hames   switch (Sym.getVisibility()) {
2508e66fc43SLang Hames   case ELF::STV_DEFAULT:
2518e66fc43SLang Hames   case ELF::STV_PROTECTED:
2528e66fc43SLang Hames     // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs
2538e66fc43SLang Hames     // Orc support.
2548e66fc43SLang Hames     // Otherwise nothing to do here.
2558e66fc43SLang Hames     break;
2568e66fc43SLang Hames   case ELF::STV_HIDDEN:
2578e66fc43SLang Hames     // Default scope -> Hidden scope. No effect on local scope.
2588e66fc43SLang Hames     if (S == Scope::Default)
2598e66fc43SLang Hames       S = Scope::Hidden;
2608e66fc43SLang Hames     break;
2618e66fc43SLang Hames   case ELF::STV_INTERNAL:
26229ff2e87SLang Hames     return make_error<StringError>(
26329ff2e87SLang Hames         "Unrecognized symbol visibility " +
26429ff2e87SLang Hames             Twine(static_cast<int>(Sym.getVisibility())) + " for " + Name,
2658e66fc43SLang Hames         inconvertibleErrorCode());
2668e66fc43SLang Hames   }
2678e66fc43SLang Hames 
2688e66fc43SLang Hames   return std::make_pair(L, S);
2698e66fc43SLang Hames }
2708e66fc43SLang Hames 
2718e66fc43SLang Hames template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::prepare() {
2728e66fc43SLang Hames   LLVM_DEBUG(dbgs() << "  Preparing to build...\n");
2738e66fc43SLang Hames 
2748e66fc43SLang Hames   // Get the sections array.
2758e66fc43SLang Hames   if (auto SectionsOrErr = Obj.sections())
2768e66fc43SLang Hames     Sections = *SectionsOrErr;
2778e66fc43SLang Hames   else
2788e66fc43SLang Hames     return SectionsOrErr.takeError();
2798e66fc43SLang Hames 
2808e66fc43SLang Hames   // Get the section string table.
2818e66fc43SLang Hames   if (auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))
2828e66fc43SLang Hames     SectionStringTab = *SectionStringTabOrErr;
2838e66fc43SLang Hames   else
2848e66fc43SLang Hames     return SectionStringTabOrErr.takeError();
2858e66fc43SLang Hames 
2868e66fc43SLang Hames   // Get the SHT_SYMTAB section.
2875e3200f3SSteven Wu   for (auto &Sec : Sections) {
2888e66fc43SLang Hames     if (Sec.sh_type == ELF::SHT_SYMTAB) {
2898e66fc43SLang Hames       if (!SymTabSec)
2908e66fc43SLang Hames         SymTabSec = &Sec;
2918e66fc43SLang Hames       else
2928e66fc43SLang Hames         return make_error<JITLinkError>("Multiple SHT_SYMTAB sections in " +
2938e66fc43SLang Hames                                         G->getName());
2948e66fc43SLang Hames     }
2958e66fc43SLang Hames 
2965e3200f3SSteven Wu     // Extended table.
2975e3200f3SSteven Wu     if (Sec.sh_type == ELF::SHT_SYMTAB_SHNDX) {
2985e3200f3SSteven Wu       uint32_t SymtabNdx = Sec.sh_link;
2995e3200f3SSteven Wu       if (SymtabNdx >= Sections.size())
3005e3200f3SSteven Wu         return make_error<JITLinkError>("sh_link is out of bound");
3015e3200f3SSteven Wu 
3025e3200f3SSteven Wu       auto ShndxTable = Obj.getSHNDXTable(Sec);
3035e3200f3SSteven Wu       if (!ShndxTable)
3045e3200f3SSteven Wu         return ShndxTable.takeError();
3055e3200f3SSteven Wu 
3065e3200f3SSteven Wu       ShndxTables.insert({&Sections[SymtabNdx], *ShndxTable});
3075e3200f3SSteven Wu     }
3085e3200f3SSteven Wu   }
3095e3200f3SSteven Wu 
3108e66fc43SLang Hames   return Error::success();
3118e66fc43SLang Hames }
3128e66fc43SLang Hames 
3138e66fc43SLang Hames template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() {
3148e66fc43SLang Hames   LLVM_DEBUG(dbgs() << "  Creating graph sections...\n");
3158e66fc43SLang Hames 
3168e66fc43SLang Hames   // For each section...
3178e66fc43SLang Hames   for (ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {
3188e66fc43SLang Hames 
3198e66fc43SLang Hames     auto &Sec = Sections[SecIndex];
3208e66fc43SLang Hames 
3218e66fc43SLang Hames     // Start by getting the section name.
3228e66fc43SLang Hames     auto Name = Obj.getSectionName(Sec, SectionStringTab);
3238e66fc43SLang Hames     if (!Name)
3248e66fc43SLang Hames       return Name.takeError();
3255c1d160cSStefan Gränitz     if (excludeSection(Sec)) {
3265c1d160cSStefan Gränitz       LLVM_DEBUG({
3275c1d160cSStefan Gränitz         dbgs() << "    " << SecIndex << ": Skipping section \"" << *Name
3285c1d160cSStefan Gränitz                << "\" explicitly\n";
3295c1d160cSStefan Gränitz       });
3305c1d160cSStefan Gränitz       continue;
3315c1d160cSStefan Gränitz     }
3328e66fc43SLang Hames 
3330b7e16afSLang Hames     // Skip null sections.
3340b7e16afSLang Hames     if (Sec.sh_type == ELF::SHT_NULL) {
3350b7e16afSLang Hames       LLVM_DEBUG({
3360b7e16afSLang Hames         dbgs() << "    " << SecIndex << ": has type SHT_NULL. Skipping.\n";
3370b7e16afSLang Hames       });
3380b7e16afSLang Hames       continue;
3390b7e16afSLang Hames     }
3400b7e16afSLang Hames 
3418e66fc43SLang Hames     // If the name indicates that it's a debug section then skip it: We don't
3428e66fc43SLang Hames     // support those yet.
343f05ac803SLang Hames     if (!ProcessDebugSections && isDwarfSection(*Name)) {
3448e66fc43SLang Hames       LLVM_DEBUG({
3458e66fc43SLang Hames         dbgs() << "    " << SecIndex << ": \"" << *Name
3468e66fc43SLang Hames                << "\" is a debug section: "
3478e66fc43SLang Hames                   "No graph section will be created.\n";
3488e66fc43SLang Hames       });
3498e66fc43SLang Hames       continue;
3508e66fc43SLang Hames     }
3518e66fc43SLang Hames 
3528e66fc43SLang Hames     LLVM_DEBUG({
3538e66fc43SLang Hames       dbgs() << "    " << SecIndex << ": Creating section for \"" << *Name
3548e66fc43SLang Hames              << "\"\n";
3558e66fc43SLang Hames     });
3568e66fc43SLang Hames 
3578e66fc43SLang Hames     // Get the section's memory protection flags.
358e9b394b0SJob Noorman     orc::MemProt Prot = orc::MemProt::Read;
3598e66fc43SLang Hames     if (Sec.sh_flags & ELF::SHF_EXECINSTR)
360e9b394b0SJob Noorman       Prot |= orc::MemProt::Exec;
361e9b394b0SJob Noorman     if (Sec.sh_flags & ELF::SHF_WRITE)
362e9b394b0SJob Noorman       Prot |= orc::MemProt::Write;
3638e66fc43SLang Hames 
364091e3648SSteven Wu     // Look for existing sections first.
365091e3648SSteven Wu     auto *GraphSec = G->findSectionByName(*Name);
3660b7e16afSLang Hames     if (!GraphSec) {
367091e3648SSteven Wu       GraphSec = &G->createSection(*Name, Prot);
3680b7e16afSLang Hames       // Non-SHF_ALLOC sections get NoAlloc memory lifetimes.
3690b7e16afSLang Hames       if (!(Sec.sh_flags & ELF::SHF_ALLOC)) {
370e994f84cSLang Hames         GraphSec->setMemLifetime(orc::MemLifetime::NoAlloc);
3710b7e16afSLang Hames         LLVM_DEBUG({
3720b7e16afSLang Hames           dbgs() << "      " << SecIndex << ": \"" << *Name
3730b7e16afSLang Hames                  << "\" is not a SHF_ALLOC section. Using NoAlloc lifetime.\n";
3740b7e16afSLang Hames         });
3750b7e16afSLang Hames       }
3760b7e16afSLang Hames     }
3770b7e16afSLang Hames 
378a43bf8a8SLang Hames     if (GraphSec->getMemProt() != Prot) {
379a43bf8a8SLang Hames       std::string ErrMsg;
380a43bf8a8SLang Hames       raw_string_ostream(ErrMsg)
381a43bf8a8SLang Hames           << "In " << G->getName() << ", section " << *Name
382a43bf8a8SLang Hames           << " is present more than once with different permissions: "
383a43bf8a8SLang Hames           << GraphSec->getMemProt() << " vs " << Prot;
384a43bf8a8SLang Hames       return make_error<JITLinkError>(std::move(ErrMsg));
385a43bf8a8SLang Hames     }
386091e3648SSteven Wu 
387091e3648SSteven Wu     Block *B = nullptr;
3888e66fc43SLang Hames     if (Sec.sh_type != ELF::SHT_NOBITS) {
3898e66fc43SLang Hames       auto Data = Obj.template getSectionContentsAsArray<char>(Sec);
3908e66fc43SLang Hames       if (!Data)
3918e66fc43SLang Hames         return Data.takeError();
3928e66fc43SLang Hames 
393091e3648SSteven Wu       B = &G->createContentBlock(*GraphSec, *Data,
394091e3648SSteven Wu                                  orc::ExecutorAddr(Sec.sh_addr),
395c5965a41SLang Hames                                  Sec.sh_addralign, 0);
396118e953bSLang Hames     } else
397091e3648SSteven Wu       B = &G->createZeroFillBlock(*GraphSec, Sec.sh_size,
398091e3648SSteven Wu                                   orc::ExecutorAddr(Sec.sh_addr),
399091e3648SSteven Wu                                   Sec.sh_addralign, 0);
4008e66fc43SLang Hames 
4019577806bSStefan Gränitz     if (Sec.sh_type == ELF::SHT_ARM_EXIDX) {
4029577806bSStefan Gränitz       // Add live symbol to avoid dead-stripping for .ARM.exidx sections
4039577806bSStefan Gränitz       G->addAnonymousSymbol(*B, orc::ExecutorAddrDiff(),
4049577806bSStefan Gränitz                             orc::ExecutorAddrDiff(), false, true);
4059577806bSStefan Gränitz     }
4069577806bSStefan Gränitz 
407091e3648SSteven Wu     setGraphBlock(SecIndex, B);
4088e66fc43SLang Hames   }
4098e66fc43SLang Hames 
4108e66fc43SLang Hames   return Error::success();
4118e66fc43SLang Hames }
4128e66fc43SLang Hames 
4138e66fc43SLang Hames template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
4148e66fc43SLang Hames   LLVM_DEBUG(dbgs() << "  Creating graph symbols...\n");
4158e66fc43SLang Hames 
4168e66fc43SLang Hames   // No SYMTAB -- Bail out early.
4178e66fc43SLang Hames   if (!SymTabSec)
4188e66fc43SLang Hames     return Error::success();
4198e66fc43SLang Hames 
4208e66fc43SLang Hames   // Get the section content as a Symbols array.
4218e66fc43SLang Hames   auto Symbols = Obj.symbols(SymTabSec);
4228e66fc43SLang Hames   if (!Symbols)
4238e66fc43SLang Hames     return Symbols.takeError();
4248e66fc43SLang Hames 
4258e66fc43SLang Hames   // Get the string table for this section.
4268e66fc43SLang Hames   auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
4278e66fc43SLang Hames   if (!StringTab)
4288e66fc43SLang Hames     return StringTab.takeError();
4298e66fc43SLang Hames 
4308e66fc43SLang Hames   LLVM_DEBUG({
4318e66fc43SLang Hames     StringRef SymTabName;
4328e66fc43SLang Hames 
4338e66fc43SLang Hames     if (auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
4348e66fc43SLang Hames       SymTabName = *SymTabNameOrErr;
4358e66fc43SLang Hames     else {
4368e66fc43SLang Hames       dbgs() << "Could not get ELF SHT_SYMTAB section name for logging: "
4378e66fc43SLang Hames              << toString(SymTabNameOrErr.takeError()) << "\n";
4388e66fc43SLang Hames       SymTabName = "<SHT_SYMTAB section with invalid name>";
4398e66fc43SLang Hames     }
4408e66fc43SLang Hames 
4418e66fc43SLang Hames     dbgs() << "    Adding symbols from symtab section \"" << SymTabName
4428e66fc43SLang Hames            << "\"\n";
4438e66fc43SLang Hames   });
4448e66fc43SLang Hames 
4458e66fc43SLang Hames   for (ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
4468e66fc43SLang Hames     auto &Sym = (*Symbols)[SymIndex];
4478e66fc43SLang Hames 
4488e66fc43SLang Hames     // Check symbol type.
4498e66fc43SLang Hames     switch (Sym.getType()) {
4508e66fc43SLang Hames     case ELF::STT_FILE:
4518e66fc43SLang Hames       LLVM_DEBUG({
4528e66fc43SLang Hames         if (auto Name = Sym.getName(*StringTab))
4538e66fc43SLang Hames           dbgs() << "      " << SymIndex << ": Skipping STT_FILE symbol \""
4548e66fc43SLang Hames                  << *Name << "\"\n";
4558e66fc43SLang Hames         else {
4568e66fc43SLang Hames           dbgs() << "Could not get STT_FILE symbol name: "
4578e66fc43SLang Hames                  << toString(Name.takeError()) << "\n";
4588e66fc43SLang Hames           dbgs() << "     " << SymIndex
4598e66fc43SLang Hames                  << ": Skipping STT_FILE symbol with invalid name\n";
4608e66fc43SLang Hames         }
4618e66fc43SLang Hames       });
4628e66fc43SLang Hames       continue;
4638e66fc43SLang Hames       break;
4648e66fc43SLang Hames     }
4658e66fc43SLang Hames 
4668e66fc43SLang Hames     // Get the symbol name.
4678e66fc43SLang Hames     auto Name = Sym.getName(*StringTab);
4688e66fc43SLang Hames     if (!Name)
4698e66fc43SLang Hames       return Name.takeError();
4708e66fc43SLang Hames 
4718e66fc43SLang Hames     // Handle common symbols specially.
4728e66fc43SLang Hames     if (Sym.isCommon()) {
473ffe2dda2SLang Hames       Symbol &GSym = G->addDefinedSymbol(
474ffe2dda2SLang Hames           G->createZeroFillBlock(getCommonSection(), Sym.st_size,
475ffe2dda2SLang Hames                                  orc::ExecutorAddr(), Sym.getValue(), 0),
476e7698a13SLang Hames           0, *Name, Sym.st_size, Linkage::Weak, Scope::Default, false, false);
4778e66fc43SLang Hames       setGraphSymbol(SymIndex, GSym);
4788e66fc43SLang Hames       continue;
4798e66fc43SLang Hames     }
4808e66fc43SLang Hames 
48175404e9eSLang Hames     if (Sym.isDefined() &&
48275404e9eSLang Hames         (Sym.getType() == ELF::STT_NOTYPE || Sym.getType() == ELF::STT_FUNC ||
48375404e9eSLang Hames          Sym.getType() == ELF::STT_OBJECT ||
48475404e9eSLang Hames          Sym.getType() == ELF::STT_SECTION || Sym.getType() == ELF::STT_TLS)) {
48575404e9eSLang Hames 
4868e66fc43SLang Hames       // Map Visibility and Binding to Scope and Linkage:
4878e66fc43SLang Hames       Linkage L;
4888e66fc43SLang Hames       Scope S;
4898e66fc43SLang Hames       if (auto LSOrErr = getSymbolLinkageAndScope(Sym, *Name))
4908e66fc43SLang Hames         std::tie(L, S) = *LSOrErr;
4918e66fc43SLang Hames       else
4928e66fc43SLang Hames         return LSOrErr.takeError();
4938e66fc43SLang Hames 
4945e3200f3SSteven Wu       // Handle extended tables.
4955e3200f3SSteven Wu       unsigned Shndx = Sym.st_shndx;
4965e3200f3SSteven Wu       if (Shndx == ELF::SHN_XINDEX) {
4975e3200f3SSteven Wu         auto ShndxTable = ShndxTables.find(SymTabSec);
4985e3200f3SSteven Wu         if (ShndxTable == ShndxTables.end())
4995e3200f3SSteven Wu           continue;
5005e3200f3SSteven Wu         auto NdxOrErr = object::getExtendedSymbolTableIndex<ELFT>(
5015e3200f3SSteven Wu             Sym, SymIndex, ShndxTable->second);
5025e3200f3SSteven Wu         if (!NdxOrErr)
5035e3200f3SSteven Wu           return NdxOrErr.takeError();
5045e3200f3SSteven Wu         Shndx = *NdxOrErr;
5055e3200f3SSteven Wu       }
506091e3648SSteven Wu       if (auto *B = getGraphBlock(Shndx)) {
5078e66fc43SLang Hames         LLVM_DEBUG({
5088e66fc43SLang Hames           dbgs() << "      " << SymIndex
5098e66fc43SLang Hames                  << ": Creating defined graph symbol for ELF symbol \"" << *Name
5108e66fc43SLang Hames                  << "\"\n";
5118e66fc43SLang Hames         });
5128e66fc43SLang Hames 
513cf8dc9dfSStefan Gränitz         TargetFlagsType Flags = makeTargetFlags(Sym);
514cf8dc9dfSStefan Gränitz         orc::ExecutorAddrDiff Offset = getRawOffset(Sym, Flags);
515cf8dc9dfSStefan Gränitz 
516a43bf8a8SLang Hames         if (Offset + Sym.st_size > B->getSize()) {
517a43bf8a8SLang Hames           std::string ErrMsg;
518a43bf8a8SLang Hames           raw_string_ostream ErrStream(ErrMsg);
519a43bf8a8SLang Hames           ErrStream << "In " << G->getName() << ", symbol ";
520a43bf8a8SLang Hames           if (!Name->empty())
521a43bf8a8SLang Hames             ErrStream << *Name;
522a43bf8a8SLang Hames           else
523a43bf8a8SLang Hames             ErrStream << "<anon>";
524a43bf8a8SLang Hames           ErrStream << " (" << (B->getAddress() + Offset) << " -- "
525a43bf8a8SLang Hames                     << (B->getAddress() + Offset + Sym.st_size) << ") extends "
526a43bf8a8SLang Hames                     << formatv("{0:x}", Offset + Sym.st_size - B->getSize())
527a43bf8a8SLang Hames                     << " bytes past the end of its containing block ("
528a43bf8a8SLang Hames                     << B->getRange() << ")";
529a43bf8a8SLang Hames           return make_error<JITLinkError>(std::move(ErrMsg));
530a43bf8a8SLang Hames         }
531a43bf8a8SLang Hames 
5320283b077Sluxufan         // In RISCV, temporary symbols (Used to generate dwarf, eh_frame
5330283b077Sluxufan         // sections...) will appear in object code's symbol table, and LLVM does
5340283b077Sluxufan         // not use names on these temporary symbols (RISCV gnu toolchain uses
5350283b077Sluxufan         // names on these temporary symbols). If the symbol is unnamed, add an
5360283b077Sluxufan         // anonymous symbol.
5378e66fc43SLang Hames         auto &GSym =
5380283b077Sluxufan             Name->empty()
539cf8dc9dfSStefan Gränitz                 ? G->addAnonymousSymbol(*B, Offset, Sym.st_size,
5400283b077Sluxufan                                         false, false)
541cf8dc9dfSStefan Gränitz                 : G->addDefinedSymbol(*B, Offset, *Name, Sym.st_size, L,
542cf8dc9dfSStefan Gränitz                                       S, Sym.getType() == ELF::STT_FUNC,
543cf8dc9dfSStefan Gränitz                                       false);
544cf8dc9dfSStefan Gränitz 
545cf8dc9dfSStefan Gränitz         GSym.setTargetFlags(Flags);
5468e66fc43SLang Hames         setGraphSymbol(SymIndex, GSym);
5478e66fc43SLang Hames       }
5488e66fc43SLang Hames     } else if (Sym.isUndefined() && Sym.isExternal()) {
5498e66fc43SLang Hames       LLVM_DEBUG({
5508e66fc43SLang Hames         dbgs() << "      " << SymIndex
5518e66fc43SLang Hames                << ": Creating external graph symbol for ELF symbol \"" << *Name
5528e66fc43SLang Hames                << "\"\n";
5538e66fc43SLang Hames       });
55475404e9eSLang Hames 
55575404e9eSLang Hames       if (Sym.getBinding() != ELF::STB_GLOBAL &&
55675404e9eSLang Hames           Sym.getBinding() != ELF::STB_WEAK)
55775404e9eSLang Hames         return make_error<StringError>(
55875404e9eSLang Hames             "Invalid symbol binding " +
55975404e9eSLang Hames                 Twine(static_cast<int>(Sym.getBinding())) +
56075404e9eSLang Hames                 " for external symbol " + *Name,
56175404e9eSLang Hames             inconvertibleErrorCode());
56275404e9eSLang Hames 
56375404e9eSLang Hames       // If L is Linkage::Weak that means this is a weakly referenced symbol.
56475404e9eSLang Hames       auto &GSym = G->addExternalSymbol(*Name, Sym.st_size,
56575404e9eSLang Hames                                         Sym.getBinding() == ELF::STB_WEAK);
5668e66fc43SLang Hames       setGraphSymbol(SymIndex, GSym);
5676c06a079SJob Noorman     } else if (Sym.isUndefined() && Sym.st_value == 0 && Sym.st_size == 0 &&
5686c06a079SJob Noorman                Sym.getType() == ELF::STT_NOTYPE &&
5696c06a079SJob Noorman                Sym.getBinding() == ELF::STB_LOCAL && Name->empty()) {
5706c06a079SJob Noorman       // Some relocations (e.g., R_RISCV_ALIGN) don't have a target symbol and
5716c06a079SJob Noorman       // use this kind of null symbol as a placeholder.
5726c06a079SJob Noorman       LLVM_DEBUG({
5736c06a079SJob Noorman         dbgs() << "      " << SymIndex << ": Creating null graph symbol\n";
5746c06a079SJob Noorman       });
5756c06a079SJob Noorman 
5766c06a079SJob Noorman       auto SymName =
5776c06a079SJob Noorman           G->allocateContent("__jitlink_ELF_SYM_UND_" + Twine(SymIndex));
5786c06a079SJob Noorman       auto SymNameRef = StringRef(SymName.data(), SymName.size());
5796c06a079SJob Noorman       auto &GSym = G->addAbsoluteSymbol(SymNameRef, orc::ExecutorAddr(0), 0,
5806c06a079SJob Noorman                                         Linkage::Strong, Scope::Local, false);
5816c06a079SJob Noorman       setGraphSymbol(SymIndex, GSym);
5828e66fc43SLang Hames     } else {
5838e66fc43SLang Hames       LLVM_DEBUG({
5848e66fc43SLang Hames         dbgs() << "      " << SymIndex
5858e66fc43SLang Hames                << ": Not creating graph symbol for ELF symbol \"" << *Name
5868e66fc43SLang Hames                << "\" with unrecognized type\n";
5878e66fc43SLang Hames       });
5888e66fc43SLang Hames     }
5898e66fc43SLang Hames   }
5908e66fc43SLang Hames 
5918e66fc43SLang Hames   return Error::success();
5928e66fc43SLang Hames }
593aff57ff2SLang Hames 
59496918515SStefan Gränitz template <typename ELFT>
595f97d3ba2SStefan Gränitz template <typename RelocHandlerFunction>
5962a3b257aSKshitij Jain Error ELFLinkGraphBuilder<ELFT>::forEachRelaRelocation(
597f05ac803SLang Hames     const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
59896918515SStefan Gränitz   // Only look into sections that store relocation entries.
5992a3b257aSKshitij Jain   if (RelSect.sh_type != ELF::SHT_RELA)
60096918515SStefan Gränitz     return Error::success();
60196918515SStefan Gränitz 
60296918515SStefan Gränitz   // sh_info contains the section header index of the target (FixupSection),
60396918515SStefan Gränitz   // which is the section to which all relocations in RelSect apply.
60496918515SStefan Gränitz   auto FixupSection = Obj.getSection(RelSect.sh_info);
60596918515SStefan Gränitz   if (!FixupSection)
60696918515SStefan Gränitz     return FixupSection.takeError();
60796918515SStefan Gränitz 
60896918515SStefan Gränitz   // Target sections have names in valid ELF object files.
60996918515SStefan Gränitz   Expected<StringRef> Name = Obj.getSectionName(**FixupSection);
61096918515SStefan Gränitz   if (!Name)
61196918515SStefan Gränitz     return Name.takeError();
61296918515SStefan Gränitz   LLVM_DEBUG(dbgs() << "  " << *Name << ":\n");
61396918515SStefan Gränitz 
61496918515SStefan Gränitz   // Consider skipping these relocations.
61596918515SStefan Gränitz   if (!ProcessDebugSections && isDwarfSection(*Name)) {
61696918515SStefan Gränitz     LLVM_DEBUG(dbgs() << "    skipped (dwarf section)\n\n");
61796918515SStefan Gränitz     return Error::success();
61896918515SStefan Gränitz   }
6195c1d160cSStefan Gränitz   if (excludeSection(**FixupSection)) {
6205c1d160cSStefan Gränitz     LLVM_DEBUG(dbgs() << "    skipped (fixup section excluded explicitly)\n\n");
6215c1d160cSStefan Gränitz     return Error::success();
6225c1d160cSStefan Gränitz   }
62396918515SStefan Gränitz 
62496918515SStefan Gränitz   // Lookup the link-graph node corresponding to the target section name.
625091e3648SSteven Wu   auto *BlockToFix = getGraphBlock(RelSect.sh_info);
626091e3648SSteven Wu   if (!BlockToFix)
62796918515SStefan Gränitz     return make_error<StringError>(
62896918515SStefan Gränitz         "Refencing a section that wasn't added to the graph: " + *Name,
62996918515SStefan Gränitz         inconvertibleErrorCode());
63096918515SStefan Gränitz 
63196918515SStefan Gränitz   auto RelEntries = Obj.relas(RelSect);
63296918515SStefan Gränitz   if (!RelEntries)
63396918515SStefan Gränitz     return RelEntries.takeError();
63496918515SStefan Gränitz 
63596918515SStefan Gränitz   // Let the callee process relocation entries one by one.
63696918515SStefan Gränitz   for (const typename ELFT::Rela &R : *RelEntries)
637091e3648SSteven Wu     if (Error Err = Func(R, **FixupSection, *BlockToFix))
63896918515SStefan Gränitz       return Err;
63996918515SStefan Gränitz 
64096918515SStefan Gränitz   LLVM_DEBUG(dbgs() << "\n");
64196918515SStefan Gränitz   return Error::success();
64296918515SStefan Gränitz }
64396918515SStefan Gränitz 
6442a3b257aSKshitij Jain template <typename ELFT>
645f97d3ba2SStefan Gränitz template <typename RelocHandlerFunction>
6462a3b257aSKshitij Jain Error ELFLinkGraphBuilder<ELFT>::forEachRelRelocation(
647f05ac803SLang Hames     const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {
6482a3b257aSKshitij Jain   // Only look into sections that store relocation entries.
6492a3b257aSKshitij Jain   if (RelSect.sh_type != ELF::SHT_REL)
6502a3b257aSKshitij Jain     return Error::success();
6512a3b257aSKshitij Jain 
6522a3b257aSKshitij Jain   // sh_info contains the section header index of the target (FixupSection),
6532a3b257aSKshitij Jain   // which is the section to which all relocations in RelSect apply.
6542a3b257aSKshitij Jain   auto FixupSection = Obj.getSection(RelSect.sh_info);
6552a3b257aSKshitij Jain   if (!FixupSection)
6562a3b257aSKshitij Jain     return FixupSection.takeError();
6572a3b257aSKshitij Jain 
6582a3b257aSKshitij Jain   // Target sections have names in valid ELF object files.
6592a3b257aSKshitij Jain   Expected<StringRef> Name = Obj.getSectionName(**FixupSection);
6602a3b257aSKshitij Jain   if (!Name)
6612a3b257aSKshitij Jain     return Name.takeError();
6622a3b257aSKshitij Jain   LLVM_DEBUG(dbgs() << "  " << *Name << ":\n");
6632a3b257aSKshitij Jain 
6642a3b257aSKshitij Jain   // Consider skipping these relocations.
6652a3b257aSKshitij Jain   if (!ProcessDebugSections && isDwarfSection(*Name)) {
6662a3b257aSKshitij Jain     LLVM_DEBUG(dbgs() << "    skipped (dwarf section)\n\n");
6672a3b257aSKshitij Jain     return Error::success();
6682a3b257aSKshitij Jain   }
6695c1d160cSStefan Gränitz   if (excludeSection(**FixupSection)) {
6705c1d160cSStefan Gränitz     LLVM_DEBUG(dbgs() << "    skipped (fixup section excluded explicitly)\n\n");
6715c1d160cSStefan Gränitz     return Error::success();
6725c1d160cSStefan Gränitz   }
6732a3b257aSKshitij Jain 
6742a3b257aSKshitij Jain   // Lookup the link-graph node corresponding to the target section name.
6752a3b257aSKshitij Jain   auto *BlockToFix = getGraphBlock(RelSect.sh_info);
6762a3b257aSKshitij Jain   if (!BlockToFix)
6772a3b257aSKshitij Jain     return make_error<StringError>(
6782a3b257aSKshitij Jain         "Refencing a section that wasn't added to the graph: " + *Name,
6792a3b257aSKshitij Jain         inconvertibleErrorCode());
6802a3b257aSKshitij Jain 
6812a3b257aSKshitij Jain   auto RelEntries = Obj.rels(RelSect);
6822a3b257aSKshitij Jain   if (!RelEntries)
6832a3b257aSKshitij Jain     return RelEntries.takeError();
6842a3b257aSKshitij Jain 
6852a3b257aSKshitij Jain   // Let the callee process relocation entries one by one.
6862a3b257aSKshitij Jain   for (const typename ELFT::Rel &R : *RelEntries)
6872a3b257aSKshitij Jain     if (Error Err = Func(R, **FixupSection, *BlockToFix))
6882a3b257aSKshitij Jain       return Err;
6892a3b257aSKshitij Jain 
6902a3b257aSKshitij Jain   LLVM_DEBUG(dbgs() << "\n");
6912a3b257aSKshitij Jain   return Error::success();
6922a3b257aSKshitij Jain }
6932a3b257aSKshitij Jain 
694aff57ff2SLang Hames } // end namespace jitlink
695aff57ff2SLang Hames } // end namespace llvm
696aff57ff2SLang Hames 
6978e66fc43SLang Hames #undef DEBUG_TYPE
6988e66fc43SLang Hames 
699aff57ff2SLang Hames #endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
700