brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.4 KiB · 8dd176c Raw
700 lines · c
1//===------- ELFLinkGraphBuilder.h - ELF LinkGraph builder ------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Generic ELF LinkGraph building code.10//11//===----------------------------------------------------------------------===//12 13#ifndef LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H14#define LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H15 16#include "llvm/ExecutionEngine/JITLink/JITLink.h"17#include "llvm/Object/ELF.h"18#include "llvm/Support/Debug.h"19#include "llvm/Support/Error.h"20#include "llvm/Support/FormatVariadic.h"21 22#define DEBUG_TYPE "jitlink"23 24namespace llvm {25namespace jitlink {26 27/// Common link-graph building code shared between all ELFFiles.28class ELFLinkGraphBuilderBase {29public:30  ELFLinkGraphBuilderBase(std::unique_ptr<LinkGraph> G) : G(std::move(G)) {}31  virtual ~ELFLinkGraphBuilderBase();32 33protected:34  static bool isDwarfSection(StringRef SectionName) {35    return llvm::is_contained(DwarfSectionNames, SectionName);36  }37 38  Section &getCommonSection() {39    if (!CommonSection)40      CommonSection = &G->createSection(41          CommonSectionName, orc::MemProt::Read | orc::MemProt::Write);42    return *CommonSection;43  }44 45  std::unique_ptr<LinkGraph> G;46 47private:48  static StringRef CommonSectionName;49  static ArrayRef<const char *> DwarfSectionNames;50 51  Section *CommonSection = nullptr;52};53 54/// LinkGraph building code that's specific to the given ELFT, but common55/// across all architectures.56template <typename ELFT>57class ELFLinkGraphBuilder : public ELFLinkGraphBuilderBase {58  using ELFFile = object::ELFFile<ELFT>;59 60public:61  ELFLinkGraphBuilder(const object::ELFFile<ELFT> &Obj,62                      std::shared_ptr<orc::SymbolStringPool> SSP, Triple TT,63                      SubtargetFeatures Features, StringRef FileName,64                      LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);65 66  /// Debug sections are included in the graph by default. Use67  /// setProcessDebugSections(false) to ignore them if debug info is not68  /// needed.69  ELFLinkGraphBuilder &setProcessDebugSections(bool ProcessDebugSections) {70    this->ProcessDebugSections = ProcessDebugSections;71    return *this;72  }73 74  /// Attempt to construct and return the LinkGraph.75  Expected<std::unique_ptr<LinkGraph>> buildGraph();76 77  /// Call to derived class to handle relocations. These require78  /// architecture specific knowledge to map to JITLink edge kinds.79  virtual Error addRelocations() = 0;80 81protected:82  using ELFSectionIndex = unsigned;83  using ELFSymbolIndex = unsigned;84 85  bool isRelocatable() const {86    return Obj.getHeader().e_type == llvm::ELF::ET_REL;87  }88 89  void setGraphBlock(ELFSectionIndex SecIndex, Block *B) {90    assert(!GraphBlocks.count(SecIndex) && "Duplicate section at index");91    GraphBlocks[SecIndex] = B;92  }93 94  Block *getGraphBlock(ELFSectionIndex SecIndex) {95    return GraphBlocks.lookup(SecIndex);96  }97 98  void setGraphSymbol(ELFSymbolIndex SymIndex, Symbol &Sym) {99    assert(!GraphSymbols.count(SymIndex) && "Duplicate symbol at index");100    GraphSymbols[SymIndex] = &Sym;101  }102 103  Symbol *getGraphSymbol(ELFSymbolIndex SymIndex) {104    return GraphSymbols.lookup(SymIndex);105  }106 107  Expected<std::pair<Linkage, Scope>>108  getSymbolLinkageAndScope(const typename ELFT::Sym &Sym, StringRef Name);109 110  /// Set the target flags on the given Symbol.111  virtual TargetFlagsType makeTargetFlags(const typename ELFT::Sym &Sym) {112    return TargetFlagsType{};113  }114 115  /// Get the physical offset of the symbol on the target platform.116  virtual orc::ExecutorAddrDiff getRawOffset(const typename ELFT::Sym &Sym,117                                             TargetFlagsType Flags) {118    return Sym.getValue();119  }120 121  Error prepare();122  Error graphifySections();123  Error graphifySymbols();124 125  /// Override in derived classes to suppress certain sections in the link126  /// graph.127  virtual bool excludeSection(const typename ELFT::Shdr &Sect) const {128    return false;129  }130 131  /// Traverse all matching ELFT::Rela relocation records in the given section.132  /// The handler function Func should be callable with this signature:133  ///   Error(const typename ELFT::Rela &,134  ///         const typename ELFT::Shdr &, Section &)135  ///136  template <typename RelocHandlerMethod>137  Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,138                              RelocHandlerMethod &&Func);139 140  /// Traverse all matching ELFT::Rel relocation records in the given section.141  /// The handler function Func should be callable with this signature:142  ///   Error(const typename ELFT::Rel &,143  ///         const typename ELFT::Shdr &, Section &)144  ///145  template <typename RelocHandlerMethod>146  Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,147                             RelocHandlerMethod &&Func);148 149  /// Traverse all matching rela relocation records in the given section.150  /// Convenience wrapper to allow passing a member function for the handler.151  ///152  template <typename ClassT, typename RelocHandlerMethod>153  Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,154                              ClassT *Instance, RelocHandlerMethod &&Method) {155    return forEachRelaRelocation(156        RelSect,157        [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {158          return (Instance->*Method)(Rel, Target, GS);159        });160  }161 162  /// Traverse all matching rel relocation records in the given section.163  /// Convenience wrapper to allow passing a member function for the handler.164  ///165  template <typename ClassT, typename RelocHandlerMethod>166  Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,167                             ClassT *Instance, RelocHandlerMethod &&Method) {168    return forEachRelRelocation(169        RelSect,170        [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {171          return (Instance->*Method)(Rel, Target, GS);172        });173  }174 175  const ELFFile &Obj;176 177  typename ELFFile::Elf_Shdr_Range Sections;178  const typename ELFFile::Elf_Shdr *SymTabSec = nullptr;179  StringRef SectionStringTab;180  bool ProcessDebugSections = true;181 182  // Maps ELF section indexes to LinkGraph Blocks.183  // Only SHF_ALLOC sections will have graph blocks.184  DenseMap<ELFSectionIndex, Block *> GraphBlocks;185  DenseMap<ELFSymbolIndex, Symbol *> GraphSymbols;186  DenseMap<const typename ELFFile::Elf_Shdr *,187           ArrayRef<typename ELFFile::Elf_Word>>188      ShndxTables;189};190 191template <typename ELFT>192ELFLinkGraphBuilder<ELFT>::ELFLinkGraphBuilder(193    const ELFFile &Obj, std::shared_ptr<orc::SymbolStringPool> SSP, Triple TT,194    SubtargetFeatures Features, StringRef FileName,195    LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)196    : ELFLinkGraphBuilderBase(std::make_unique<LinkGraph>(197          FileName.str(), std::move(SSP), std::move(TT), std::move(Features),198          std::move(GetEdgeKindName))),199      Obj(Obj) {200  LLVM_DEBUG(201      { dbgs() << "Created ELFLinkGraphBuilder for \"" << FileName << "\""; });202}203 204template <typename ELFT>205Expected<std::unique_ptr<LinkGraph>> ELFLinkGraphBuilder<ELFT>::buildGraph() {206  if (!isRelocatable())207    return make_error<JITLinkError>("Object is not a relocatable ELF file");208 209  if (auto Err = prepare())210    return std::move(Err);211 212  if (auto Err = graphifySections())213    return std::move(Err);214 215  if (auto Err = graphifySymbols())216    return std::move(Err);217 218  if (auto Err = addRelocations())219    return std::move(Err);220 221  return std::move(G);222}223 224template <typename ELFT>225Expected<std::pair<Linkage, Scope>>226ELFLinkGraphBuilder<ELFT>::getSymbolLinkageAndScope(227    const typename ELFT::Sym &Sym, StringRef Name) {228  Linkage L = Linkage::Strong;229  Scope S = Scope::Default;230 231  switch (Sym.getBinding()) {232  case ELF::STB_LOCAL:233    S = Scope::Local;234    break;235  case ELF::STB_GLOBAL:236    // Nothing to do here.237    break;238  case ELF::STB_WEAK:239  case ELF::STB_GNU_UNIQUE:240    L = Linkage::Weak;241    break;242  default:243    return make_error<StringError>(244        "Unrecognized symbol binding " +245            Twine(static_cast<int>(Sym.getBinding())) + " for " + Name,246        inconvertibleErrorCode());247  }248 249  switch (Sym.getVisibility()) {250  case ELF::STV_DEFAULT:251  case ELF::STV_PROTECTED:252    // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs253    // Orc support.254    // Otherwise nothing to do here.255    break;256  case ELF::STV_HIDDEN:257    // Default scope -> Hidden scope. No effect on local scope.258    if (S == Scope::Default)259      S = Scope::Hidden;260    break;261  case ELF::STV_INTERNAL:262    return make_error<StringError>(263        "Unrecognized symbol visibility " +264            Twine(static_cast<int>(Sym.getVisibility())) + " for " + Name,265        inconvertibleErrorCode());266  }267 268  return std::make_pair(L, S);269}270 271template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::prepare() {272  LLVM_DEBUG(dbgs() << "  Preparing to build...\n");273 274  // Get the sections array.275  if (auto SectionsOrErr = Obj.sections())276    Sections = *SectionsOrErr;277  else278    return SectionsOrErr.takeError();279 280  // Get the section string table.281  if (auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))282    SectionStringTab = *SectionStringTabOrErr;283  else284    return SectionStringTabOrErr.takeError();285 286  // Get the SHT_SYMTAB section.287  for (auto &Sec : Sections) {288    if (Sec.sh_type == ELF::SHT_SYMTAB) {289      if (!SymTabSec)290        SymTabSec = &Sec;291      else292        return make_error<JITLinkError>("Multiple SHT_SYMTAB sections in " +293                                        G->getName());294    }295 296    // Extended table.297    if (Sec.sh_type == ELF::SHT_SYMTAB_SHNDX) {298      uint32_t SymtabNdx = Sec.sh_link;299      if (SymtabNdx >= Sections.size())300        return make_error<JITLinkError>("sh_link is out of bound");301 302      auto ShndxTable = Obj.getSHNDXTable(Sec);303      if (!ShndxTable)304        return ShndxTable.takeError();305 306      ShndxTables.insert({&Sections[SymtabNdx], *ShndxTable});307    }308  }309 310  return Error::success();311}312 313template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() {314  LLVM_DEBUG(dbgs() << "  Creating graph sections...\n");315 316  // For each section...317  for (ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {318 319    auto &Sec = Sections[SecIndex];320 321    // Start by getting the section name.322    auto Name = Obj.getSectionName(Sec, SectionStringTab);323    if (!Name)324      return Name.takeError();325    if (excludeSection(Sec)) {326      LLVM_DEBUG({327        dbgs() << "    " << SecIndex << ": Skipping section \"" << *Name328               << "\" explicitly\n";329      });330      continue;331    }332 333    // Skip null sections.334    if (Sec.sh_type == ELF::SHT_NULL) {335      LLVM_DEBUG({336        dbgs() << "    " << SecIndex << ": has type SHT_NULL. Skipping.\n";337      });338      continue;339    }340 341    // If the name indicates that it's a debug section then skip it: We don't342    // support those yet.343    if (!ProcessDebugSections && isDwarfSection(*Name)) {344      LLVM_DEBUG({345        dbgs() << "    " << SecIndex << ": \"" << *Name346               << "\" is a debug section: "347                  "No graph section will be created.\n";348      });349      continue;350    }351 352    LLVM_DEBUG({353      dbgs() << "    " << SecIndex << ": Creating section for \"" << *Name354             << "\"\n";355    });356 357    // Get the section's memory protection flags.358    orc::MemProt Prot = orc::MemProt::Read;359    if (Sec.sh_flags & ELF::SHF_EXECINSTR)360      Prot |= orc::MemProt::Exec;361    if (Sec.sh_flags & ELF::SHF_WRITE)362      Prot |= orc::MemProt::Write;363 364    // Look for existing sections first.365    auto *GraphSec = G->findSectionByName(*Name);366    if (!GraphSec) {367      GraphSec = &G->createSection(*Name, Prot);368      // Non-SHF_ALLOC sections get NoAlloc memory lifetimes.369      if (!(Sec.sh_flags & ELF::SHF_ALLOC)) {370        GraphSec->setMemLifetime(orc::MemLifetime::NoAlloc);371        LLVM_DEBUG({372          dbgs() << "      " << SecIndex << ": \"" << *Name373                 << "\" is not a SHF_ALLOC section. Using NoAlloc lifetime.\n";374        });375      }376    }377 378    if (GraphSec->getMemProt() != Prot) {379      std::string ErrMsg;380      raw_string_ostream(ErrMsg)381          << "In " << G->getName() << ", section " << *Name382          << " is present more than once with different permissions: "383          << GraphSec->getMemProt() << " vs " << Prot;384      return make_error<JITLinkError>(std::move(ErrMsg));385    }386 387    Block *B = nullptr;388    if (Sec.sh_type != ELF::SHT_NOBITS) {389      auto Data = Obj.template getSectionContentsAsArray<char>(Sec);390      if (!Data)391        return Data.takeError();392 393      B = &G->createContentBlock(*GraphSec, *Data,394                                 orc::ExecutorAddr(Sec.sh_addr),395                                 Sec.sh_addralign, 0);396    } else397      B = &G->createZeroFillBlock(*GraphSec, Sec.sh_size,398                                  orc::ExecutorAddr(Sec.sh_addr),399                                  Sec.sh_addralign, 0);400 401    if (Sec.sh_type == ELF::SHT_ARM_EXIDX) {402      // Add live symbol to avoid dead-stripping for .ARM.exidx sections403      G->addAnonymousSymbol(*B, orc::ExecutorAddrDiff(),404                            orc::ExecutorAddrDiff(), false, true);405    }406 407    setGraphBlock(SecIndex, B);408  }409 410  return Error::success();411}412 413template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {414  LLVM_DEBUG(dbgs() << "  Creating graph symbols...\n");415 416  // No SYMTAB -- Bail out early.417  if (!SymTabSec)418    return Error::success();419 420  // Get the section content as a Symbols array.421  auto Symbols = Obj.symbols(SymTabSec);422  if (!Symbols)423    return Symbols.takeError();424 425  // Get the string table for this section.426  auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);427  if (!StringTab)428    return StringTab.takeError();429 430  LLVM_DEBUG({431    StringRef SymTabName;432 433    if (auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))434      SymTabName = *SymTabNameOrErr;435    else {436      dbgs() << "Could not get ELF SHT_SYMTAB section name for logging: "437             << toString(SymTabNameOrErr.takeError()) << "\n";438      SymTabName = "<SHT_SYMTAB section with invalid name>";439    }440 441    dbgs() << "    Adding symbols from symtab section \"" << SymTabName442           << "\"\n";443  });444 445  for (ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {446    auto &Sym = (*Symbols)[SymIndex];447 448    // Check symbol type.449    switch (Sym.getType()) {450    case ELF::STT_FILE:451      LLVM_DEBUG({452        if (auto Name = Sym.getName(*StringTab))453          dbgs() << "      " << SymIndex << ": Skipping STT_FILE symbol \""454                 << *Name << "\"\n";455        else {456          dbgs() << "Could not get STT_FILE symbol name: "457                 << toString(Name.takeError()) << "\n";458          dbgs() << "     " << SymIndex459                 << ": Skipping STT_FILE symbol with invalid name\n";460        }461      });462      continue;463      break;464    }465 466    // Get the symbol name.467    auto Name = Sym.getName(*StringTab);468    if (!Name)469      return Name.takeError();470 471    // Handle common symbols specially.472    if (Sym.isCommon()) {473      Symbol &GSym = G->addDefinedSymbol(474          G->createZeroFillBlock(getCommonSection(), Sym.st_size,475                                 orc::ExecutorAddr(), Sym.getValue(), 0),476          0, *Name, Sym.st_size, Linkage::Weak, Scope::Default, false, false);477      setGraphSymbol(SymIndex, GSym);478      continue;479    }480 481    if (Sym.isDefined() &&482        (Sym.getType() == ELF::STT_NOTYPE || Sym.getType() == ELF::STT_FUNC ||483         Sym.getType() == ELF::STT_OBJECT ||484         Sym.getType() == ELF::STT_SECTION || Sym.getType() == ELF::STT_TLS)) {485 486      // Map Visibility and Binding to Scope and Linkage:487      Linkage L;488      Scope S;489      if (auto LSOrErr = getSymbolLinkageAndScope(Sym, *Name))490        std::tie(L, S) = *LSOrErr;491      else492        return LSOrErr.takeError();493 494      // Handle extended tables.495      unsigned Shndx = Sym.st_shndx;496      if (Shndx == ELF::SHN_XINDEX) {497        auto ShndxTable = ShndxTables.find(SymTabSec);498        if (ShndxTable == ShndxTables.end())499          continue;500        auto NdxOrErr = object::getExtendedSymbolTableIndex<ELFT>(501            Sym, SymIndex, ShndxTable->second);502        if (!NdxOrErr)503          return NdxOrErr.takeError();504        Shndx = *NdxOrErr;505      }506      if (auto *B = getGraphBlock(Shndx)) {507        LLVM_DEBUG({508          dbgs() << "      " << SymIndex509                 << ": Creating defined graph symbol for ELF symbol \"" << *Name510                 << "\"\n";511        });512 513        TargetFlagsType Flags = makeTargetFlags(Sym);514        orc::ExecutorAddrDiff Offset = getRawOffset(Sym, Flags);515 516        if (Offset + Sym.st_size > B->getSize()) {517          std::string ErrMsg;518          raw_string_ostream ErrStream(ErrMsg);519          ErrStream << "In " << G->getName() << ", symbol ";520          if (!Name->empty())521            ErrStream << *Name;522          else523            ErrStream << "<anon>";524          ErrStream << " (" << (B->getAddress() + Offset) << " -- "525                    << (B->getAddress() + Offset + Sym.st_size) << ") extends "526                    << formatv("{0:x}", Offset + Sym.st_size - B->getSize())527                    << " bytes past the end of its containing block ("528                    << B->getRange() << ")";529          return make_error<JITLinkError>(std::move(ErrMsg));530        }531 532        // In RISCV, temporary symbols (Used to generate dwarf, eh_frame533        // sections...) will appear in object code's symbol table, and LLVM does534        // not use names on these temporary symbols (RISCV gnu toolchain uses535        // names on these temporary symbols). If the symbol is unnamed, add an536        // anonymous symbol.537        auto &GSym =538            Name->empty()539                ? G->addAnonymousSymbol(*B, Offset, Sym.st_size,540                                        false, false)541                : G->addDefinedSymbol(*B, Offset, *Name, Sym.st_size, L,542                                      S, Sym.getType() == ELF::STT_FUNC,543                                      false);544 545        GSym.setTargetFlags(Flags);546        setGraphSymbol(SymIndex, GSym);547      }548    } else if (Sym.isUndefined() && Sym.isExternal()) {549      LLVM_DEBUG({550        dbgs() << "      " << SymIndex551               << ": Creating external graph symbol for ELF symbol \"" << *Name552               << "\"\n";553      });554 555      if (Sym.getBinding() != ELF::STB_GLOBAL &&556          Sym.getBinding() != ELF::STB_WEAK)557        return make_error<StringError>(558            "Invalid symbol binding " +559                Twine(static_cast<int>(Sym.getBinding())) +560                " for external symbol " + *Name,561            inconvertibleErrorCode());562 563      // If L is Linkage::Weak that means this is a weakly referenced symbol.564      auto &GSym = G->addExternalSymbol(*Name, Sym.st_size,565                                        Sym.getBinding() == ELF::STB_WEAK);566      setGraphSymbol(SymIndex, GSym);567    } else if (Sym.isUndefined() && Sym.st_value == 0 && Sym.st_size == 0 &&568               Sym.getType() == ELF::STT_NOTYPE &&569               Sym.getBinding() == ELF::STB_LOCAL && Name->empty()) {570      // Some relocations (e.g., R_RISCV_ALIGN) don't have a target symbol and571      // use this kind of null symbol as a placeholder.572      LLVM_DEBUG({573        dbgs() << "      " << SymIndex << ": Creating null graph symbol\n";574      });575 576      auto SymName =577          G->allocateContent("__jitlink_ELF_SYM_UND_" + Twine(SymIndex));578      auto SymNameRef = StringRef(SymName.data(), SymName.size());579      auto &GSym = G->addAbsoluteSymbol(SymNameRef, orc::ExecutorAddr(0), 0,580                                        Linkage::Strong, Scope::Local, false);581      setGraphSymbol(SymIndex, GSym);582    } else {583      LLVM_DEBUG({584        dbgs() << "      " << SymIndex585               << ": Not creating graph symbol for ELF symbol \"" << *Name586               << "\" with unrecognized type\n";587      });588    }589  }590 591  return Error::success();592}593 594template <typename ELFT>595template <typename RelocHandlerFunction>596Error ELFLinkGraphBuilder<ELFT>::forEachRelaRelocation(597    const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {598  // Only look into sections that store relocation entries.599  if (RelSect.sh_type != ELF::SHT_RELA)600    return Error::success();601 602  // sh_info contains the section header index of the target (FixupSection),603  // which is the section to which all relocations in RelSect apply.604  auto FixupSection = Obj.getSection(RelSect.sh_info);605  if (!FixupSection)606    return FixupSection.takeError();607 608  // Target sections have names in valid ELF object files.609  Expected<StringRef> Name = Obj.getSectionName(**FixupSection);610  if (!Name)611    return Name.takeError();612  LLVM_DEBUG(dbgs() << "  " << *Name << ":\n");613 614  // Consider skipping these relocations.615  if (!ProcessDebugSections && isDwarfSection(*Name)) {616    LLVM_DEBUG(dbgs() << "    skipped (dwarf section)\n\n");617    return Error::success();618  }619  if (excludeSection(**FixupSection)) {620    LLVM_DEBUG(dbgs() << "    skipped (fixup section excluded explicitly)\n\n");621    return Error::success();622  }623 624  // Lookup the link-graph node corresponding to the target section name.625  auto *BlockToFix = getGraphBlock(RelSect.sh_info);626  if (!BlockToFix)627    return make_error<StringError>(628        "Refencing a section that wasn't added to the graph: " + *Name,629        inconvertibleErrorCode());630 631  auto RelEntries = Obj.relas(RelSect);632  if (!RelEntries)633    return RelEntries.takeError();634 635  // Let the callee process relocation entries one by one.636  for (const typename ELFT::Rela &R : *RelEntries)637    if (Error Err = Func(R, **FixupSection, *BlockToFix))638      return Err;639 640  LLVM_DEBUG(dbgs() << "\n");641  return Error::success();642}643 644template <typename ELFT>645template <typename RelocHandlerFunction>646Error ELFLinkGraphBuilder<ELFT>::forEachRelRelocation(647    const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func) {648  // Only look into sections that store relocation entries.649  if (RelSect.sh_type != ELF::SHT_REL)650    return Error::success();651 652  // sh_info contains the section header index of the target (FixupSection),653  // which is the section to which all relocations in RelSect apply.654  auto FixupSection = Obj.getSection(RelSect.sh_info);655  if (!FixupSection)656    return FixupSection.takeError();657 658  // Target sections have names in valid ELF object files.659  Expected<StringRef> Name = Obj.getSectionName(**FixupSection);660  if (!Name)661    return Name.takeError();662  LLVM_DEBUG(dbgs() << "  " << *Name << ":\n");663 664  // Consider skipping these relocations.665  if (!ProcessDebugSections && isDwarfSection(*Name)) {666    LLVM_DEBUG(dbgs() << "    skipped (dwarf section)\n\n");667    return Error::success();668  }669  if (excludeSection(**FixupSection)) {670    LLVM_DEBUG(dbgs() << "    skipped (fixup section excluded explicitly)\n\n");671    return Error::success();672  }673 674  // Lookup the link-graph node corresponding to the target section name.675  auto *BlockToFix = getGraphBlock(RelSect.sh_info);676  if (!BlockToFix)677    return make_error<StringError>(678        "Refencing a section that wasn't added to the graph: " + *Name,679        inconvertibleErrorCode());680 681  auto RelEntries = Obj.rels(RelSect);682  if (!RelEntries)683    return RelEntries.takeError();684 685  // Let the callee process relocation entries one by one.686  for (const typename ELFT::Rel &R : *RelEntries)687    if (Error Err = Func(R, **FixupSection, *BlockToFix))688      return Err;689 690  LLVM_DEBUG(dbgs() << "\n");691  return Error::success();692}693 694} // end namespace jitlink695} // end namespace llvm696 697#undef DEBUG_TYPE698 699#endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H700