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) 40349cc55cSDimitry Andric CommonSection = 41349cc55cSDimitry Andric &G->createSection(CommonSectionName, MemProt::Read | 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 80*04eeddc0SDimitry Andric void setGraphBlock(ELFSectionIndex SecIndex, Block *B) { 81*04eeddc0SDimitry Andric assert(!GraphBlocks.count(SecIndex) && "Duplicate section at index"); 82*04eeddc0SDimitry Andric GraphBlocks[SecIndex] = B; 83fe6060f1SDimitry Andric } 84fe6060f1SDimitry Andric 85*04eeddc0SDimitry Andric Block *getGraphBlock(ELFSectionIndex SecIndex) { 86*04eeddc0SDimitry Andric auto I = GraphBlocks.find(SecIndex); 87*04eeddc0SDimitry 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 111349cc55cSDimitry Andric /// Traverse all matching relocation records in the given section. The handler 112349cc55cSDimitry Andric /// function Func should be callable with this signature: 113349cc55cSDimitry Andric /// Error(const typename ELFT::Rela &, 114349cc55cSDimitry Andric /// const typename ELFT::Shdr &, Section &) 115349cc55cSDimitry Andric /// 116349cc55cSDimitry Andric template <typename RelocHandlerFunction> 117349cc55cSDimitry Andric Error forEachRelocation(const typename ELFT::Shdr &RelSect, 118349cc55cSDimitry Andric RelocHandlerFunction &&Func, 119349cc55cSDimitry Andric bool ProcessDebugSections = false); 120349cc55cSDimitry Andric 121349cc55cSDimitry Andric /// Traverse all matching relocation records in the given section. Convenience 122349cc55cSDimitry Andric /// wrapper to allow passing a member function for the handler. 123349cc55cSDimitry Andric /// 124349cc55cSDimitry Andric template <typename ClassT, typename RelocHandlerMethod> 125349cc55cSDimitry Andric Error forEachRelocation(const typename ELFT::Shdr &RelSect, ClassT *Instance, 126349cc55cSDimitry Andric RelocHandlerMethod &&Method, 127349cc55cSDimitry Andric bool ProcessDebugSections = false) { 128349cc55cSDimitry Andric return forEachRelocation( 129349cc55cSDimitry Andric RelSect, 130349cc55cSDimitry Andric [Instance, Method](const auto &Rel, const auto &Target, auto &GS) { 131349cc55cSDimitry Andric return (Instance->*Method)(Rel, Target, GS); 132349cc55cSDimitry Andric }, 133349cc55cSDimitry Andric ProcessDebugSections); 134349cc55cSDimitry Andric } 135349cc55cSDimitry Andric 136fe6060f1SDimitry Andric const ELFFile &Obj; 137fe6060f1SDimitry Andric 138fe6060f1SDimitry Andric typename ELFFile::Elf_Shdr_Range Sections; 139fe6060f1SDimitry Andric const typename ELFFile::Elf_Shdr *SymTabSec = nullptr; 140fe6060f1SDimitry Andric StringRef SectionStringTab; 141fe6060f1SDimitry Andric 142*04eeddc0SDimitry Andric // Maps ELF section indexes to LinkGraph Blocks. 143*04eeddc0SDimitry Andric // Only SHF_ALLOC sections will have graph blocks. 144*04eeddc0SDimitry Andric DenseMap<ELFSectionIndex, Block *> GraphBlocks; 145fe6060f1SDimitry Andric DenseMap<ELFSymbolIndex, Symbol *> GraphSymbols; 1464824e7fdSDimitry Andric DenseMap<const typename ELFFile::Elf_Shdr *, 1474824e7fdSDimitry Andric ArrayRef<typename ELFFile::Elf_Word>> 1484824e7fdSDimitry Andric ShndxTables; 149fe6060f1SDimitry Andric }; 150fe6060f1SDimitry Andric 151fe6060f1SDimitry Andric template <typename ELFT> 152fe6060f1SDimitry Andric ELFLinkGraphBuilder<ELFT>::ELFLinkGraphBuilder( 153fe6060f1SDimitry Andric const ELFFile &Obj, Triple TT, StringRef FileName, 154fe6060f1SDimitry Andric LinkGraph::GetEdgeKindNameFunction GetEdgeKindName) 155fe6060f1SDimitry Andric : ELFLinkGraphBuilderBase(std::make_unique<LinkGraph>( 156fe6060f1SDimitry Andric FileName.str(), Triple(std::move(TT)), ELFT::Is64Bits ? 8 : 4, 157fe6060f1SDimitry Andric support::endianness(ELFT::TargetEndianness), 158fe6060f1SDimitry Andric std::move(GetEdgeKindName))), 159fe6060f1SDimitry Andric Obj(Obj) { 160fe6060f1SDimitry Andric LLVM_DEBUG( 161fe6060f1SDimitry Andric { dbgs() << "Created ELFLinkGraphBuilder for \"" << FileName << "\""; }); 162fe6060f1SDimitry Andric } 163fe6060f1SDimitry Andric 164fe6060f1SDimitry Andric template <typename ELFT> 165fe6060f1SDimitry Andric Expected<std::unique_ptr<LinkGraph>> ELFLinkGraphBuilder<ELFT>::buildGraph() { 166fe6060f1SDimitry Andric if (!isRelocatable()) 167fe6060f1SDimitry Andric return make_error<JITLinkError>("Object is not a relocatable ELF file"); 168fe6060f1SDimitry Andric 169fe6060f1SDimitry Andric if (auto Err = prepare()) 170fe6060f1SDimitry Andric return std::move(Err); 171fe6060f1SDimitry Andric 172fe6060f1SDimitry Andric if (auto Err = graphifySections()) 173fe6060f1SDimitry Andric return std::move(Err); 174fe6060f1SDimitry Andric 175fe6060f1SDimitry Andric if (auto Err = graphifySymbols()) 176fe6060f1SDimitry Andric return std::move(Err); 177fe6060f1SDimitry Andric 178fe6060f1SDimitry Andric if (auto Err = addRelocations()) 179fe6060f1SDimitry Andric return std::move(Err); 180fe6060f1SDimitry Andric 181fe6060f1SDimitry Andric return std::move(G); 182fe6060f1SDimitry Andric } 183fe6060f1SDimitry Andric 184fe6060f1SDimitry Andric template <typename ELFT> 185fe6060f1SDimitry Andric Expected<std::pair<Linkage, Scope>> 186fe6060f1SDimitry Andric ELFLinkGraphBuilder<ELFT>::getSymbolLinkageAndScope( 187fe6060f1SDimitry Andric const typename ELFT::Sym &Sym, StringRef Name) { 188fe6060f1SDimitry Andric Linkage L = Linkage::Strong; 189fe6060f1SDimitry Andric Scope S = Scope::Default; 190fe6060f1SDimitry Andric 191fe6060f1SDimitry Andric switch (Sym.getBinding()) { 192fe6060f1SDimitry Andric case ELF::STB_LOCAL: 193fe6060f1SDimitry Andric S = Scope::Local; 194fe6060f1SDimitry Andric break; 195fe6060f1SDimitry Andric case ELF::STB_GLOBAL: 196fe6060f1SDimitry Andric // Nothing to do here. 197fe6060f1SDimitry Andric break; 198fe6060f1SDimitry Andric case ELF::STB_WEAK: 199349cc55cSDimitry Andric case ELF::STB_GNU_UNIQUE: 200fe6060f1SDimitry Andric L = Linkage::Weak; 201fe6060f1SDimitry Andric break; 202fe6060f1SDimitry Andric default: 203349cc55cSDimitry Andric return make_error<StringError>( 204349cc55cSDimitry Andric "Unrecognized symbol binding " + 205349cc55cSDimitry Andric Twine(static_cast<int>(Sym.getBinding())) + " for " + Name, 206fe6060f1SDimitry Andric inconvertibleErrorCode()); 207fe6060f1SDimitry Andric } 208fe6060f1SDimitry Andric 209fe6060f1SDimitry Andric switch (Sym.getVisibility()) { 210fe6060f1SDimitry Andric case ELF::STV_DEFAULT: 211fe6060f1SDimitry Andric case ELF::STV_PROTECTED: 212fe6060f1SDimitry Andric // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs 213fe6060f1SDimitry Andric // Orc support. 214fe6060f1SDimitry Andric // Otherwise nothing to do here. 215fe6060f1SDimitry Andric break; 216fe6060f1SDimitry Andric case ELF::STV_HIDDEN: 217fe6060f1SDimitry Andric // Default scope -> Hidden scope. No effect on local scope. 218fe6060f1SDimitry Andric if (S == Scope::Default) 219fe6060f1SDimitry Andric S = Scope::Hidden; 220fe6060f1SDimitry Andric break; 221fe6060f1SDimitry Andric case ELF::STV_INTERNAL: 222349cc55cSDimitry Andric return make_error<StringError>( 223349cc55cSDimitry Andric "Unrecognized symbol visibility " + 224349cc55cSDimitry Andric Twine(static_cast<int>(Sym.getVisibility())) + " for " + Name, 225fe6060f1SDimitry Andric inconvertibleErrorCode()); 226fe6060f1SDimitry Andric } 227fe6060f1SDimitry Andric 228fe6060f1SDimitry Andric return std::make_pair(L, S); 229fe6060f1SDimitry Andric } 230fe6060f1SDimitry Andric 231fe6060f1SDimitry Andric template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::prepare() { 232fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << " Preparing to build...\n"); 233fe6060f1SDimitry Andric 234fe6060f1SDimitry Andric // Get the sections array. 235fe6060f1SDimitry Andric if (auto SectionsOrErr = Obj.sections()) 236fe6060f1SDimitry Andric Sections = *SectionsOrErr; 237fe6060f1SDimitry Andric else 238fe6060f1SDimitry Andric return SectionsOrErr.takeError(); 239fe6060f1SDimitry Andric 240fe6060f1SDimitry Andric // Get the section string table. 241fe6060f1SDimitry Andric if (auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections)) 242fe6060f1SDimitry Andric SectionStringTab = *SectionStringTabOrErr; 243fe6060f1SDimitry Andric else 244fe6060f1SDimitry Andric return SectionStringTabOrErr.takeError(); 245fe6060f1SDimitry Andric 246fe6060f1SDimitry Andric // Get the SHT_SYMTAB section. 2474824e7fdSDimitry Andric for (auto &Sec : Sections) { 248fe6060f1SDimitry Andric if (Sec.sh_type == ELF::SHT_SYMTAB) { 249fe6060f1SDimitry Andric if (!SymTabSec) 250fe6060f1SDimitry Andric SymTabSec = &Sec; 251fe6060f1SDimitry Andric else 252fe6060f1SDimitry Andric return make_error<JITLinkError>("Multiple SHT_SYMTAB sections in " + 253fe6060f1SDimitry Andric G->getName()); 254fe6060f1SDimitry Andric } 255fe6060f1SDimitry Andric 2564824e7fdSDimitry Andric // Extended table. 2574824e7fdSDimitry Andric if (Sec.sh_type == ELF::SHT_SYMTAB_SHNDX) { 2584824e7fdSDimitry Andric uint32_t SymtabNdx = Sec.sh_link; 2594824e7fdSDimitry Andric if (SymtabNdx >= Sections.size()) 2604824e7fdSDimitry Andric return make_error<JITLinkError>("sh_link is out of bound"); 2614824e7fdSDimitry Andric 2624824e7fdSDimitry Andric auto ShndxTable = Obj.getSHNDXTable(Sec); 2634824e7fdSDimitry Andric if (!ShndxTable) 2644824e7fdSDimitry Andric return ShndxTable.takeError(); 2654824e7fdSDimitry Andric 2664824e7fdSDimitry Andric ShndxTables.insert({&Sections[SymtabNdx], *ShndxTable}); 2674824e7fdSDimitry Andric } 2684824e7fdSDimitry Andric } 2694824e7fdSDimitry Andric 270fe6060f1SDimitry Andric return Error::success(); 271fe6060f1SDimitry Andric } 272fe6060f1SDimitry Andric 273fe6060f1SDimitry Andric template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() { 274fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << " Creating graph sections...\n"); 275fe6060f1SDimitry Andric 276fe6060f1SDimitry Andric // For each section... 277fe6060f1SDimitry Andric for (ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) { 278fe6060f1SDimitry Andric 279fe6060f1SDimitry Andric auto &Sec = Sections[SecIndex]; 280fe6060f1SDimitry Andric 281fe6060f1SDimitry Andric // Start by getting the section name. 282fe6060f1SDimitry Andric auto Name = Obj.getSectionName(Sec, SectionStringTab); 283fe6060f1SDimitry Andric if (!Name) 284fe6060f1SDimitry Andric return Name.takeError(); 285fe6060f1SDimitry Andric 286fe6060f1SDimitry Andric // If the name indicates that it's a debug section then skip it: We don't 287fe6060f1SDimitry Andric // support those yet. 288fe6060f1SDimitry Andric if (isDwarfSection(*Name)) { 289fe6060f1SDimitry Andric LLVM_DEBUG({ 290fe6060f1SDimitry Andric dbgs() << " " << SecIndex << ": \"" << *Name 291fe6060f1SDimitry Andric << "\" is a debug section: " 292fe6060f1SDimitry Andric "No graph section will be created.\n"; 293fe6060f1SDimitry Andric }); 294fe6060f1SDimitry Andric continue; 295fe6060f1SDimitry Andric } 296fe6060f1SDimitry Andric 297fe6060f1SDimitry Andric // Skip non-SHF_ALLOC sections 298fe6060f1SDimitry Andric if (!(Sec.sh_flags & ELF::SHF_ALLOC)) { 299fe6060f1SDimitry Andric LLVM_DEBUG({ 300fe6060f1SDimitry Andric dbgs() << " " << SecIndex << ": \"" << *Name 301fe6060f1SDimitry Andric << "\" is not an SHF_ALLOC section: " 302fe6060f1SDimitry Andric "No graph section will be created.\n"; 303fe6060f1SDimitry Andric }); 304fe6060f1SDimitry Andric continue; 305fe6060f1SDimitry Andric } 306fe6060f1SDimitry Andric 307fe6060f1SDimitry Andric LLVM_DEBUG({ 308fe6060f1SDimitry Andric dbgs() << " " << SecIndex << ": Creating section for \"" << *Name 309fe6060f1SDimitry Andric << "\"\n"; 310fe6060f1SDimitry Andric }); 311fe6060f1SDimitry Andric 312fe6060f1SDimitry Andric // Get the section's memory protection flags. 313349cc55cSDimitry Andric MemProt Prot; 314fe6060f1SDimitry Andric if (Sec.sh_flags & ELF::SHF_EXECINSTR) 315349cc55cSDimitry Andric Prot = MemProt::Read | MemProt::Exec; 316fe6060f1SDimitry Andric else 317349cc55cSDimitry Andric Prot = MemProt::Read | MemProt::Write; 318fe6060f1SDimitry Andric 319*04eeddc0SDimitry Andric // Look for existing sections first. 320*04eeddc0SDimitry Andric auto *GraphSec = G->findSectionByName(*Name); 321*04eeddc0SDimitry Andric if (!GraphSec) 322*04eeddc0SDimitry Andric GraphSec = &G->createSection(*Name, Prot); 323*04eeddc0SDimitry Andric assert(GraphSec->getMemProt() == Prot && "MemProt should match"); 324*04eeddc0SDimitry Andric 325*04eeddc0SDimitry Andric Block *B = nullptr; 326fe6060f1SDimitry Andric if (Sec.sh_type != ELF::SHT_NOBITS) { 327fe6060f1SDimitry Andric auto Data = Obj.template getSectionContentsAsArray<char>(Sec); 328fe6060f1SDimitry Andric if (!Data) 329fe6060f1SDimitry Andric return Data.takeError(); 330fe6060f1SDimitry Andric 331*04eeddc0SDimitry Andric B = &G->createContentBlock(*GraphSec, *Data, 332*04eeddc0SDimitry Andric orc::ExecutorAddr(Sec.sh_addr), 333*04eeddc0SDimitry Andric Sec.sh_addralign, 0); 334fe6060f1SDimitry Andric } else 335*04eeddc0SDimitry Andric B = &G->createZeroFillBlock(*GraphSec, Sec.sh_size, 336*04eeddc0SDimitry Andric orc::ExecutorAddr(Sec.sh_addr), 337fe6060f1SDimitry Andric Sec.sh_addralign, 0); 338fe6060f1SDimitry Andric 339*04eeddc0SDimitry Andric setGraphBlock(SecIndex, B); 340fe6060f1SDimitry Andric } 341fe6060f1SDimitry Andric 342fe6060f1SDimitry Andric return Error::success(); 343fe6060f1SDimitry Andric } 344fe6060f1SDimitry Andric 345fe6060f1SDimitry Andric template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() { 346fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << " Creating graph symbols...\n"); 347fe6060f1SDimitry Andric 348fe6060f1SDimitry Andric // No SYMTAB -- Bail out early. 349fe6060f1SDimitry Andric if (!SymTabSec) 350fe6060f1SDimitry Andric return Error::success(); 351fe6060f1SDimitry Andric 352fe6060f1SDimitry Andric // Get the section content as a Symbols array. 353fe6060f1SDimitry Andric auto Symbols = Obj.symbols(SymTabSec); 354fe6060f1SDimitry Andric if (!Symbols) 355fe6060f1SDimitry Andric return Symbols.takeError(); 356fe6060f1SDimitry Andric 357fe6060f1SDimitry Andric // Get the string table for this section. 358fe6060f1SDimitry Andric auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections); 359fe6060f1SDimitry Andric if (!StringTab) 360fe6060f1SDimitry Andric return StringTab.takeError(); 361fe6060f1SDimitry Andric 362fe6060f1SDimitry Andric LLVM_DEBUG({ 363fe6060f1SDimitry Andric StringRef SymTabName; 364fe6060f1SDimitry Andric 365fe6060f1SDimitry Andric if (auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab)) 366fe6060f1SDimitry Andric SymTabName = *SymTabNameOrErr; 367fe6060f1SDimitry Andric else { 368fe6060f1SDimitry Andric dbgs() << "Could not get ELF SHT_SYMTAB section name for logging: " 369fe6060f1SDimitry Andric << toString(SymTabNameOrErr.takeError()) << "\n"; 370fe6060f1SDimitry Andric SymTabName = "<SHT_SYMTAB section with invalid name>"; 371fe6060f1SDimitry Andric } 372fe6060f1SDimitry Andric 373fe6060f1SDimitry Andric dbgs() << " Adding symbols from symtab section \"" << SymTabName 374fe6060f1SDimitry Andric << "\"\n"; 375fe6060f1SDimitry Andric }); 376fe6060f1SDimitry Andric 377fe6060f1SDimitry Andric for (ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) { 378fe6060f1SDimitry Andric auto &Sym = (*Symbols)[SymIndex]; 379fe6060f1SDimitry Andric 380fe6060f1SDimitry Andric // Check symbol type. 381fe6060f1SDimitry Andric switch (Sym.getType()) { 382fe6060f1SDimitry Andric case ELF::STT_FILE: 383fe6060f1SDimitry Andric LLVM_DEBUG({ 384fe6060f1SDimitry Andric if (auto Name = Sym.getName(*StringTab)) 385fe6060f1SDimitry Andric dbgs() << " " << SymIndex << ": Skipping STT_FILE symbol \"" 386fe6060f1SDimitry Andric << *Name << "\"\n"; 387fe6060f1SDimitry Andric else { 388fe6060f1SDimitry Andric dbgs() << "Could not get STT_FILE symbol name: " 389fe6060f1SDimitry Andric << toString(Name.takeError()) << "\n"; 390fe6060f1SDimitry Andric dbgs() << " " << SymIndex 391fe6060f1SDimitry Andric << ": Skipping STT_FILE symbol with invalid name\n"; 392fe6060f1SDimitry Andric } 393fe6060f1SDimitry Andric }); 394fe6060f1SDimitry Andric continue; 395fe6060f1SDimitry Andric break; 396fe6060f1SDimitry Andric } 397fe6060f1SDimitry Andric 398fe6060f1SDimitry Andric // Get the symbol name. 399fe6060f1SDimitry Andric auto Name = Sym.getName(*StringTab); 400fe6060f1SDimitry Andric if (!Name) 401fe6060f1SDimitry Andric return Name.takeError(); 402fe6060f1SDimitry Andric 403fe6060f1SDimitry Andric // Handle common symbols specially. 404fe6060f1SDimitry Andric if (Sym.isCommon()) { 405*04eeddc0SDimitry Andric Symbol &GSym = G->addCommonSymbol(*Name, Scope::Default, 406*04eeddc0SDimitry Andric getCommonSection(), orc::ExecutorAddr(), 407fe6060f1SDimitry Andric Sym.st_size, Sym.getValue(), false); 408fe6060f1SDimitry Andric setGraphSymbol(SymIndex, GSym); 409fe6060f1SDimitry Andric continue; 410fe6060f1SDimitry Andric } 411fe6060f1SDimitry Andric 412fe6060f1SDimitry Andric // Map Visibility and Binding to Scope and Linkage: 413fe6060f1SDimitry Andric Linkage L; 414fe6060f1SDimitry Andric Scope S; 415fe6060f1SDimitry Andric 416fe6060f1SDimitry Andric if (auto LSOrErr = getSymbolLinkageAndScope(Sym, *Name)) 417fe6060f1SDimitry Andric std::tie(L, S) = *LSOrErr; 418fe6060f1SDimitry Andric else 419fe6060f1SDimitry Andric return LSOrErr.takeError(); 420fe6060f1SDimitry Andric 421fe6060f1SDimitry Andric if (Sym.isDefined() && 422fe6060f1SDimitry Andric (Sym.getType() == ELF::STT_NOTYPE || Sym.getType() == ELF::STT_FUNC || 423fe6060f1SDimitry Andric Sym.getType() == ELF::STT_OBJECT || 424349cc55cSDimitry Andric Sym.getType() == ELF::STT_SECTION || Sym.getType() == ELF::STT_TLS)) { 4254824e7fdSDimitry Andric // Handle extended tables. 4264824e7fdSDimitry Andric unsigned Shndx = Sym.st_shndx; 4274824e7fdSDimitry Andric if (Shndx == ELF::SHN_XINDEX) { 4284824e7fdSDimitry Andric auto ShndxTable = ShndxTables.find(SymTabSec); 4294824e7fdSDimitry Andric if (ShndxTable == ShndxTables.end()) 4304824e7fdSDimitry Andric continue; 4314824e7fdSDimitry Andric auto NdxOrErr = object::getExtendedSymbolTableIndex<ELFT>( 4324824e7fdSDimitry Andric Sym, SymIndex, ShndxTable->second); 4334824e7fdSDimitry Andric if (!NdxOrErr) 4344824e7fdSDimitry Andric return NdxOrErr.takeError(); 4354824e7fdSDimitry Andric Shndx = *NdxOrErr; 4364824e7fdSDimitry Andric } 437*04eeddc0SDimitry Andric if (auto *B = getGraphBlock(Shndx)) { 438fe6060f1SDimitry Andric LLVM_DEBUG({ 439fe6060f1SDimitry Andric dbgs() << " " << SymIndex 440fe6060f1SDimitry Andric << ": Creating defined graph symbol for ELF symbol \"" << *Name 441fe6060f1SDimitry Andric << "\"\n"; 442fe6060f1SDimitry Andric }); 443fe6060f1SDimitry Andric 444*04eeddc0SDimitry Andric // In RISCV, temporary symbols (Used to generate dwarf, eh_frame 445*04eeddc0SDimitry Andric // sections...) will appear in object code's symbol table, and LLVM does 446*04eeddc0SDimitry Andric // not use names on these temporary symbols (RISCV gnu toolchain uses 447*04eeddc0SDimitry Andric // names on these temporary symbols). If the symbol is unnamed, add an 448*04eeddc0SDimitry Andric // anonymous symbol. 449fe6060f1SDimitry Andric auto &GSym = 450*04eeddc0SDimitry Andric Name->empty() 451*04eeddc0SDimitry Andric ? G->addAnonymousSymbol(*B, Sym.getValue(), Sym.st_size, 452*04eeddc0SDimitry Andric false, false) 453*04eeddc0SDimitry Andric : G->addDefinedSymbol(*B, Sym.getValue(), *Name, Sym.st_size, L, 454*04eeddc0SDimitry Andric S, Sym.getType() == ELF::STT_FUNC, false); 455fe6060f1SDimitry Andric setGraphSymbol(SymIndex, GSym); 456fe6060f1SDimitry Andric } 457fe6060f1SDimitry Andric } else if (Sym.isUndefined() && Sym.isExternal()) { 458fe6060f1SDimitry Andric LLVM_DEBUG({ 459fe6060f1SDimitry Andric dbgs() << " " << SymIndex 460fe6060f1SDimitry Andric << ": Creating external graph symbol for ELF symbol \"" << *Name 461fe6060f1SDimitry Andric << "\"\n"; 462fe6060f1SDimitry Andric }); 463fe6060f1SDimitry Andric auto &GSym = G->addExternalSymbol(*Name, Sym.st_size, L); 464fe6060f1SDimitry Andric setGraphSymbol(SymIndex, GSym); 465fe6060f1SDimitry Andric } else { 466fe6060f1SDimitry Andric LLVM_DEBUG({ 467fe6060f1SDimitry Andric dbgs() << " " << SymIndex 468fe6060f1SDimitry Andric << ": Not creating graph symbol for ELF symbol \"" << *Name 469fe6060f1SDimitry Andric << "\" with unrecognized type\n"; 470fe6060f1SDimitry Andric }); 471fe6060f1SDimitry Andric } 472fe6060f1SDimitry Andric } 473fe6060f1SDimitry Andric 474fe6060f1SDimitry Andric return Error::success(); 475fe6060f1SDimitry Andric } 476fe6060f1SDimitry Andric 477349cc55cSDimitry Andric template <typename ELFT> 478349cc55cSDimitry Andric template <typename RelocHandlerFunction> 479349cc55cSDimitry Andric Error ELFLinkGraphBuilder<ELFT>::forEachRelocation( 480349cc55cSDimitry Andric const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func, 481349cc55cSDimitry Andric bool ProcessDebugSections) { 482349cc55cSDimitry Andric 483349cc55cSDimitry Andric // Only look into sections that store relocation entries. 484349cc55cSDimitry Andric if (RelSect.sh_type != ELF::SHT_RELA && RelSect.sh_type != ELF::SHT_REL) 485349cc55cSDimitry Andric return Error::success(); 486349cc55cSDimitry Andric 487349cc55cSDimitry Andric // sh_info contains the section header index of the target (FixupSection), 488349cc55cSDimitry Andric // which is the section to which all relocations in RelSect apply. 489349cc55cSDimitry Andric auto FixupSection = Obj.getSection(RelSect.sh_info); 490349cc55cSDimitry Andric if (!FixupSection) 491349cc55cSDimitry Andric return FixupSection.takeError(); 492349cc55cSDimitry Andric 493349cc55cSDimitry Andric // Target sections have names in valid ELF object files. 494349cc55cSDimitry Andric Expected<StringRef> Name = Obj.getSectionName(**FixupSection); 495349cc55cSDimitry Andric if (!Name) 496349cc55cSDimitry Andric return Name.takeError(); 497349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << " " << *Name << ":\n"); 498349cc55cSDimitry Andric 499349cc55cSDimitry Andric // Consider skipping these relocations. 500349cc55cSDimitry Andric if (!ProcessDebugSections && isDwarfSection(*Name)) { 501349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << " skipped (dwarf section)\n\n"); 502349cc55cSDimitry Andric return Error::success(); 503349cc55cSDimitry Andric } 504349cc55cSDimitry Andric 505349cc55cSDimitry Andric // Lookup the link-graph node corresponding to the target section name. 506*04eeddc0SDimitry Andric auto *BlockToFix = getGraphBlock(RelSect.sh_info); 507*04eeddc0SDimitry Andric if (!BlockToFix) 508349cc55cSDimitry Andric return make_error<StringError>( 509349cc55cSDimitry Andric "Refencing a section that wasn't added to the graph: " + *Name, 510349cc55cSDimitry Andric inconvertibleErrorCode()); 511349cc55cSDimitry Andric 512349cc55cSDimitry Andric auto RelEntries = Obj.relas(RelSect); 513349cc55cSDimitry Andric if (!RelEntries) 514349cc55cSDimitry Andric return RelEntries.takeError(); 515349cc55cSDimitry Andric 516349cc55cSDimitry Andric // Let the callee process relocation entries one by one. 517349cc55cSDimitry Andric for (const typename ELFT::Rela &R : *RelEntries) 518*04eeddc0SDimitry Andric if (Error Err = Func(R, **FixupSection, *BlockToFix)) 519349cc55cSDimitry Andric return Err; 520349cc55cSDimitry Andric 521349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 522349cc55cSDimitry Andric return Error::success(); 523349cc55cSDimitry Andric } 524349cc55cSDimitry Andric 525fe6060f1SDimitry Andric } // end namespace jitlink 526fe6060f1SDimitry Andric } // end namespace llvm 527fe6060f1SDimitry Andric 528fe6060f1SDimitry Andric #undef DEBUG_TYPE 529fe6060f1SDimitry Andric 530fe6060f1SDimitry Andric #endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H 531