[llvm] r357947 - [RuntimeDyld] Decouple RuntimeDyldChecker from RuntimeDyld.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 8 14:50:49 PDT 2019


Author: lhames
Date: Mon Apr  8 14:50:48 2019
New Revision: 357947

URL: http://llvm.org/viewvc/llvm-project?rev=357947&view=rev
Log:
[RuntimeDyld] Decouple RuntimeDyldChecker from RuntimeDyld.

This will allow RuntimeDyldChecker (and rtdyld-check tests) to test a new JIT
linker: JITLink (https://reviews.llvm.org/D58704).

Modified:
    llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h
    llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
    llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp

Modified: llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h?rev=357947&r1=357946&r2=357947&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h Mon Apr  8 14:50:48 2019
@@ -52,18 +52,20 @@ private:
   std::string ErrMsg;
 };
 
-class RuntimeDyldCheckerImpl;
 class RuntimeDyldImpl;
 
 class RuntimeDyld {
-  friend class RuntimeDyldCheckerImpl;
-
 protected:
   // Change the address associated with a section when resolving relocations.
   // Any relocations already associated with the symbol will be re-resolved.
   void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
 
 public:
+
+  using NotifyStubEmittedFunction =
+    std::function<void(StringRef FileName, StringRef SectionName,
+                       StringRef SymbolName, uint32_t StubOffset)>;
+
   /// Information about the loaded object.
   class LoadedObjectInfo : public llvm::LoadedObjectInfo {
     friend class RuntimeDyldImpl;
@@ -184,6 +186,9 @@ public:
   /// and resolve relocatons based on where they put it).
   void *getSymbolLocalAddress(StringRef Name) const;
 
+  /// Get the section ID for the section containing the given symbol.
+  unsigned getSymbolSectionID(StringRef Name) const;
+
   /// Get the target address and flags for the named symbol.
   /// This address is the one used for relocation.
   JITEvaluatedSymbol getSymbol(StringRef Name) const;
@@ -204,6 +209,19 @@ public:
   /// This is the address which will be used for relocation resolution.
   void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress);
 
+  /// Returns the section's working memory.
+  StringRef getSectionContent(unsigned SectionID) const;
+
+  /// If the section was loaded, return the section's load address,
+  /// otherwise return None.
+  uint64_t getSectionLoadAddress(unsigned SectionID) const;
+
+  /// Set the NotifyStubEmitted callback. This is used for debugging
+  /// purposes. A callback is made for each stub that is generated.
+  void setNotifyStubEmitted(NotifyStubEmittedFunction NotifyStubEmitted) {
+    this->NotifyStubEmitted = std::move(NotifyStubEmitted);
+  }
+
   /// Register any EH frame sections that have been loaded but not previously
   /// registered with the memory manager.  Note, RuntimeDyld is responsible
   /// for identifying the EH frame and calling the memory manager with the
@@ -265,7 +283,7 @@ private:
   MemoryManager &MemMgr;
   JITSymbolResolver &Resolver;
   bool ProcessAllSections;
-  RuntimeDyldCheckerImpl *Checker;
+  NotifyStubEmittedFunction NotifyStubEmitted;
 };
 
 // Asynchronous JIT link for ORC.

Modified: llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyldChecker.h?rev=357947&r1=357946&r2=357947&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyldChecker.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyldChecker.h Mon Apr  8 14:50:48 2019
@@ -9,7 +9,10 @@
 #ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
 #define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
 
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/Support/Endian.h"
 
 #include <cstdint>
 #include <memory>
@@ -69,16 +72,34 @@ class raw_ostream;
 ///
 class RuntimeDyldChecker {
 public:
-  RuntimeDyldChecker(RuntimeDyld &RTDyld, MCDisassembler *Disassembler,
+
+  using IsSymbolValidFunction = std::function<bool(StringRef Symbol)>;
+  using GetSymbolAddressFunction =
+    std::function<Expected<JITTargetAddress>(StringRef Symbol)>;
+  using GetSymbolContentFunction =
+    std::function<Expected<StringRef>(StringRef Symbol)>;
+  using GetSectionLoadAddressFunction =
+    std::function<Optional<JITTargetAddress>(StringRef FileName,
+                                             StringRef SectionName)>;
+  using GetSectionContentFunction =
+    std::function<Expected<StringRef>(StringRef FileName,
+                                      StringRef SectionName)>;
+  using GetStubOffsetInSectionFunction =
+    std::function<Expected<uint32_t>(StringRef FileName,
+                                     StringRef SectionName,
+                                     StringRef SymbolName)>;
+
+  RuntimeDyldChecker(IsSymbolValidFunction IsSymbolValid,
+                     GetSymbolAddressFunction GetSymbolAddress,
+                     GetSymbolContentFunction GetSymbolContent,
+                     GetSectionLoadAddressFunction GetSectionLoadAddresss,
+                     GetSectionContentFunction GetSectionContent,
+                     GetStubOffsetInSectionFunction GetStubOffsetInSection,
+                     support::endianness Endianness,
+                     MCDisassembler *Disassembler,
                      MCInstPrinter *InstPrinter, raw_ostream &ErrStream);
   ~RuntimeDyldChecker();
 
-  // Get the associated RTDyld instance.
-  RuntimeDyld& getRTDyld();
-
-  // Get the associated RTDyld instance.
-  const RuntimeDyld& getRTDyld() const;
-
   /// Check a single expression against the attached RuntimeDyld
   ///        instance.
   bool check(StringRef CheckExpr) const;
@@ -99,7 +120,7 @@ public:
                                                   bool LocalAddress);
 
   /// If there is a section at the given local address, return its load
-  ///        address, otherwise return none.
+  /// address, otherwise return none.
   Optional<uint64_t> getSectionLoadAddress(void *LocalAddress) const;
 
 private:

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp?rev=357947&r1=357946&r2=357947&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp Mon Apr  8 14:50:48 2019
@@ -12,7 +12,6 @@
 
 #include "llvm/ExecutionEngine/RuntimeDyld.h"
 #include "RuntimeDyldCOFF.h"
-#include "RuntimeDyldCheckerImpl.h"
 #include "RuntimeDyldELF.h"
 #include "RuntimeDyldImpl.h"
 #include "RuntimeDyldMachO.h"
@@ -375,10 +374,34 @@ RuntimeDyldImpl::loadObjectImpl(const ob
       else
         return IOrErr.takeError();
 
-    // If there is an attached checker, notify it about the stubs for this
-    // section so that they can be verified.
-    if (Checker)
-      Checker->registerStubMap(Obj.getFileName(), SectionID, Stubs);
+    // If there is a NotifyStubEmitted callback set, call it to register any
+    // stubs created for this section.
+    if (NotifyStubEmitted) {
+      StringRef FileName = Obj.getFileName();
+      StringRef SectionName = Sections[SectionID].getName();
+      for (auto &KV : Stubs) {
+
+        auto &VR = KV.first;
+        uint64_t StubAddr = KV.second;
+
+        // If this is a named stub, just call NotifyStubEmitted.
+        if (VR.SymbolName) {
+          NotifyStubEmitted(FileName, SectionName, VR.SymbolName, StubAddr);
+          continue;
+        }
+
+        // Otherwise we will have to try a reverse lookup on the globla symbol table.
+        for (auto &GSTMapEntry : GlobalSymbolTable) {
+          StringRef SymbolName = GSTMapEntry.first();
+          auto &GSTEntry = GSTMapEntry.second;
+          if (GSTEntry.getSectionID() == VR.SectionID &&
+              GSTEntry.getOffset() == VR.Offset) {
+            NotifyStubEmitted(FileName, SectionName, SymbolName, StubAddr);
+            break;
+          }
+        }
+      }
+    }
   }
 
   // Process remaining sections
@@ -721,9 +744,6 @@ Error RuntimeDyldImpl::emitCommonSymbols
     Addr += Size;
   }
 
-  if (Checker)
-    Checker->registerSection(Obj.getFileName(), SectionID);
-
   return Error::success();
 }
 
@@ -840,9 +860,6 @@ RuntimeDyldImpl::emitSection(const Objec
   if (!IsRequired)
     Sections.back().setLoadAddress(0);
 
-  if (Checker)
-    Checker->registerSection(Obj.getFileName(), SectionID);
-
   return SectionID;
 }
 
@@ -1225,42 +1242,43 @@ RuntimeDyld::RuntimeDyld(RuntimeDyld::Me
   // permissions are applied.
   Dyld = nullptr;
   ProcessAllSections = false;
-  Checker = nullptr;
 }
 
 RuntimeDyld::~RuntimeDyld() {}
 
 static std::unique_ptr<RuntimeDyldCOFF>
-createRuntimeDyldCOFF(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM,
-                      JITSymbolResolver &Resolver, bool ProcessAllSections,
-                      RuntimeDyldCheckerImpl *Checker) {
+createRuntimeDyldCOFF(
+                     Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM,
+                     JITSymbolResolver &Resolver, bool ProcessAllSections,
+                     RuntimeDyld::NotifyStubEmittedFunction NotifyStubEmitted) {
   std::unique_ptr<RuntimeDyldCOFF> Dyld =
     RuntimeDyldCOFF::create(Arch, MM, Resolver);
   Dyld->setProcessAllSections(ProcessAllSections);
-  Dyld->setRuntimeDyldChecker(Checker);
+  Dyld->setNotifyStubEmitted(std::move(NotifyStubEmitted));
   return Dyld;
 }
 
 static std::unique_ptr<RuntimeDyldELF>
 createRuntimeDyldELF(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM,
                      JITSymbolResolver &Resolver, bool ProcessAllSections,
-                     RuntimeDyldCheckerImpl *Checker) {
+                     RuntimeDyld::NotifyStubEmittedFunction NotifyStubEmitted) {
   std::unique_ptr<RuntimeDyldELF> Dyld =
       RuntimeDyldELF::create(Arch, MM, Resolver);
   Dyld->setProcessAllSections(ProcessAllSections);
-  Dyld->setRuntimeDyldChecker(Checker);
+  Dyld->setNotifyStubEmitted(std::move(NotifyStubEmitted));
   return Dyld;
 }
 
 static std::unique_ptr<RuntimeDyldMachO>
-createRuntimeDyldMachO(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM,
-                       JITSymbolResolver &Resolver,
-                       bool ProcessAllSections,
-                       RuntimeDyldCheckerImpl *Checker) {
+createRuntimeDyldMachO(
+                     Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM,
+                     JITSymbolResolver &Resolver,
+                     bool ProcessAllSections,
+                     RuntimeDyld::NotifyStubEmittedFunction NotifyStubEmitted) {
   std::unique_ptr<RuntimeDyldMachO> Dyld =
     RuntimeDyldMachO::create(Arch, MM, Resolver);
   Dyld->setProcessAllSections(ProcessAllSections);
-  Dyld->setRuntimeDyldChecker(Checker);
+  Dyld->setNotifyStubEmitted(std::move(NotifyStubEmitted));
   return Dyld;
 }
 
@@ -1270,15 +1288,16 @@ RuntimeDyld::loadObject(const ObjectFile
     if (Obj.isELF())
       Dyld =
           createRuntimeDyldELF(static_cast<Triple::ArchType>(Obj.getArch()),
-                               MemMgr, Resolver, ProcessAllSections, Checker);
+                               MemMgr, Resolver, ProcessAllSections,
+                               std::move(NotifyStubEmitted));
     else if (Obj.isMachO())
       Dyld = createRuntimeDyldMachO(
                static_cast<Triple::ArchType>(Obj.getArch()), MemMgr, Resolver,
-               ProcessAllSections, Checker);
+               ProcessAllSections, std::move(NotifyStubEmitted));
     else if (Obj.isCOFF())
       Dyld = createRuntimeDyldCOFF(
                static_cast<Triple::ArchType>(Obj.getArch()), MemMgr, Resolver,
-               ProcessAllSections, Checker);
+               ProcessAllSections, std::move(NotifyStubEmitted));
     else
       report_fatal_error("Incompatible object format!");
   }
@@ -1297,6 +1316,11 @@ void *RuntimeDyld::getSymbolLocalAddress
   return Dyld->getSymbolLocalAddress(Name);
 }
 
+unsigned RuntimeDyld::getSymbolSectionID(StringRef Name) const {
+  assert(Dyld && "No RuntimeDyld instance attached");
+  return Dyld->getSymbolSectionID(Name);
+}
+
 JITEvaluatedSymbol RuntimeDyld::getSymbol(StringRef Name) const {
   if (!Dyld)
     return nullptr;
@@ -1335,6 +1359,16 @@ void RuntimeDyld::finalizeWithMemoryMana
   }
 }
 
+StringRef RuntimeDyld::getSectionContent(unsigned SectionID) const {
+  assert(Dyld && "No Dyld instance attached");
+  return Dyld->getSectionContent(SectionID);
+}
+
+uint64_t RuntimeDyld::getSectionLoadAddress(unsigned SectionID) const {
+  assert(Dyld && "No Dyld instance attached");
+  return Dyld->getSectionLoadAddress(SectionID);
+}
+
 void RuntimeDyld::registerEHFrames() {
   if (Dyld)
     Dyld->registerEHFrames();

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp?rev=357947&r1=357946&r2=357947&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp Mon Apr  8 14:50:48 2019
@@ -8,15 +8,14 @@
 
 #include "llvm/ExecutionEngine/RuntimeDyldChecker.h"
 #include "RuntimeDyldCheckerImpl.h"
-#include "RuntimeDyldImpl.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
 #include "llvm/MC/MCInst.h"
+#include "llvm/Support/Endian.h"
 #include "llvm/Support/MSVCErrorWorkarounds.h"
 #include "llvm/Support/Path.h"
 #include <cctype>
-#include <future>
 #include <memory>
 #include <utility>
 
@@ -665,25 +664,36 @@ private:
 
   bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size) const {
     MCDisassembler *Dis = Checker.Disassembler;
-    StringRef SectionMem = Checker.getSubsectionStartingAt(Symbol);
-    ArrayRef<uint8_t> SectionBytes(SectionMem.bytes_begin(), SectionMem.size());
+    StringRef SymbolMem = Checker.getSymbolContent(Symbol);
+    ArrayRef<uint8_t> SymbolBytes(SymbolMem.bytes_begin(), SymbolMem.size());
 
     MCDisassembler::DecodeStatus S =
-        Dis->getInstruction(Inst, Size, SectionBytes, 0, nulls(), nulls());
+        Dis->getInstruction(Inst, Size, SymbolBytes, 0, nulls(), nulls());
 
     return (S == MCDisassembler::Success);
   }
 };
 }
 
-RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl(RuntimeDyld &RTDyld,
-                                               MCDisassembler *Disassembler,
-                                               MCInstPrinter *InstPrinter,
-                                               raw_ostream &ErrStream)
-    : RTDyld(RTDyld), Disassembler(Disassembler), InstPrinter(InstPrinter),
-      ErrStream(ErrStream) {
-  RTDyld.Checker = this;
-}
+RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl(
+                      IsSymbolValidFunction IsSymbolValid,
+                      GetSymbolAddressFunction GetSymbolAddress,
+                      GetSymbolContentFunction GetSymbolContent,
+                      GetSectionLoadAddressFunction GetSectionLoadAddress,
+                      GetSectionContentFunction GetSectionContent,
+                      GetStubOffsetInSectionFunction GetStubOffsetInSection,
+                      support::endianness Endianness,
+                      MCDisassembler *Disassembler,
+                      MCInstPrinter *InstPrinter,
+                      raw_ostream &ErrStream)
+    : IsSymbolValid(std::move(IsSymbolValid)),
+      GetSymbolAddress(std::move(GetSymbolAddress)),
+      GetSymbolContent(std::move(GetSymbolContent)),
+      GetSectionLoadAddress(std::move(GetSectionLoadAddress)),
+      GetSectionContent(std::move(GetSectionContent)),
+      GetStubOffsetInSection(std::move(GetStubOffsetInSection)),
+      Endianness(Endianness), Disassembler(Disassembler),
+      InstPrinter(InstPrinter), ErrStream(ErrStream) {}
 
 bool RuntimeDyldCheckerImpl::check(StringRef CheckExpr) const {
   CheckExpr = CheckExpr.trim();
@@ -728,243 +738,133 @@ bool RuntimeDyldCheckerImpl::checkAllRul
   return DidAllTestsPass && (NumRules != 0);
 }
 
-Expected<JITSymbolResolver::LookupResult> RuntimeDyldCheckerImpl::lookup(
-    const JITSymbolResolver::LookupSet &Symbols) const {
-
-#ifdef _MSC_VER
-  using ExpectedLookupResult = MSVCPExpected<JITSymbolResolver::LookupResult>;
-#else
-  using ExpectedLookupResult = Expected<JITSymbolResolver::LookupResult>;
-#endif
-
-  auto ResultP = std::make_shared<std::promise<ExpectedLookupResult>>();
-  auto ResultF = ResultP->get_future();
-
-  getRTDyld().Resolver.lookup(
-      Symbols, [=](Expected<JITSymbolResolver::LookupResult> Result) {
-        ResultP->set_value(std::move(Result));
-      });
-  return ResultF.get();
-}
-
 bool RuntimeDyldCheckerImpl::isSymbolValid(StringRef Symbol) const {
-  if (getRTDyld().getSymbol(Symbol))
-    return true;
-  auto Result = lookup({Symbol});
-
-  if (!Result) {
-    logAllUnhandledErrors(Result.takeError(), errs(), "RTDyldChecker: ");
-    return false;
-  }
-
-  assert(Result->count(Symbol) && "Missing symbol result");
-  return true;
+  return IsSymbolValid(Symbol);
 }
 
 uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const {
-  return static_cast<uint64_t>(
-      reinterpret_cast<uintptr_t>(getRTDyld().getSymbolLocalAddress(Symbol)));
+  auto Contents = GetSymbolContent(Symbol);
+  if (!Contents) {
+    logAllUnhandledErrors(Contents.takeError(), errs(), "RTDyldChecker: ");
+    return 0;
+  }
+  return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Contents->data()));
 }
 
 uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const {
-  if (auto InternalSymbol = getRTDyld().getSymbol(Symbol))
-    return InternalSymbol.getAddress();
-
-  auto Result = lookup({Symbol});
-  if (!Result) {
-    logAllUnhandledErrors(Result.takeError(), errs(), "RTDyldChecker: ");
+  auto Addr = GetSymbolAddress(Symbol);
+  if (!Addr) {
+    logAllUnhandledErrors(Addr.takeError(), errs(), "RTDyldChecker: ");
     return 0;
   }
-  auto I = Result->find(Symbol);
-  assert(I != Result->end() && "Missing symbol result");
-  return I->second.getAddress();
+
+  return *Addr;
 }
 
 uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr,
                                                   unsigned Size) const {
   uintptr_t PtrSizedAddr = static_cast<uintptr_t>(SrcAddr);
   assert(PtrSizedAddr == SrcAddr && "Linker memory pointer out-of-range.");
-  uint8_t *Src = reinterpret_cast<uint8_t*>(PtrSizedAddr);
-  return getRTDyld().readBytesUnaligned(Src, Size);
-}
-
-
-std::pair<const RuntimeDyldCheckerImpl::SectionAddressInfo*, std::string>
-RuntimeDyldCheckerImpl::findSectionAddrInfo(StringRef FileName,
-                                            StringRef SectionName) const {
-
-  auto SectionMapItr = Stubs.find(FileName);
-  if (SectionMapItr == Stubs.end()) {
-    std::string ErrorMsg = "File '";
-    ErrorMsg += FileName;
-    ErrorMsg += "' not found. ";
-    if (Stubs.empty())
-      ErrorMsg += "No stubs registered.";
-    else {
-      ErrorMsg += "Available files are:";
-      for (const auto& StubEntry : Stubs) {
-        ErrorMsg += " '";
-        ErrorMsg += StubEntry.first;
-        ErrorMsg += "'";
-      }
-    }
-    ErrorMsg += "\n";
-    return std::make_pair(nullptr, ErrorMsg);
-  }
-
-  auto SectionInfoItr = SectionMapItr->second.find(SectionName);
-  if (SectionInfoItr == SectionMapItr->second.end())
-    return std::make_pair(nullptr,
-                          ("Section '" + SectionName + "' not found in file '" +
-                           FileName + "'\n").str());
+  void *Ptr = reinterpret_cast<void*>(PtrSizedAddr);
 
-  return std::make_pair(&SectionInfoItr->second, std::string(""));
+  switch (Size) {
+  case 1:
+    return support::endian::read<uint8_t>(Ptr, Endianness);
+  case 2:
+    return support::endian::read<uint16_t>(Ptr, Endianness);
+  case 4:
+    return support::endian::read<uint32_t>(Ptr, Endianness);
+  case 8:
+    return support::endian::read<uint64_t>(Ptr, Endianness);
+  }
+  llvm_unreachable("Unsupported read size");
+}
+
+StringRef RuntimeDyldCheckerImpl::getSymbolContent(StringRef Symbol) const {
+  auto Content = GetSymbolContent(Symbol);
+  if (!Content) {
+    logAllUnhandledErrors(Content.takeError(), errs(), "RTDyldChecker: ");
+    return StringRef();
+  }
+  return *Content;
 }
 
 std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getSectionAddr(
     StringRef FileName, StringRef SectionName, bool IsInsideLoad) const {
 
-  const SectionAddressInfo *SectionInfo = nullptr;
-  {
-    std::string ErrorMsg;
-    std::tie(SectionInfo, ErrorMsg) =
-      findSectionAddrInfo(FileName, SectionName);
-    if (ErrorMsg != "")
-      return std::make_pair(0, ErrorMsg);
+  uint64_t Addr = 0;
+  std::string ErrMsg;
+
+  // If this address is being looked up in "load" mode, return the content
+  // pointer.
+  if (IsInsideLoad) {
+    if (auto Content = GetSectionContent(FileName, SectionName))
+      Addr = pointerToJITTargetAddress(Content->data());
+    else {
+      raw_string_ostream ErrMsgStream(ErrMsg);
+      logAllUnhandledErrors(Content.takeError(), ErrMsgStream,
+                            "RTDyldChecker: ");
+    }
+    return std::make_pair(Addr, std::move(ErrMsg));
   }
 
-  unsigned SectionID = SectionInfo->SectionID;
-  uint64_t Addr;
-  if (IsInsideLoad)
-    Addr = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(
-        getRTDyld().Sections[SectionID].getAddress()));
+  // ... otherwise return the target pointer.
+  if (auto LoadAddr = GetSectionLoadAddress(FileName, SectionName))
+    Addr = *LoadAddr;
   else
-    Addr = getRTDyld().Sections[SectionID].getLoadAddress();
+    return std::make_pair(Addr, ("Section (" + FileName + ", " +
+                                 SectionName + ") does not exist").str());
 
-  return std::make_pair(Addr, std::string(""));
+  return std::make_pair(Addr, std::move(ErrMsg));
 }
 
 std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubAddrFor(
     StringRef FileName, StringRef SectionName, StringRef SymbolName,
     bool IsInsideLoad) const {
 
-  const SectionAddressInfo *SectionInfo = nullptr;
-  {
-    std::string ErrorMsg;
-    std::tie(SectionInfo, ErrorMsg) =
-      findSectionAddrInfo(FileName, SectionName);
-    if (ErrorMsg != "")
-      return std::make_pair(0, ErrorMsg);
-  }
+  auto SectionAddr = getSectionAddr(FileName, SectionName, IsInsideLoad);
 
-  unsigned SectionID = SectionInfo->SectionID;
-  const StubOffsetsMap &SymbolStubs = SectionInfo->StubOffsets;
-  auto StubOffsetItr = SymbolStubs.find(SymbolName);
-  if (StubOffsetItr == SymbolStubs.end())
-    return std::make_pair(0,
-                          ("Stub for symbol '" + SymbolName + "' not found. "
-                           "If '" + SymbolName + "' is an internal symbol this "
-                           "may indicate that the stub target offset is being "
-                           "computed incorrectly.\n").str());
+  if (!SectionAddr.second.empty())
+    return SectionAddr;
 
-  uint64_t StubOffset = StubOffsetItr->second;
+  auto StubOffset = GetStubOffsetInSection(FileName, SectionName, SymbolName);
 
-  uint64_t Addr;
-  if (IsInsideLoad) {
-    uintptr_t SectionBase = reinterpret_cast<uintptr_t>(
-        getRTDyld().Sections[SectionID].getAddress());
-    Addr = static_cast<uint64_t>(SectionBase) + StubOffset;
-  } else {
-    uint64_t SectionBase = getRTDyld().Sections[SectionID].getLoadAddress();
-    Addr = SectionBase + StubOffset;
-  }
-
-  return std::make_pair(Addr, std::string(""));
-}
-
-StringRef
-RuntimeDyldCheckerImpl::getSubsectionStartingAt(StringRef Name) const {
-  RTDyldSymbolTable::const_iterator pos =
-      getRTDyld().GlobalSymbolTable.find(Name);
-  if (pos == getRTDyld().GlobalSymbolTable.end())
-    return StringRef();
-  const auto &SymInfo = pos->second;
-  uint8_t *SectionAddr = getRTDyld().getSectionAddress(SymInfo.getSectionID());
-  return StringRef(reinterpret_cast<const char *>(SectionAddr) +
-                       SymInfo.getOffset(),
-                   getRTDyld().Sections[SymInfo.getSectionID()].getSize() -
-                       SymInfo.getOffset());
-}
-
-Optional<uint64_t>
-RuntimeDyldCheckerImpl::getSectionLoadAddress(void *LocalAddress) const {
-  for (auto &S : getRTDyld().Sections) {
-    if (S.getAddress() == LocalAddress)
-      return S.getLoadAddress();
+  if (!StubOffset) {
+    std::string ErrMsg;
+    {
+      raw_string_ostream ErrMsgStream(ErrMsg);
+      logAllUnhandledErrors(StubOffset.takeError(), ErrMsgStream,
+                            "RTDyldChecker: ");
+    }
+    return std::make_pair((uint64_t)0, std::move(ErrMsg));
   }
-  return Optional<uint64_t>();
-}
-
-void RuntimeDyldCheckerImpl::registerSection(
-    StringRef FilePath, unsigned SectionID) {
-  StringRef FileName = sys::path::filename(FilePath);
-  const SectionEntry &Section = getRTDyld().Sections[SectionID];
-  StringRef SectionName = Section.getName();
 
-  Stubs[FileName][SectionName].SectionID = SectionID;
+  return std::make_pair(SectionAddr.first + *StubOffset, "");
 }
 
-void RuntimeDyldCheckerImpl::registerStubMap(
-    StringRef FilePath, unsigned SectionID,
-    const RuntimeDyldImpl::StubMap &RTDyldStubs) {
-  StringRef FileName = sys::path::filename(FilePath);
-  const SectionEntry &Section = getRTDyld().Sections[SectionID];
-  StringRef SectionName = Section.getName();
-
-  Stubs[FileName][SectionName].SectionID = SectionID;
-
-  for (auto &StubMapEntry : RTDyldStubs) {
-    std::string SymbolName = "";
-
-    if (StubMapEntry.first.SymbolName)
-      SymbolName = StubMapEntry.first.SymbolName;
-    else {
-      // If this is a (Section, Offset) pair, do a reverse lookup in the
-      // global symbol table to find the name.
-      for (auto &GSTEntry : getRTDyld().GlobalSymbolTable) {
-        const auto &SymInfo = GSTEntry.second;
-        if (SymInfo.getSectionID() == StubMapEntry.first.SectionID &&
-            SymInfo.getOffset() ==
-              static_cast<uint64_t>(StubMapEntry.first.Offset)) {
-          SymbolName = GSTEntry.first();
-          break;
-        }
-      }
-    }
-
-    if (SymbolName != "")
-      Stubs[FileName][SectionName].StubOffsets[SymbolName] =
-        StubMapEntry.second;
-  }
-}
-
-RuntimeDyldChecker::RuntimeDyldChecker(RuntimeDyld &RTDyld,
-                                       MCDisassembler *Disassembler,
-                                       MCInstPrinter *InstPrinter,
-                                       raw_ostream &ErrStream)
-    : Impl(make_unique<RuntimeDyldCheckerImpl>(RTDyld, Disassembler,
-                                               InstPrinter, ErrStream)) {}
+RuntimeDyldChecker::RuntimeDyldChecker(
+                      IsSymbolValidFunction IsSymbolValid,
+                      GetSymbolAddressFunction GetSymbolAddress,
+                      GetSymbolContentFunction GetSymbolContent,
+                      GetSectionLoadAddressFunction GetSectionLoadAddress,
+                      GetSectionContentFunction GetSectionContent,
+                      GetStubOffsetInSectionFunction GetStubOffsetInSection,
+                      support::endianness Endianness,
+                      MCDisassembler *Disassembler,
+                      MCInstPrinter *InstPrinter,
+                      raw_ostream &ErrStream)
+    : Impl(make_unique<RuntimeDyldCheckerImpl>(
+                                            std::move(IsSymbolValid),
+                                            std::move(GetSymbolAddress),
+                                            std::move(GetSymbolContent),
+                                            std::move(GetSectionLoadAddress),
+                                            std::move(GetSectionContent),
+                                            std::move(GetStubOffsetInSection),
+                                            Endianness, Disassembler,
+                                            InstPrinter, ErrStream)) {}
 
 RuntimeDyldChecker::~RuntimeDyldChecker() {}
 
-RuntimeDyld& RuntimeDyldChecker::getRTDyld() {
-  return Impl->RTDyld;
-}
-
-const RuntimeDyld& RuntimeDyldChecker::getRTDyld() const {
-  return Impl->RTDyld;
-}
-
 bool RuntimeDyldChecker::check(StringRef CheckExpr) const {
   return Impl->check(CheckExpr);
 }
@@ -979,8 +879,3 @@ RuntimeDyldChecker::getSectionAddr(Strin
                                    bool LocalAddress) {
   return Impl->getSectionAddr(FileName, SectionName, LocalAddress);
 }
-
-Optional<uint64_t>
-RuntimeDyldChecker::getSectionLoadAddress(void *LocalAddress) const {
-  return Impl->getSectionLoadAddress(LocalAddress);
-}

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h?rev=357947&r1=357946&r2=357947&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h Mon Apr  8 14:50:48 2019
@@ -15,14 +15,35 @@ namespace llvm {
 
 class RuntimeDyldCheckerImpl {
   friend class RuntimeDyldChecker;
-  friend class RuntimeDyldImpl;
   friend class RuntimeDyldCheckerExprEval;
-  friend class RuntimeDyldELF;
+
+  using IsSymbolValidFunction =
+    RuntimeDyldChecker::IsSymbolValidFunction;
+  using GetSymbolAddressFunction =
+    RuntimeDyldChecker::GetSymbolAddressFunction;
+  using GetSymbolContentFunction =
+    RuntimeDyldChecker::GetSymbolContentFunction;
+
+  using GetSectionLoadAddressFunction =
+    RuntimeDyldChecker::GetSectionLoadAddressFunction;
+  using GetSectionContentFunction =
+    RuntimeDyldChecker::GetSectionContentFunction;
+
+  using GetStubOffsetInSectionFunction =
+    RuntimeDyldChecker::GetStubOffsetInSectionFunction;
 
 public:
-  RuntimeDyldCheckerImpl(RuntimeDyld &RTDyld, MCDisassembler *Disassembler,
-                         MCInstPrinter *InstPrinter,
-                         llvm::raw_ostream &ErrStream);
+  RuntimeDyldCheckerImpl(
+                      IsSymbolValidFunction IsSymbolValid,
+                      GetSymbolAddressFunction GetSymbolAddress,
+                      GetSymbolContentFunction GetSymbolContent,
+                      GetSectionLoadAddressFunction GetSectionLoadAddress,
+                      GetSectionContentFunction GetSectionContent,
+                      GetStubOffsetInSectionFunction GetStubOffsetInSection,
+                      support::endianness Endianness,
+                      MCDisassembler *Disassembler,
+                      MCInstPrinter *InstPrinter,
+                      llvm::raw_ostream &ErrStream);
 
   bool check(StringRef CheckExpr) const;
   bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
@@ -30,15 +51,6 @@ public:
 private:
 
   // StubMap typedefs.
-  typedef std::map<std::string, uint64_t> StubOffsetsMap;
-  struct SectionAddressInfo {
-    uint64_t SectionID;
-    StubOffsetsMap StubOffsets;
-  };
-  typedef std::map<std::string, SectionAddressInfo> SectionMap;
-  typedef std::map<std::string, SectionMap> StubMap;
-
-  RuntimeDyldImpl &getRTDyld() const { return *RTDyld.Dyld; }
 
   Expected<JITSymbolResolver::LookupResult>
   lookup(const JITSymbolResolver::LookupSet &Symbols) const;
@@ -48,9 +60,7 @@ private:
   uint64_t getSymbolRemoteAddr(StringRef Symbol) const;
   uint64_t readMemoryAtAddr(uint64_t Addr, unsigned Size) const;
 
-  std::pair<const SectionAddressInfo*, std::string> findSectionAddrInfo(
-                                                   StringRef FileName,
-                                                   StringRef SectionName) const;
+  StringRef getSymbolContent(StringRef Symbol) const;
 
   std::pair<uint64_t, std::string> getSectionAddr(StringRef FileName,
                                                   StringRef SectionName,
@@ -60,20 +70,19 @@ private:
                                                   StringRef SectionName,
                                                   StringRef Symbol,
                                                   bool IsInsideLoad) const;
-  StringRef getSubsectionStartingAt(StringRef Name) const;
 
   Optional<uint64_t> getSectionLoadAddress(void *LocalAddr) const;
 
-  void registerSection(StringRef FilePath, unsigned SectionID);
-  void registerStubMap(StringRef FilePath, unsigned SectionID,
-                       const RuntimeDyldImpl::StubMap &RTDyldStubs);
-
-  RuntimeDyld &RTDyld;
+  IsSymbolValidFunction IsSymbolValid;
+  GetSymbolAddressFunction GetSymbolAddress;
+  GetSymbolContentFunction GetSymbolContent;
+  GetSectionLoadAddressFunction GetSectionLoadAddress;
+  GetSectionContentFunction GetSectionContent;
+  GetStubOffsetInSectionFunction GetStubOffsetInSection;
+  support::endianness Endianness;
   MCDisassembler *Disassembler;
   MCInstPrinter *InstPrinter;
   llvm::raw_ostream &ErrStream;
-
-  StubMap Stubs;
 };
 }
 

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp?rev=357947&r1=357946&r2=357947&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp Mon Apr  8 14:50:48 2019
@@ -1856,9 +1856,6 @@ Error RuntimeDyldELF::finalizeLoad(const
     Sections[GOTSectionID] =
         SectionEntry(".got", Addr, TotalSize, TotalSize, 0);
 
-    if (Checker)
-      Checker->registerSection(Obj.getFileName(), GOTSectionID);
-
     // For now, initialize all GOT entries to zero.  We'll fill them in as
     // needed when GOT-based relocations are applied.
     memset(Addr, 0, TotalSize);

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h?rev=357947&r1=357946&r2=357947&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h Mon Apr  8 14:50:48 2019
@@ -240,7 +240,6 @@ typedef StringMap<SymbolTableEntry> RTDy
 
 class RuntimeDyldImpl {
   friend class RuntimeDyld::LoadedObjectInfo;
-  friend class RuntimeDyldCheckerImpl;
 protected:
   static const unsigned AbsoluteSymbolSection = ~0U;
 
@@ -250,9 +249,6 @@ protected:
   // The symbol resolver to use for external symbols.
   JITSymbolResolver &Resolver;
 
-  // Attached RuntimeDyldChecker instance. Null if no instance attached.
-  RuntimeDyldCheckerImpl *Checker;
-
   // A list of all sections emitted by the dynamic linker.  These sections are
   // referenced in the code by means of their index in this list - SectionID.
   typedef SmallVector<SectionEntry, 64> SectionList;
@@ -312,20 +308,16 @@ protected:
   // the end of the list while the list is being processed.
   sys::Mutex lock;
 
+  using NotifyStubEmittedFunction =
+    RuntimeDyld::NotifyStubEmittedFunction;
+  NotifyStubEmittedFunction NotifyStubEmitted;
+
   virtual unsigned getMaxStubSize() = 0;
   virtual unsigned getStubAlignment() = 0;
 
   bool HasError;
   std::string ErrorStr;
 
-  uint64_t getSectionLoadAddress(unsigned SectionID) const {
-    return Sections[SectionID].getLoadAddress();
-  }
-
-  uint8_t *getSectionAddress(unsigned SectionID) const {
-    return Sections[SectionID].getAddress();
-  }
-
   void writeInt16BE(uint8_t *Addr, uint16_t Value) {
     if (IsTargetLittleEndian)
       sys::swapByteOrder(Value);
@@ -471,7 +463,7 @@ protected:
 public:
   RuntimeDyldImpl(RuntimeDyld::MemoryManager &MemMgr,
                   JITSymbolResolver &Resolver)
-    : MemMgr(MemMgr), Resolver(Resolver), Checker(nullptr),
+    : MemMgr(MemMgr), Resolver(Resolver),
       ProcessAllSections(false), HasError(false) {
   }
 
@@ -481,13 +473,22 @@ public:
     this->ProcessAllSections = ProcessAllSections;
   }
 
-  void setRuntimeDyldChecker(RuntimeDyldCheckerImpl *Checker) {
-    this->Checker = Checker;
-  }
-
   virtual std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
   loadObject(const object::ObjectFile &Obj) = 0;
 
+  uint64_t getSectionLoadAddress(unsigned SectionID) const {
+    return Sections[SectionID].getLoadAddress();
+  }
+
+  uint8_t *getSectionAddress(unsigned SectionID) const {
+    return Sections[SectionID].getAddress();
+  }
+
+  StringRef getSectionContent(unsigned SectionID) const {
+    return StringRef(reinterpret_cast<char*>(Sections[SectionID].getAddress()),
+                     Sections[SectionID].getSize());
+  }
+
   uint8_t* getSymbolLocalAddress(StringRef Name) const {
     // FIXME: Just look up as a function for now. Overly simple of course.
     // Work in progress.
@@ -501,6 +502,13 @@ public:
     return getSectionAddress(SymInfo.getSectionID()) + SymInfo.getOffset();
   }
 
+  unsigned getSymbolSectionID(StringRef Name) const {
+    auto GSTItr = GlobalSymbolTable.find(Name);
+    if (GSTItr == GlobalSymbolTable.end())
+      return ~0U;
+    return GSTItr->second.getSectionID();
+  }
+
   JITEvaluatedSymbol getSymbol(StringRef Name) const {
     // FIXME: Just look up as a function for now. Overly simple of course.
     // Work in progress.
@@ -559,6 +567,10 @@ public:
 
   virtual bool isCompatibleFile(const ObjectFile &Obj) const = 0;
 
+  void setNotifyStubEmitted(NotifyStubEmittedFunction NotifyStubEmitted) {
+    this->NotifyStubEmitted = std::move(NotifyStubEmitted);
+  }
+
   virtual void registerEHFrames();
 
   void deregisterEHFrames();

Modified: llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp?rev=357947&r1=357946&r2=357947&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp (original)
+++ llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp Mon Apr  8 14:50:48 2019
@@ -29,9 +29,12 @@
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/Memory.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/raw_ostream.h"
+
+#include <future>
 #include <list>
 
 using namespace llvm;
@@ -137,14 +140,50 @@ PrintAllocationRequests("print-alloc-req
                                  "manager by RuntimeDyld"),
                         cl::Hidden);
 
+ExitOnError ExitOnErr;
+
 /* *** */
 
+using SectionIDMap = StringMap<unsigned>;
+using FileToSectionIDMap = StringMap<SectionIDMap>;
+
+void dumpFileToSectionIDMap(const FileToSectionIDMap &FileToSecIDMap) {
+  for (const auto &KV : FileToSecIDMap) {
+    llvm::dbgs() << "In " << KV.first() << "\n";
+    for (auto &KV2 : KV.second)
+      llvm::dbgs() << "  \"" << KV2.first() << "\" -> " << KV2.second << "\n";
+  }
+}
+
+Expected<unsigned> getSectionId(const FileToSectionIDMap &FileToSecIDMap,
+                                StringRef FileName, StringRef SectionName) {
+  auto I = FileToSecIDMap.find(FileName);
+  if (I == FileToSecIDMap.end())
+    return make_error<StringError>("No file named " + FileName,
+                                   inconvertibleErrorCode());
+  auto &SectionIDs = I->second;
+  auto J = SectionIDs.find(SectionName);
+  if (J == SectionIDs.end())
+    return make_error<StringError>("No section named \"" + SectionName +
+                                   "\" in file " + FileName,
+                                   inconvertibleErrorCode());
+  return J->second;
+}
+
 // A trivial memory manager that doesn't do anything fancy, just uses the
 // support library allocation routines directly.
 class TrivialMemoryManager : public RTDyldMemoryManager {
 public:
-  SmallVector<sys::MemoryBlock, 16> FunctionMemory;
-  SmallVector<sys::MemoryBlock, 16> DataMemory;
+  struct SectionInfo {
+    SectionInfo(StringRef Name, sys::MemoryBlock MB, unsigned SectionID)
+      : Name(Name), MB(std::move(MB)), SectionID(SectionID) {}
+    std::string Name;
+    sys::MemoryBlock MB;
+    unsigned SectionID = ~0U;
+  };
+
+  SmallVector<SectionInfo, 16> FunctionMemory;
+  SmallVector<SectionInfo, 16> DataMemory;
 
   uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
                                unsigned SectionID,
@@ -153,6 +192,11 @@ public:
                                unsigned SectionID, StringRef SectionName,
                                bool IsReadOnly) override;
 
+  /// If non null, records subsequent Name -> SectionID mappings.
+  void setSectionIDsMap(SectionIDMap *SecIDMap) {
+    this->SecIDMap = SecIDMap;
+  }
+
   void *getPointerToNamedFunction(const std::string &Name,
                                   bool AbortOnFailure = true) override {
     return nullptr;
@@ -192,7 +236,8 @@ public:
     SlabSize = Size;
   }
 
-  uint8_t *allocateFromSlab(uintptr_t Size, unsigned Alignment, bool isCode) {
+  uint8_t *allocateFromSlab(uintptr_t Size, unsigned Alignment, bool isCode,
+                            StringRef SectionName, unsigned SectionID) {
     Size = alignTo(Size, Alignment);
     if (CurrentSlabOffset + Size > SlabSize)
       report_fatal_error("Can't allocate enough memory. Tune --preallocate");
@@ -200,9 +245,9 @@ public:
     uintptr_t OldSlabOffset = CurrentSlabOffset;
     sys::MemoryBlock MB((void *)OldSlabOffset, Size);
     if (isCode)
-      FunctionMemory.push_back(MB);
+      FunctionMemory.push_back(SectionInfo(SectionName, MB, SectionID));
     else
-      DataMemory.push_back(MB);
+      DataMemory.push_back(SectionInfo(SectionName, MB, SectionID));
     CurrentSlabOffset += Size;
     return (uint8_t*)OldSlabOffset;
   }
@@ -213,6 +258,7 @@ private:
   bool UsePreallocation = false;
   uintptr_t SlabSize = 0;
   uintptr_t CurrentSlabOffset = 0;
+  SectionIDMap *SecIDMap = nullptr;
 };
 
 uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size,
@@ -223,8 +269,13 @@ uint8_t *TrivialMemoryManager::allocateC
     outs() << "allocateCodeSection(Size = " << Size << ", Alignment = "
            << Alignment << ", SectionName = " << SectionName << ")\n";
 
+  dbgs() << "  Registering code section \"" << SectionName << "\"\n";
+  if (SecIDMap)
+    (*SecIDMap)[SectionName] = SectionID;
+
   if (UsePreallocation)
-    return allocateFromSlab(Size, Alignment, true /* isCode */);
+    return allocateFromSlab(Size, Alignment, true /* isCode */,
+                            SectionName, SectionID);
 
   std::error_code EC;
   sys::MemoryBlock MB =
@@ -234,7 +285,7 @@ uint8_t *TrivialMemoryManager::allocateC
                                       EC);
   if (!MB.base())
     report_fatal_error("MemoryManager allocation failed: " + EC.message());
-  FunctionMemory.push_back(MB);
+  FunctionMemory.push_back(SectionInfo(SectionName, MB, SectionID));
   return (uint8_t*)MB.base();
 }
 
@@ -247,8 +298,13 @@ uint8_t *TrivialMemoryManager::allocateD
     outs() << "allocateDataSection(Size = " << Size << ", Alignment = "
            << Alignment << ", SectionName = " << SectionName << ")\n";
 
+  dbgs() << "  Registering code section \"" << SectionName << "\"\n";
+  if (SecIDMap)
+    (*SecIDMap)[SectionName] = SectionID;
+
   if (UsePreallocation)
-    return allocateFromSlab(Size, Alignment, false /* isCode */);
+    return allocateFromSlab(Size, Alignment, false /* isCode */, SectionName,
+                            SectionID);
 
   std::error_code EC;
   sys::MemoryBlock MB =
@@ -258,7 +314,7 @@ uint8_t *TrivialMemoryManager::allocateD
                                       EC);
   if (!MB.base())
     report_fatal_error("MemoryManager allocation failed: " + EC.message());
-  DataMemory.push_back(MB);
+  DataMemory.push_back(SectionInfo(SectionName, MB, SectionID));
   return (uint8_t*)MB.base();
 }
 
@@ -469,9 +525,11 @@ static int executeInput() {
   // Invalidate the instruction cache for each loaded function.
   for (auto &FM : MemMgr.FunctionMemory) {
 
+    auto &FM_MB = FM.MB;
+
     // Make sure the memory is executable.
     // setExecutable will call InvalidateInstructionCache.
-    if (auto EC = sys::Memory::protectMappedMemory(FM,
+    if (auto EC = sys::Memory::protectMappedMemory(FM_MB,
                                                    sys::Memory::MF_READ |
                                                    sys::Memory::MF_EXEC))
       ErrorAndExit("unable to mark function executable: '" + EC.message() +
@@ -505,10 +563,10 @@ static int checkAllExpressions(RuntimeDy
   return 0;
 }
 
-void applySpecificSectionMappings(RuntimeDyldChecker &Checker) {
+void applySpecificSectionMappings(RuntimeDyld &Dyld,
+                                  const FileToSectionIDMap &FileToSecIDMap) {
 
   for (StringRef Mapping : SpecificSectionMappings) {
-
     size_t EqualsIdx = Mapping.find_first_of("=");
     std::string SectionIDStr = Mapping.substr(0, EqualsIdx);
     size_t ComaIdx = Mapping.find_first_of(",");
@@ -519,17 +577,10 @@ void applySpecificSectionMappings(Runtim
 
     std::string FileName = SectionIDStr.substr(0, ComaIdx);
     std::string SectionName = SectionIDStr.substr(ComaIdx + 1);
+    unsigned SectionID =
+      ExitOnErr(getSectionId(FileToSecIDMap, FileName, SectionName));
 
-    uint64_t OldAddrInt;
-    std::string ErrorMsg;
-    std::tie(OldAddrInt, ErrorMsg) =
-      Checker.getSectionAddr(FileName, SectionName, true);
-
-    if (ErrorMsg != "")
-      report_fatal_error(ErrorMsg);
-
-    void* OldAddr = reinterpret_cast<void*>(static_cast<uintptr_t>(OldAddrInt));
-
+    auto* OldAddr = Dyld.getSectionContent(SectionID).data();
     std::string NewAddrStr = Mapping.substr(EqualsIdx + 1);
     uint64_t NewAddr;
 
@@ -537,7 +588,7 @@ void applySpecificSectionMappings(Runtim
       report_fatal_error("Invalid section address in mapping '" + Mapping +
                          "'.");
 
-    Checker.getRTDyld().mapSectionAddress(OldAddr, NewAddr);
+    Dyld.mapSectionAddress(OldAddr, NewAddr);
   }
 }
 
@@ -553,21 +604,17 @@ void applySpecificSectionMappings(Runtim
 //                            (e.g. 1 << 32) to stress-test stubs, GOTs, etc.
 //
 static void remapSectionsAndSymbols(const llvm::Triple &TargetTriple,
-                                    TrivialMemoryManager &MemMgr,
-                                    RuntimeDyldChecker &Checker) {
+                                    RuntimeDyld &Dyld,
+                                    TrivialMemoryManager &MemMgr) {
 
   // Set up a work list (section addr/size pairs).
-  typedef std::list<std::pair<void*, uint64_t>> WorklistT;
+  typedef std::list<const TrivialMemoryManager::SectionInfo*> WorklistT;
   WorklistT Worklist;
 
   for (const auto& CodeSection : MemMgr.FunctionMemory)
-    Worklist.push_back(std::make_pair(CodeSection.base(), CodeSection.size()));
+    Worklist.push_back(&CodeSection);
   for (const auto& DataSection : MemMgr.DataMemory)
-    Worklist.push_back(std::make_pair(DataSection.base(), DataSection.size()));
-
-  // Apply any section-specific mappings that were requested on the command
-  // line.
-  applySpecificSectionMappings(Checker);
+    Worklist.push_back(&DataSection);
 
   // Keep an "already allocated" mapping of section target addresses to sizes.
   // Sections whose address mappings aren't specified on the command line will
@@ -582,16 +629,16 @@ static void remapSectionsAndSymbols(cons
        I != E;) {
     WorklistT::iterator Tmp = I;
     ++I;
-    auto LoadAddr = Checker.getSectionLoadAddress(Tmp->first);
 
-    if (LoadAddr &&
-        *LoadAddr != static_cast<uint64_t>(
-                       reinterpret_cast<uintptr_t>(Tmp->first))) {
+    auto LoadAddr = Dyld.getSectionLoadAddress((*Tmp)->SectionID);
+
+    if (LoadAddr != static_cast<uint64_t>(
+          reinterpret_cast<uintptr_t>((*Tmp)->MB.base()))) {
       // A section will have a LoadAddr of 0 if it wasn't loaded for whatever
       // reason (e.g. zero byte COFF sections). Don't include those sections in
       // the allocation map.
-      if (*LoadAddr != 0)
-        AlreadyAllocated[*LoadAddr] = Tmp->second;
+      if (LoadAddr != 0)
+        AlreadyAllocated[LoadAddr] = (*Tmp)->MB.size();
       Worklist.erase(Tmp);
     }
   }
@@ -609,19 +656,19 @@ static void remapSectionsAndSymbols(cons
 
   // Process any elements remaining in the worklist.
   while (!Worklist.empty()) {
-    std::pair<void*, uint64_t> CurEntry = Worklist.front();
+    auto *CurEntry = Worklist.front();
     Worklist.pop_front();
 
     uint64_t NextSectionAddr = TargetAddrStart;
 
     for (const auto &Alloc : AlreadyAllocated)
-      if (NextSectionAddr + CurEntry.second + TargetSectionSep <= Alloc.first)
+      if (NextSectionAddr + CurEntry->MB.size() + TargetSectionSep <= Alloc.first)
         break;
       else
         NextSectionAddr = Alloc.first + Alloc.second + TargetSectionSep;
 
-    AlreadyAllocated[NextSectionAddr] = CurEntry.second;
-    Checker.getRTDyld().mapSectionAddress(CurEntry.first, NextSectionAddr);
+    Dyld.mapSectionAddress(CurEntry->MB.base(), NextSectionAddr);
+    AlreadyAllocated[NextSectionAddr] = CurEntry->MB.size();
   }
 
   // Add dummy symbols to the memory manager.
@@ -693,18 +740,116 @@ static int linkAndVerify() {
   // Instantiate a dynamic linker.
   TrivialMemoryManager MemMgr;
   doPreallocation(MemMgr);
+
+  using StubOffsets = StringMap<uint32_t>;
+  using SectionStubs = StringMap<StubOffsets>;
+  using FileStubs = StringMap<SectionStubs>;
+
+  FileStubs StubMap;
   RuntimeDyld Dyld(MemMgr, MemMgr);
   Dyld.setProcessAllSections(true);
-  RuntimeDyldChecker Checker(Dyld, Disassembler.get(), InstPrinter.get(),
-                             llvm::dbgs());
+
+  Dyld.setNotifyStubEmitted(
+      [&StubMap](StringRef FilePath, StringRef SectionName,
+                 StringRef SymbolName, uint32_t StubOffset) {
+        StubMap[sys::path::filename(FilePath)][SectionName][SymbolName] =
+          StubOffset;
+      });
+
+  auto GetSymbolAddress =
+    [&Dyld, &MemMgr](StringRef Symbol) -> Expected<JITTargetAddress> {
+      if (auto InternalSymbol = Dyld.getSymbol(Symbol))
+        return InternalSymbol.getAddress();
+
+#ifdef _MSC_VER
+      using ExpectedLookupResult = MSVCPExpected<JITSymbolResolver::LookupResult>;
+#else
+      using ExpectedLookupResult = Expected<JITSymbolResolver::LookupResult>;
+#endif
+
+      auto ResultP = std::make_shared<std::promise<ExpectedLookupResult>>();
+      auto ResultF = ResultP->get_future();
+
+      MemMgr.lookup(
+        JITSymbolResolver::LookupSet({Symbol}),
+        [=](Expected<JITSymbolResolver::LookupResult> Result) {
+          ResultP->set_value(std::move(Result));
+        });
+
+      auto Result = ResultF.get();
+      if (!Result)
+        return Result.takeError();
+
+      auto I = Result->find(Symbol);
+      assert(I != Result->end() &&
+             "Expected symbol address if no error occurred");
+      return I->second.getAddress();
+    };
+
+  auto IsSymbolValid =
+    [&Dyld, GetSymbolAddress](StringRef Symbol) {
+      if (Dyld.getSymbol(Symbol))
+        return true;
+      auto Addr = GetSymbolAddress(Symbol);
+      if (!Addr) {
+        logAllUnhandledErrors(Addr.takeError(), errs(), "RTDyldChecker: ");
+        return false;
+      }
+      return *Addr != 0;
+    };
+
+  FileToSectionIDMap FileToSecIDMap;
+
+  auto GetSectionAddress =
+    [&Dyld, &FileToSecIDMap](StringRef FileName, StringRef SectionName) {
+      unsigned SectionID =
+        ExitOnErr(getSectionId(FileToSecIDMap, FileName, SectionName));
+      return Dyld.getSectionLoadAddress(SectionID);
+    };
+
+  auto GetSectionContent =
+    [&Dyld, &FileToSecIDMap](StringRef FileName, StringRef SectionName) {
+      unsigned SectionID =
+        ExitOnErr(getSectionId(FileToSecIDMap, FileName, SectionName));
+      return Dyld.getSectionContent(SectionID);
+    };
+
+
+  auto GetSymbolContents =
+    [&Dyld](StringRef Symbol) {
+      auto *SymAddr = static_cast<char*>(Dyld.getSymbolLocalAddress(Symbol));
+      if (!SymAddr)
+        return StringRef();
+      unsigned SectionID = Dyld.getSymbolSectionID(Symbol);
+      if (SectionID == ~0U)
+        return StringRef();
+      StringRef SecContent = Dyld.getSectionContent(SectionID);
+      uint64_t SymSize = SecContent.size() - (SymAddr - SecContent.data());
+      return StringRef(SymAddr, SymSize);
+    };
+
+  auto GetStubOffset =
+    [&StubMap](StringRef FileName, StringRef SectionName, StringRef SymbolName) -> Expected<uint32_t> {
+      if (!StubMap.count(FileName))
+        return make_error<StringError>("File name not found", inconvertibleErrorCode());
+      if (!StubMap[FileName].count(SectionName))
+        return make_error<StringError>("Section name not found", inconvertibleErrorCode());
+      if (!StubMap[FileName][SectionName].count(SymbolName))
+        return make_error<StringError>("Symbol name not found", inconvertibleErrorCode());
+      return StubMap[FileName][SectionName][SymbolName];
+    };
+
+  // We will initialize this below once we have the first object file and can
+  // know the endianness.
+  std::unique_ptr<RuntimeDyldChecker> Checker;
 
   // If we don't have any input files, read from stdin.
   if (!InputFileList.size())
     InputFileList.push_back("-");
-  for (auto &Filename : InputFileList) {
+  for (auto &InputFile : InputFileList) {
     // Load the input memory buffer.
     ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer =
-        MemoryBuffer::getFileOrSTDIN(Filename);
+        MemoryBuffer::getFileOrSTDIN(InputFile);
 
     if (std::error_code EC = InputBuffer.getError())
       ErrorAndExit("unable to read input: '" + EC.message() + "'");
@@ -722,6 +867,22 @@ static int linkAndVerify() {
 
     ObjectFile &Obj = **MaybeObj;
 
+    if (!Checker)
+      Checker =
+        llvm::make_unique<RuntimeDyldChecker>(IsSymbolValid, GetSymbolAddress,
+                                              GetSymbolContents,
+                                              GetSectionAddress,
+                                              GetSectionContent, GetStubOffset,
+                                              Obj.isLittleEndian()
+                                                ? support::little
+                                                : support::big,
+                                              Disassembler.get(),
+                                              InstPrinter.get(), dbgs());
+
+    auto FileName = sys::path::filename(InputFile);
+    dbgs() << "In " << FileName << ":\n";
+    MemMgr.setSectionIDsMap(&FileToSecIDMap[FileName]);
+
     // Load the object file
     Dyld.loadObject(Obj);
     if (Dyld.hasError()) {
@@ -731,7 +892,8 @@ static int linkAndVerify() {
 
   // Re-map the section addresses into the phony target address space and add
   // dummy symbols.
-  remapSectionsAndSymbols(TheTriple, MemMgr, Checker);
+  applySpecificSectionMappings(Dyld, FileToSecIDMap);
+  remapSectionsAndSymbols(TheTriple, Dyld, MemMgr);
 
   // Resolve all the relocations we can.
   Dyld.resolveRelocations();
@@ -739,7 +901,7 @@ static int linkAndVerify() {
   // Register EH frames.
   Dyld.registerEHFrames();
 
-  int ErrorCode = checkAllExpressions(Checker);
+  int ErrorCode = checkAllExpressions(*Checker);
   if (Dyld.hasError())
     ErrorAndExit("RTDyld reported an error applying relocations:\n  " +
                  Dyld.getErrorString());
@@ -757,6 +919,8 @@ int main(int argc, char **argv) {
 
   cl::ParseCommandLineOptions(argc, argv, "llvm MC-JIT tool\n");
 
+  ExitOnErr.setBanner(std::string(argv[0]) + ": ");
+
   switch (Action) {
   case AC_Execute:
     return executeInput();




More information about the llvm-commits mailing list