[llvm] 8e66fc4 - [JITLink][ELF] Move ELF section and symbol parsing into ELFLinkGraphBuilder.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 28 17:07:39 PDT 2021


Author: Lang Hames
Date: 2021-06-29T09:59:49+10:00
New Revision: 8e66fc438463e8cf6fa05e88b51ce29b604ce307

URL: https://github.com/llvm/llvm-project/commit/8e66fc438463e8cf6fa05e88b51ce29b604ce307
DIFF: https://github.com/llvm/llvm-project/commit/8e66fc438463e8cf6fa05e88b51ce29b604ce307.diff

LOG: [JITLink][ELF] Move ELF section and symbol parsing into ELFLinkGraphBuilder.

Move architecture independent ELF parsing/graph-building code from
ELFLinkGraphBuilder_x86_64 to the ELFLinkGraphBuilder base class template.

Added: 
    

Modified: 
    llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.cpp
    llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
    llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
    llvm/test/ExecutionEngine/JITLink/X86/ELF_skip_debug_sections.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.cpp b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.cpp
index d1e221b2145b2..2194a4fbf1f41 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.cpp
@@ -14,9 +14,19 @@
 
 #define DEBUG_TYPE "jitlink"
 
+static const char *DWSecNames[] = {
+#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
+  ELF_NAME,
+#include "llvm/BinaryFormat/Dwarf.def"
+#undef HANDLE_DWARF_SECTION
+};
+
 namespace llvm {
 namespace jitlink {
 
+StringRef ELFLinkGraphBuilderBase::CommonSectionName(".common");
+ArrayRef<const char *> ELFLinkGraphBuilderBase::DwarfSectionNames = DWSecNames;
+
 ELFLinkGraphBuilderBase::~ELFLinkGraphBuilderBase() {}
 
 } // end namespace jitlink

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
index 0841bdb621657..2b2a1a8db4c1d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
+++ b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
@@ -15,7 +15,11 @@
 
 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
 #include "llvm/Object/ELF.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/FormatVariadic.h"
+
+#define DEBUG_TYPE "jitlink"
 
 namespace llvm {
 namespace jitlink {
@@ -23,34 +27,403 @@ namespace jitlink {
 /// Common link-graph building code shared between all ELFFiles.
 class ELFLinkGraphBuilderBase {
 public:
+  ELFLinkGraphBuilderBase(std::unique_ptr<LinkGraph> G) : G(std::move(G)) {}
   virtual ~ELFLinkGraphBuilderBase();
+
+protected:
+  static bool isDwarfSection(StringRef SectionName) {
+    return llvm::is_contained(DwarfSectionNames, SectionName);
+  }
+
+  Section &getCommonSection() {
+    if (!CommonSection) {
+      auto Prot = static_cast<sys::Memory::ProtectionFlags>(
+          sys::Memory::MF_READ | sys::Memory::MF_WRITE);
+      CommonSection = &G->createSection(CommonSectionName, Prot);
+    }
+    return *CommonSection;
+  }
+
+  std::unique_ptr<LinkGraph> G;
+
+private:
+  static StringRef CommonSectionName;
+  static ArrayRef<const char *> DwarfSectionNames;
+
+  Section *CommonSection = nullptr;
 };
 
 /// Ling-graph building code that's specific to the given ELFT, but common
 /// across all architectures.
 template <typename ELFT>
 class ELFLinkGraphBuilder : public ELFLinkGraphBuilderBase {
+  using ELFFile = object::ELFFile<ELFT>;
+
 public:
   ELFLinkGraphBuilder(const object::ELFFile<ELFT> &Obj, Triple TT,
                       StringRef FileName,
                       LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
 
+  /// Attempt to construct and return the LinkGraph.
+  Expected<std::unique_ptr<LinkGraph>> buildGraph();
+
+  /// Call to derived class to handle relocations. These require
+  /// architecture specific knowledge to map to JITLink edge kinds.
+  virtual Error addRelocations() = 0;
+
 protected:
-  std::unique_ptr<LinkGraph> G;
-  const object::ELFFile<ELFT> &Obj;
+  using ELFSectionIndex = unsigned;
+  using ELFSymbolIndex = unsigned;
+
+  bool isRelocatable() const {
+    return Obj.getHeader().e_type == llvm::ELF::ET_REL;
+  }
+
+  void setGraphSection(ELFSectionIndex SecIndex, Section &Sec) {
+    assert(!GraphSections.count(SecIndex) && "Duplicate section at index");
+    GraphSections[SecIndex] = &Sec;
+  }
+
+  Section *getGraphSection(ELFSectionIndex SecIndex) {
+    auto I = GraphSections.find(SecIndex);
+    if (I == GraphSections.end())
+      return nullptr;
+    return I->second;
+  }
+
+  void setGraphSymbol(ELFSymbolIndex SymIndex, Symbol &Sym) {
+    assert(!GraphSymbols.count(SymIndex) && "Duplicate symbol at index");
+    GraphSymbols[SymIndex] = &Sym;
+  }
+
+  Symbol *getGraphSymbol(ELFSymbolIndex SymIndex) {
+    auto I = GraphSymbols.find(SymIndex);
+    if (I == GraphSymbols.end())
+      return nullptr;
+    return I->second;
+  }
+
+  Expected<std::pair<Linkage, Scope>>
+  getSymbolLinkageAndScope(const typename ELFT::Sym &Sym, StringRef Name);
+
+  Error prepare();
+  Error graphifySections();
+  Error graphifySymbols();
+
+  const ELFFile &Obj;
+
+  typename ELFFile::Elf_Shdr_Range Sections;
+  const typename ELFFile::Elf_Shdr *SymTabSec = nullptr;
+  StringRef SectionStringTab;
+
+  // Maps ELF section indexes to LinkGraph Sections.
+  // Only SHF_ALLOC sections will have graph sections.
+  DenseMap<ELFSectionIndex, Section *> GraphSections;
+  DenseMap<ELFSymbolIndex, Symbol *> GraphSymbols;
 };
 
 template <typename ELFT>
 ELFLinkGraphBuilder<ELFT>::ELFLinkGraphBuilder(
-    const object::ELFFile<ELFT> &Obj, Triple TT, StringRef FileName,
+    const ELFFile &Obj, Triple TT, StringRef FileName,
     LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
-    : G(std::make_unique<LinkGraph>(FileName.str(), Triple(std::move(TT)),
-                                    ELFT::Is64Bits ? 8 : 4,
-                                    support::endianness(ELFT::TargetEndianness),
-                                    std::move(GetEdgeKindName))),
-      Obj(Obj) {}
+    : ELFLinkGraphBuilderBase(std::make_unique<LinkGraph>(
+          FileName.str(), Triple(std::move(TT)), ELFT::Is64Bits ? 8 : 4,
+          support::endianness(ELFT::TargetEndianness),
+          std::move(GetEdgeKindName))),
+      Obj(Obj) {
+  LLVM_DEBUG(
+      { dbgs() << "Created ELFLinkGraphBuilder for \"" << FileName << "\""; });
+}
+
+template <typename ELFT>
+Expected<std::unique_ptr<LinkGraph>> ELFLinkGraphBuilder<ELFT>::buildGraph() {
+  if (!isRelocatable())
+    return make_error<JITLinkError>("Object is not a relocatable ELF file");
+
+  if (auto Err = prepare())
+    return std::move(Err);
+
+  if (auto Err = graphifySections())
+    return std::move(Err);
+
+  if (auto Err = graphifySymbols())
+    return std::move(Err);
+
+  if (auto Err = addRelocations())
+    return std::move(Err);
+
+  return std::move(G);
+}
+
+template <typename ELFT>
+Expected<std::pair<Linkage, Scope>>
+ELFLinkGraphBuilder<ELFT>::getSymbolLinkageAndScope(
+    const typename ELFT::Sym &Sym, StringRef Name) {
+  Linkage L = Linkage::Strong;
+  Scope S = Scope::Default;
+
+  switch (Sym.getBinding()) {
+  case ELF::STB_LOCAL:
+    S = Scope::Local;
+    break;
+  case ELF::STB_GLOBAL:
+    // Nothing to do here.
+    break;
+  case ELF::STB_WEAK:
+    L = Linkage::Weak;
+    break;
+  default:
+    return make_error<StringError>("Unrecognized symbol binding for " + Name,
+                                   inconvertibleErrorCode());
+  }
+
+  switch (Sym.getVisibility()) {
+  case ELF::STV_DEFAULT:
+  case ELF::STV_PROTECTED:
+    // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs
+    // Orc support.
+    // Otherwise nothing to do here.
+    break;
+  case ELF::STV_HIDDEN:
+    // Default scope -> Hidden scope. No effect on local scope.
+    if (S == Scope::Default)
+      S = Scope::Hidden;
+    break;
+  case ELF::STV_INTERNAL:
+    return make_error<StringError>("Unrecognized symbol visibility for " + Name,
+                                   inconvertibleErrorCode());
+  }
+
+  return std::make_pair(L, S);
+}
+
+template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::prepare() {
+  LLVM_DEBUG(dbgs() << "  Preparing to build...\n");
+
+  // Get the sections array.
+  if (auto SectionsOrErr = Obj.sections())
+    Sections = *SectionsOrErr;
+  else
+    return SectionsOrErr.takeError();
+
+  // Get the section string table.
+  if (auto SectionStringTabOrErr = Obj.getSectionStringTable(Sections))
+    SectionStringTab = *SectionStringTabOrErr;
+  else
+    return SectionStringTabOrErr.takeError();
+
+  // Get the SHT_SYMTAB section.
+  for (auto &Sec : Sections)
+    if (Sec.sh_type == ELF::SHT_SYMTAB) {
+      if (!SymTabSec)
+        SymTabSec = &Sec;
+      else
+        return make_error<JITLinkError>("Multiple SHT_SYMTAB sections in " +
+                                        G->getName());
+    }
+
+  return Error::success();
+}
+
+template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() {
+  LLVM_DEBUG(dbgs() << "  Creating graph sections...\n");
+
+  // For each section...
+  for (ELFSectionIndex SecIndex = 0; SecIndex != Sections.size(); ++SecIndex) {
+
+    auto &Sec = Sections[SecIndex];
+
+    // Start by getting the section name.
+    auto Name = Obj.getSectionName(Sec, SectionStringTab);
+    if (!Name)
+      return Name.takeError();
+
+    // If the name indicates that it's a debug section then skip it: We don't
+    // support those yet.
+    if (isDwarfSection(*Name)) {
+      LLVM_DEBUG({
+        dbgs() << "    " << SecIndex << ": \"" << *Name
+               << "\" is a debug section: "
+                  "No graph section will be created.\n";
+      });
+      continue;
+    }
+
+    // Skip non-SHF_ALLOC sections
+    if (!(Sec.sh_flags & ELF::SHF_ALLOC)) {
+      LLVM_DEBUG({
+        dbgs() << "    " << SecIndex << ": \"" << *Name
+               << "\" is not an SHF_ALLOC section: "
+                  "No graph section will be created.\n";
+      });
+      continue;
+    }
+
+    LLVM_DEBUG({
+      dbgs() << "    " << SecIndex << ": Creating section for \"" << *Name
+             << "\"\n";
+    });
+
+    // Get the section's memory protection flags.
+    sys::Memory::ProtectionFlags Prot;
+    if (Sec.sh_flags & ELF::SHF_EXECINSTR)
+      Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
+                                                       sys::Memory::MF_EXEC);
+    else
+      Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
+                                                       sys::Memory::MF_WRITE);
+
+    // For now we just use this to skip the "undefined" section, probably need
+    // to revist.
+    if (Sec.sh_size == 0)
+      continue;
+
+    auto &GraphSec = G->createSection(*Name, Prot);
+    if (Sec.sh_type != ELF::SHT_NOBITS) {
+      auto Data = Obj.template getSectionContentsAsArray<char>(Sec);
+      if (!Data)
+        return Data.takeError();
+
+      G->createContentBlock(GraphSec, *Data, Sec.sh_addr, Sec.sh_addralign, 0);
+    } else
+      G->createZeroFillBlock(GraphSec, Sec.sh_size, Sec.sh_addr,
+                             Sec.sh_addralign, 0);
+
+    setGraphSection(SecIndex, GraphSec);
+  }
+
+  return Error::success();
+}
+
+template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
+  LLVM_DEBUG(dbgs() << "  Creating graph symbols...\n");
+
+  // No SYMTAB -- Bail out early.
+  if (!SymTabSec)
+    return Error::success();
+
+  // Get the section content as a Symbols array.
+  auto Symbols = Obj.symbols(SymTabSec);
+  if (!Symbols)
+    return Symbols.takeError();
+
+  // Get the string table for this section.
+  auto StringTab = Obj.getStringTableForSymtab(*SymTabSec, Sections);
+  if (!StringTab)
+    return StringTab.takeError();
+
+  LLVM_DEBUG({
+    StringRef SymTabName;
+
+    if (auto SymTabNameOrErr = Obj.getSectionName(*SymTabSec, SectionStringTab))
+      SymTabName = *SymTabNameOrErr;
+    else {
+      dbgs() << "Could not get ELF SHT_SYMTAB section name for logging: "
+             << toString(SymTabNameOrErr.takeError()) << "\n";
+      SymTabName = "<SHT_SYMTAB section with invalid name>";
+    }
+
+    dbgs() << "    Adding symbols from symtab section \"" << SymTabName
+           << "\"\n";
+  });
+
+  for (ELFSymbolIndex SymIndex = 0; SymIndex != Symbols->size(); ++SymIndex) {
+    auto &Sym = (*Symbols)[SymIndex];
+
+    // Check symbol type.
+    switch (Sym.getType()) {
+    case ELF::STT_FILE:
+      LLVM_DEBUG({
+        if (auto Name = Sym.getName(*StringTab))
+          dbgs() << "      " << SymIndex << ": Skipping STT_FILE symbol \""
+                 << *Name << "\"\n";
+        else {
+          dbgs() << "Could not get STT_FILE symbol name: "
+                 << toString(Name.takeError()) << "\n";
+          dbgs() << "     " << SymIndex
+                 << ": Skipping STT_FILE symbol with invalid name\n";
+        }
+      });
+      continue;
+      break;
+    }
+
+    // Get the symbol name.
+    auto Name = Sym.getName(*StringTab);
+    if (!Name)
+      return Name.takeError();
+
+    // Handle common symbols specially.
+    if (Sym.isCommon()) {
+      Symbol &GSym =
+          G->addCommonSymbol(*Name, Scope::Default, getCommonSection(), 0,
+                             Sym.st_size, Sym.getValue(), false);
+      setGraphSymbol(SymIndex, GSym);
+      continue;
+    }
+
+    // Map Visibility and Binding to Scope and Linkage:
+    Linkage L;
+    Scope S;
+
+    if (auto LSOrErr = getSymbolLinkageAndScope(Sym, *Name))
+      std::tie(L, S) = *LSOrErr;
+    else
+      return LSOrErr.takeError();
+
+    if (Sym.isDefined() &&
+        (Sym.getType() == ELF::STT_NOTYPE || Sym.getType() == ELF::STT_FUNC ||
+         Sym.getType() == ELF::STT_OBJECT ||
+         Sym.getType() == ELF::STT_SECTION)) {
+
+      // FIXME: Handle extended tables.
+      if (auto *GraphSec = getGraphSection(Sym.st_shndx)) {
+        Block *B = nullptr;
+        {
+          auto Blocks = GraphSec->blocks();
+          assert(Blocks.begin() != Blocks.end() && "No blocks for section");
+          assert(std::next(Blocks.begin()) == Blocks.end() &&
+                 "Multiple blocks for section");
+          B = *Blocks.begin();
+        }
+
+        LLVM_DEBUG({
+          dbgs() << "      " << SymIndex
+                 << ": Creating defined graph symbol for ELF symbol \"" << *Name
+                 << "\"\n";
+        });
+
+        if (Sym.getType() == ELF::STT_SECTION)
+          *Name = GraphSec->getName();
+
+        auto &GSym =
+            G->addDefinedSymbol(*B, Sym.getValue(), *Name, Sym.st_size, L, S,
+                                Sym.getType() == ELF::STT_FUNC, false);
+        setGraphSymbol(SymIndex, GSym);
+      }
+    } else if (Sym.isUndefined() && Sym.isExternal()) {
+      LLVM_DEBUG({
+        dbgs() << "      " << SymIndex
+               << ": Creating external graph symbol for ELF symbol \"" << *Name
+               << "\"\n";
+      });
+      auto &GSym = G->addExternalSymbol(*Name, Sym.st_size, L);
+      setGraphSymbol(SymIndex, GSym);
+    } else {
+      LLVM_DEBUG({
+        dbgs() << "      " << SymIndex
+               << ": Not creating graph symbol for ELF symbol \"" << *Name
+               << "\" with unrecognized type\n";
+      });
+    }
+  }
+
+  return Error::success();
+}
 
 } // end namespace jitlink
 } // end namespace llvm
 
+#undef DEBUG_TYPE
+
 #endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
index 80f814f51fa53..a5aed6d252007 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
@@ -139,13 +139,6 @@ class PerGraphGOTAndPLTStubsBuilder_ELF_x86_64
   mutable Section *StubsSection = nullptr;
 };
 
-const char *const DwarfSectionNames[] = {
-#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
-  ELF_NAME,
-#include "llvm/BinaryFormat/Dwarf.def"
-#undef HANDLE_DWARF_SECTION
-};
-
 } // namespace
 
 const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_x86_64::NullGOTEntryContent[8] =
@@ -153,7 +146,6 @@ const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_x86_64::NullGOTEntryContent[8] =
 const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_x86_64::StubContent[6] = {
     0xFF, 0x25, 0x00, 0x00, 0x00, 0x00};
 
-static const char *CommonSectionName = "__common";
 static Error optimizeELF_x86_64_GOTAndStubs(LinkGraph &G) {
   LLVM_DEBUG(dbgs() << "Optimizing GOT entries and stubs:\n");
 
@@ -229,35 +221,13 @@ static Error optimizeELF_x86_64_GOTAndStubs(LinkGraph &G) {
   return Error::success();
 }
 
-static bool isDwarfSection(StringRef SectionName) {
-  return llvm::is_contained(DwarfSectionNames, SectionName);
-}
-
 namespace llvm {
 namespace jitlink {
 
 // This should become a template as the ELFFile is so a lot of this could become
 // generic
 class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> {
-
 private:
-  Section *CommonSection = nullptr;
-
-  // TODO hack to get this working
-  // Find a better way
-  using SymbolTable = object::ELFFile<object::ELF64LE>::Elf_Shdr;
-  // For now we just assume
-  using SymbolMap = std::map<int32_t, Symbol *>;
-  SymbolMap JITSymbolTable;
-
-  Section &getCommonSection() {
-    if (!CommonSection) {
-      auto Prot = static_cast<sys::Memory::ProtectionFlags>(
-          sys::Memory::MF_READ | sys::Memory::MF_WRITE);
-      CommonSection = &G->createSection(CommonSectionName, Prot);
-    }
-    return *CommonSection;
-  }
 
   static Expected<ELF_x86_64_Edges::ELFX86RelocationKind>
   getRelocationKind(const uint32_t Type) {
@@ -286,143 +256,11 @@ class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> {
                                     formatv("{0:d}", Type));
   }
 
-  // This could be a template
-  object::ELFFile<object::ELF64LE>::Elf_Shdr_Range sections;
-  SymbolTable SymTab;
-
-  bool isRelocatable() { return Obj.getHeader().e_type == llvm::ELF::ET_REL; }
-
-  support::endianness
-  getEndianness(const object::ELFFile<object::ELF64LE> &Obj) {
-    return Obj.isLE() ? support::little : support::big;
-  }
-
-  // This could also just become part of a template
-  unsigned getPointerSize(const object::ELFFile<object::ELF64LE> &Obj) {
-    return Obj.getHeader().getFileClass() == ELF::ELFCLASS64 ? 8 : 4;
-  }
-
-  // We don't technically need this right now
-  // But for now going to keep it as it helps me to debug things
-
-  Error createNormalizedSymbols() {
-    LLVM_DEBUG(dbgs() << "Creating normalized symbols...\n");
-
-    for (auto SecRef : sections) {
-      if (SecRef.sh_type != ELF::SHT_SYMTAB &&
-          SecRef.sh_type != ELF::SHT_DYNSYM)
-        continue;
-
-      auto Symbols = Obj.symbols(&SecRef);
-      // TODO: Currently I use this function to test things 
-      // I also want to leave it to see if its common between MACH and elf
-      // so for now I just want to continue even if there is an error
-      if (errorToBool(Symbols.takeError()))
-        continue;
-
-      auto StrTabSec = Obj.getSection(SecRef.sh_link);
-      if (!StrTabSec)
-        return StrTabSec.takeError();
-      auto StringTable = Obj.getStringTable(**StrTabSec);
-      if (!StringTable)
-        return StringTable.takeError();
-
-      for (auto SymRef : *Symbols) {
-        Optional<StringRef> Name;
-
-        if (auto NameOrErr = SymRef.getName(*StringTable))
-          Name = *NameOrErr;
-        else
-          return NameOrErr.takeError();
-
-        LLVM_DEBUG({
-          dbgs() << "  value = " << formatv("{0:x16}", SymRef.getValue())
-                 << ", type = " << formatv("{0:x2}", SymRef.getType())
-                 << ", binding = " << formatv("{0:x2}", SymRef.getBinding())
-                 << ", size = "
-                 << formatv("{0:x16}", static_cast<uint64_t>(SymRef.st_size))
-                 << ", info = " << formatv("{0:x2}", SymRef.st_info)
-                 << " :" << (Name ? *Name : "<anonymous symbol>") << "\n";
-        });
-      }
-    }
-    return Error::success();
-  }
-
-  Error createNormalizedSections() {
-    LLVM_DEBUG(dbgs() << "Creating normalized sections...\n");
-    for (auto &SecRef : sections) {
-      auto Name = Obj.getSectionName(SecRef);
-      if (!Name)
-        return Name.takeError();
-
-      // Skip Dwarf sections.
-      if (isDwarfSection(*Name)) {
-        LLVM_DEBUG({
-          dbgs() << *Name
-                 << " is a debug section: No graph section will be created.\n";
-        });
-        continue;
-      }
-
-      sys::Memory::ProtectionFlags Prot;
-      if (SecRef.sh_flags & ELF::SHF_EXECINSTR) {
-        Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
-                                                         sys::Memory::MF_EXEC);
-      } else {
-        Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
-                                                         sys::Memory::MF_WRITE);
-      }
-      uint64_t Address = SecRef.sh_addr;
-      uint64_t Size = SecRef.sh_size;
-      uint64_t Flags = SecRef.sh_flags;
-      uint64_t Alignment = SecRef.sh_addralign;
-      const char *Data = nullptr;
-      // for now we just use this to skip the "undefined" section, probably need
-      // to revist
-      if (Size == 0)
-        continue;
-
-      // FIXME: Use flags.
-      (void)Flags;
-
-      LLVM_DEBUG({
-        dbgs() << "  " << *Name << ": " << formatv("{0:x16}", Address) << " -- "
-               << formatv("{0:x16}", Address + Size) << ", align: " << Alignment
-               << " Flags: " << formatv("{0:x}", Flags) << "\n";
-      });
-
-      if (SecRef.sh_type != ELF::SHT_NOBITS) {
-        // .sections() already checks that the data is not beyond the end of
-        // file
-        auto contents = Obj.getSectionContentsAsArray<char>(SecRef);
-        if (!contents)
-          return contents.takeError();
-
-        Data = contents->data();
-        // TODO protection flags.
-        // for now everything is
-        auto &section = G->createSection(*Name, Prot);
-        // Do this here because we have it, but move it into graphify later
-        G->createContentBlock(section, ArrayRef<char>(Data, Size), Address,
-                              Alignment, 0);
-        if (SecRef.sh_type == ELF::SHT_SYMTAB)
-          // TODO: Dynamic?
-          SymTab = SecRef;
-      } else {
-        auto &Section = G->createSection(*Name, Prot);
-        G->createZeroFillBlock(Section, Size, Address, Alignment, 0);
-      }
-    }
-
-    return Error::success();
-  }
-
-  Error addRelocations() {
+  Error addRelocations() override {
     LLVM_DEBUG(dbgs() << "Adding relocations\n");
     // TODO a partern is forming of iterate some sections but only give me
     // ones I am interested, i should abstract that concept some where
-    for (auto &SecRef : sections) {
+    for (auto &SecRef : Sections) {
       if (SecRef.sh_type != ELF::SHT_RELA && SecRef.sh_type != ELF::SHT_REL)
         continue;
       // TODO can the elf obj file do this for me?
@@ -477,19 +315,20 @@ class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> {
                  << "Name: " << Obj.getRelocationTypeName(Type) << "\n";
         });
         auto SymbolIndex = Rela.getSymbol(false);
-        auto Symbol = Obj.getRelocationSymbol(Rela, &SymTab);
+        auto Symbol = Obj.getRelocationSymbol(Rela, SymTabSec);
         if (!Symbol)
           return Symbol.takeError();
 
         auto BlockToFix = *(JITSection->blocks().begin());
-        auto *TargetSymbol = JITSymbolTable[SymbolIndex];
+        auto *TargetSymbol = getGraphSymbol(SymbolIndex);
 
         if (!TargetSymbol) {
           return make_error<llvm::StringError>(
               "Could not find symbol at given index, did you add it to "
-              "JITSymbolTable? index: " + std::to_string(SymbolIndex)
-              + ", shndx: " + std::to_string((*Symbol)->st_shndx) +
-                  " Size of table: " + std::to_string(JITSymbolTable.size()),
+              "JITSymbolTable? index: " +
+                  std::to_string(SymbolIndex) +
+                  ", shndx: " + std::to_string((*Symbol)->st_shndx) +
+                  " Size of table: " + std::to_string(GraphSymbols.size()),
               llvm::inconvertibleErrorCode());
         }
         uint64_t Addend = Rela.r_addend;
@@ -518,201 +357,11 @@ class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> {
     return Error::success();
   }
 
-  Error graphifyRegularSymbols() {
-
-    // TODO: ELF supports beyond SHN_LORESERVE,
-    // need to perf test how a vector vs map handles those cases
-
-    std::vector<std::vector<object::ELFFile<object::ELF64LE>::Elf_Shdr_Range *>>
-        SecIndexToSymbols;
-
-    LLVM_DEBUG(dbgs() << "Creating graph symbols...\n");
-
-    for (auto SecRef : sections) {
-
-      if (SecRef.sh_type != ELF::SHT_SYMTAB &&
-          SecRef.sh_type != ELF::SHT_DYNSYM)
-        continue;
-      auto Symbols = Obj.symbols(&SecRef);
-      if (!Symbols)
-        return Symbols.takeError();
-
-      auto StrTabSec = Obj.getSection(SecRef.sh_link);
-      if (!StrTabSec)
-        return StrTabSec.takeError();
-      auto StringTable = Obj.getStringTable(**StrTabSec);
-      if (!StringTable)
-        return StringTable.takeError();
-      auto Name = Obj.getSectionName(SecRef);
-      if (!Name)
-        return Name.takeError();
-
-      LLVM_DEBUG(dbgs() << "Processing symbol section " << *Name << ":\n");
-
-      auto Section = G->findSectionByName(*Name);
-      if (!Section)
-        return make_error<llvm::StringError>("Could not find a section " +
-                                             *Name,
-                                             llvm::inconvertibleErrorCode());
-      // we only have one for now
-      auto blocks = Section->blocks();
-      if (blocks.empty())
-        return make_error<llvm::StringError>("Section has no block",
-                                             llvm::inconvertibleErrorCode());
-      int SymbolIndex = -1;
-      for (auto SymRef : *Symbols) {
-        ++SymbolIndex;
-        auto Type = SymRef.getType();
-
-        if (Type == ELF::STT_FILE || SymbolIndex == 0)
-          continue;
-        // these should do it for now
-        // if(Type != ELF::STT_NOTYPE &&
-        //   Type != ELF::STT_OBJECT &&
-        //   Type != ELF::STT_FUNC    &&
-        //   Type != ELF::STT_SECTION &&
-        //   Type != ELF::STT_COMMON) {
-        //     continue;
-        //   }
-        auto Name = SymRef.getName(*StringTable);
-        // I am not sure on If this is going to hold as an invariant. Revisit.
-        if (!Name)
-          return Name.takeError();
-
-        if (SymRef.isCommon()) {
-          // Symbols in SHN_COMMON refer to uninitialized data. The st_value
-          // field holds alignment constraints.
-          Symbol &S =
-              G->addCommonSymbol(*Name, Scope::Default, getCommonSection(), 0,
-                                 SymRef.st_size, SymRef.getValue(), false);
-          JITSymbolTable[SymbolIndex] = &S;
-          continue;
-        }
-
-        // Map Visibility and Binding to Scope and Linkage:
-        Linkage L = Linkage::Strong;
-        Scope S = Scope::Default;
-
-        switch (SymRef.getBinding()) {
-        case ELF::STB_LOCAL:
-          S = Scope::Local;
-          break;
-        case ELF::STB_GLOBAL:
-          // Nothing to do here.
-          break;
-        case ELF::STB_WEAK:
-          L = Linkage::Weak;
-          break;
-        default:
-          return make_error<StringError>("Unrecognized symbol binding for " +
-                                             *Name,
-                                         inconvertibleErrorCode());
-        }
-
-        switch (SymRef.getVisibility()) {
-        case ELF::STV_DEFAULT:
-        case ELF::STV_PROTECTED:
-          // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs
-          // Orc support.
-          // Otherwise nothing to do here.
-          break;
-        case ELF::STV_HIDDEN:
-          // Default scope -> Hidden scope. No effect on local scope.
-          if (S == Scope::Default)
-            S = Scope::Hidden;
-          break;
-        case ELF::STV_INTERNAL:
-          return make_error<StringError>("Unrecognized symbol visibility for " +
-                                             *Name,
-                                         inconvertibleErrorCode());
-        }
-
-        if (SymRef.isDefined() &&
-            (Type == ELF::STT_NOTYPE || Type == ELF::STT_FUNC ||
-             Type == ELF::STT_OBJECT || Type == ELF::STT_SECTION)) {
-
-          auto DefinedSection = Obj.getSection(SymRef.st_shndx);
-          if (!DefinedSection)
-            return DefinedSection.takeError();
-          auto sectName = Obj.getSectionName(**DefinedSection);
-          if (!sectName)
-            return Name.takeError();
-
-          // Skip debug section symbols.
-          if (isDwarfSection(*sectName))
-            continue;
-
-          auto JitSection = G->findSectionByName(*sectName);
-          if (!JitSection)
-            return make_error<llvm::StringError>(
-                "Could not find the JitSection " + *sectName,
-                llvm::inconvertibleErrorCode());
-          auto bs = JitSection->blocks();
-          if (bs.empty())
-            return make_error<llvm::StringError>(
-                "Section has no block", llvm::inconvertibleErrorCode());
-
-          auto *B = *bs.begin();
-          LLVM_DEBUG({ dbgs() << "  " << *Name << " at index " << SymbolIndex << "\n"; });
-          if (SymRef.getType() == ELF::STT_SECTION)
-            *Name = *sectName;
-          auto &Sym = G->addDefinedSymbol(
-              *B, SymRef.getValue(), *Name, SymRef.st_size, L, S,
-              SymRef.getType() == ELF::STT_FUNC, false);
-          JITSymbolTable[SymbolIndex] = &Sym;
-        } else if (SymRef.isUndefined() && SymRef.isExternal()) {
-          auto &Sym = G->addExternalSymbol(*Name, SymRef.st_size, L);
-          JITSymbolTable[SymbolIndex] = &Sym;
-        } else
-          LLVM_DEBUG({
-              dbgs()
-                << "Not creating graph symbol for normalized symbol at index "
-                << SymbolIndex << ", \"" << *Name << "\"\n";
-            });
-
-        // TODO: The following has to be implmented.
-        // leaving commented out to save time for future patchs
-        /*
-          G->addAbsoluteSymbol(*Name, SymRef.getValue(), SymRef.st_size,
-          Linkage::Strong, Scope::Default, false);
-        */
-      }
-    }
-    return Error::success();
-  }
-
 public:
   ELFLinkGraphBuilder_x86_64(StringRef FileName,
                              const object::ELFFile<object::ELF64LE> &Obj)
       : ELFLinkGraphBuilder(Obj, Triple("x86_64-unknown-linux"), FileName,
                             getELFX86RelocationKindName) {}
-
-  Expected<std::unique_ptr<LinkGraph>> buildGraph() {
-    // Sanity check: we only operate on relocatable objects.
-    if (!isRelocatable())
-      return make_error<JITLinkError>("Object is not a relocatable ELF");
-
-    auto Secs = Obj.sections();
-
-    if (!Secs) {
-      return Secs.takeError();
-    }
-    sections = *Secs;
-
-    if (auto Err = createNormalizedSections())
-      return std::move(Err);
-
-    if (auto Err = createNormalizedSymbols())
-      return std::move(Err);
-
-    if (auto Err = graphifyRegularSymbols())
-      return std::move(Err);
-
-    if (auto Err = addRelocations())
-      return std::move(Err);
-
-    return std::move(G);
-  }
 };
 
 class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {

diff  --git a/llvm/test/ExecutionEngine/JITLink/X86/ELF_skip_debug_sections.s b/llvm/test/ExecutionEngine/JITLink/X86/ELF_skip_debug_sections.s
index 53132c4a987b7..acd3ae7ad8b1f 100644
--- a/llvm/test/ExecutionEngine/JITLink/X86/ELF_skip_debug_sections.s
+++ b/llvm/test/ExecutionEngine/JITLink/X86/ELF_skip_debug_sections.s
@@ -4,7 +4,7 @@
 #
 # Check that debug sections are not emitted.
 #
-# CHECK: .debug_info is a debug section: No graph section will be created.
+# CHECK: ".debug_info" is a debug section: No graph section will be created.
 
 	.text
 	.file	"ELF_skip_debug_sections.c"


        


More information about the llvm-commits mailing list