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