]> granicus.if.org Git - llvm/commitdiff
Simplify decoupling between RuntimeDyld/RuntimeDyldChecker, add 'got_addr' util.
authorLang Hames <lhames@gmail.com>
Fri, 12 Apr 2019 18:07:28 +0000 (18:07 +0000)
committerLang Hames <lhames@gmail.com>
Fri, 12 Apr 2019 18:07:28 +0000 (18:07 +0000)
This patch reduces the number of functions in the interface between RuntimeDyld
and RuntimeDyldChecker by combining "GetXAddress" and "GetXContent" functions
into "GetXInfo" functions that return a struct describing both the address and
content. The GetStubOffset function is also replaced with a pair of utilities,
GetStubInfo and GetGOTInfo, that fit the new scheme. For RuntimeDyld both of
these functions will return the same result, but for the new JITLink linker
(https://reviews.llvm.org/D58704) these will provide the addresses of PLT stubs
and GOT entries respectively.

For JITLink's use, a 'got_addr' utility has been added to the rtdyld-check
language, and the syntax of 'got_addr' and 'stub_addr' has been changed: both
functions now take two arguments, a 'stub container name' and a target symbol
name. For llvm-rtdyld/RuntimeDyld the stub container name is the object file
name and section name, separated by a slash. E.g.:

rtdyld-check: *{8}(stub_addr(foo.o/__text, y)) = y

For the upcoming llvm-jitlink utility, which creates stubs on a per-file basis
rather than a per-section basis, the container name is just the file name. E.g.:

jitlink-check: *{8}(got_addr(foo.o, y)) = y

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358295 91177308-0d34-0410-b5e6-96231b3b80d8

23 files changed:
include/llvm/ExecutionEngine/RuntimeDyld.h
include/llvm/ExecutionEngine/RuntimeDyldChecker.h
lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h
lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h
lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h
lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h
lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h
lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h
lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h
test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s
test/ExecutionEngine/RuntimeDyld/ARM/MachO_ARM_PIC_relocations.s
test/ExecutionEngine/RuntimeDyld/ARM/MachO_Thumb_Relocations.s
test/ExecutionEngine/RuntimeDyld/Mips/ELF_Mips64r2N64_PIC_relocations.s
test/ExecutionEngine/RuntimeDyld/Mips/ELF_N32_relocations.s
test/ExecutionEngine/RuntimeDyld/Mips/ELF_O32_PIC_relocations.s
test/ExecutionEngine/RuntimeDyld/PowerPC/ppc64_elf.s
test/ExecutionEngine/RuntimeDyld/X86/MachO_x86-64_PIC_relocations.s
tools/llvm-rtdyld/llvm-rtdyld.cpp

index 2d5420f194ad3d11be54a16668263847d8b8e1c7..b2b4eba47074cca43758b1c89baebcfddb6fbbae 100644 (file)
@@ -61,10 +61,9 @@ protected:
   void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
 
 public:
-
-  using NotifyStubEmittedFunction =
-    std::function<void(StringRef FileName, StringRef SectionName,
-                       StringRef SymbolName, uint32_t StubOffset)>;
+  using NotifyStubEmittedFunction = std::function<void(
+      StringRef FileName, StringRef SectionName, StringRef SymbolName,
+      unsigned SectionID, uint32_t StubOffset)>;
 
   /// Information about the loaded object.
   class LoadedObjectInfo : public llvm::LoadedObjectInfo {
index 57193fb45c8779888fdb8376fb3aab7283b00d2a..2897c8ebca8f97dc91bb82059829e33dc4c616a7 100644 (file)
@@ -60,7 +60,8 @@ class raw_ostream;
 ///
 /// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')'
 ///            | 'next_pc'        '(' symbol ')'
-///            | 'stub_addr' '(' file-name ',' section-name ',' symbol ')'
+///            | 'stub_addr' '(' stub-container-name ',' symbol ')'
+///            | 'got_addr' '(' stub-container-name ',' symbol ')'
 ///            | symbol
 ///
 /// binary_expr = expr '+' expr
@@ -72,32 +73,29 @@ class raw_ostream;
 ///
 class RuntimeDyldChecker {
 public:
+  struct MemoryRegionInfo {
+    StringRef Content;
+    JITTargetAddress TargetAddress;
+  };
 
   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)>;
+  using GetSymbolInfoFunction =
+      std::function<Expected<MemoryRegionInfo>(StringRef SymbolName)>;
+  using GetSectionInfoFunction = std::function<Expected<MemoryRegionInfo>(
+      StringRef FileName, StringRef SectionName)>;
+  using GetStubInfoFunction = std::function<Expected<MemoryRegionInfo>(
+      StringRef StubContainer, StringRef TargetName)>;
+  using GetGOTInfoFunction = std::function<Expected<MemoryRegionInfo>(
+      StringRef GOTContainer, StringRef TargetName)>;
 
   RuntimeDyldChecker(IsSymbolValidFunction IsSymbolValid,
-                     GetSymbolAddressFunction GetSymbolAddress,
-                     GetSymbolContentFunction GetSymbolContent,
-                     GetSectionLoadAddressFunction GetSectionLoadAddresss,
-                     GetSectionContentFunction GetSectionContent,
-                     GetStubOffsetInSectionFunction GetStubOffsetInSection,
+                     GetSymbolInfoFunction GetSymbolInfo,
+                     GetSectionInfoFunction GetSectionInfo,
+                     GetStubInfoFunction GetStubInfo,
+                     GetGOTInfoFunction GetGOTInfo,
                      support::endianness Endianness,
-                     MCDisassembler *Disassembler,
-                     MCInstPrinter *InstPrinter, raw_ostream &ErrStream);
+                     MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
+                     raw_ostream &ErrStream);
   ~RuntimeDyldChecker();
 
   /// Check a single expression against the attached RuntimeDyld
index dee8ecda13adddab47af51264c06190e674ab86f..2fd677ab13a8ac730c493509ec426dd60739c50a 100644 (file)
@@ -386,7 +386,8 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
 
         // If this is a named stub, just call NotifyStubEmitted.
         if (VR.SymbolName) {
-          NotifyStubEmitted(FileName, SectionName, VR.SymbolName, StubAddr);
+          NotifyStubEmitted(FileName, SectionName, VR.SymbolName, SectionID,
+                            StubAddr);
           continue;
         }
 
@@ -396,7 +397,8 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
           auto &GSTEntry = GSTMapEntry.second;
           if (GSTEntry.getSectionID() == VR.SectionID &&
               GSTEntry.getOffset() == VR.Offset) {
-            NotifyStubEmitted(FileName, SectionName, SymbolName, StubAddr);
+            NotifyStubEmitted(FileName, SectionName, SymbolName, SectionID,
+                              StubAddr);
             break;
           }
         }
index 3a293c0cda43a0b89c571a8ce4eda7b653a14aa3..e801ebd1cde098048c9e17f3ecb0efe1f9c1f15e 100644 (file)
@@ -319,22 +319,22 @@ private:
     return std::make_pair(EvalResult(NextPC), RemainingExpr);
   }
 
-  // Evaluate a call to stub_addr.
+  // Evaluate a call to stub_addr/got_addr.
   // Look up and return the address of the stub for the given
   // (<file name>, <section name>, <symbol name>) tuple.
   // On success, returns a pair containing the stub address, plus the expression
   // remaining to be evaluated.
-  std::pair<EvalResult, StringRef> evalStubAddr(StringRef Expr,
-                                                ParseContext PCtx) const {
+  std::pair<EvalResult, StringRef>
+  evalStubOrGOTAddr(StringRef Expr, ParseContext PCtx, bool IsStubAddr) const {
     if (!Expr.startswith("("))
       return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");
     StringRef RemainingExpr = Expr.substr(1).ltrim();
 
     // Handle file-name specially, as it may contain characters that aren't
     // legal for symbols.
-    StringRef FileName;
+    StringRef StubContainerName;
     size_t ComaIdx = RemainingExpr.find(',');
-    FileName = RemainingExpr.substr(0, ComaIdx).rtrim();
+    StubContainerName = RemainingExpr.substr(0, ComaIdx).rtrim();
     RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim();
 
     if (!RemainingExpr.startswith(","))
@@ -342,14 +342,6 @@ private:
           unexpectedToken(RemainingExpr, Expr, "expected ','"), "");
     RemainingExpr = RemainingExpr.substr(1).ltrim();
 
-    StringRef SectionName;
-    std::tie(SectionName, RemainingExpr) = parseSymbol(RemainingExpr);
-
-    if (!RemainingExpr.startswith(","))
-      return std::make_pair(
-          unexpectedToken(RemainingExpr, Expr, "expected ','"), "");
-    RemainingExpr = RemainingExpr.substr(1).ltrim();
-
     StringRef Symbol;
     std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
 
@@ -360,8 +352,8 @@ private:
 
     uint64_t StubAddr;
     std::string ErrorMsg = "";
-    std::tie(StubAddr, ErrorMsg) = Checker.getStubAddrFor(
-        FileName, SectionName, Symbol, PCtx.IsInsideLoad);
+    std::tie(StubAddr, ErrorMsg) = Checker.getStubOrGOTAddrFor(
+        StubContainerName, Symbol, PCtx.IsInsideLoad, IsStubAddr);
 
     if (ErrorMsg != "")
       return std::make_pair(EvalResult(ErrorMsg), "");
@@ -421,7 +413,9 @@ private:
     else if (Symbol == "next_pc")
       return evalNextPC(RemainingExpr, PCtx);
     else if (Symbol == "stub_addr")
-      return evalStubAddr(RemainingExpr, PCtx);
+      return evalStubOrGOTAddr(RemainingExpr, PCtx, true);
+    else if (Symbol == "got_addr")
+      return evalStubOrGOTAddr(RemainingExpr, PCtx, false);
     else if (Symbol == "section_addr")
       return evalSectionAddr(RemainingExpr, PCtx);
 
@@ -676,22 +670,15 @@ private:
 }
 
 RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl(
-                      IsSymbolValidFunction IsSymbolValid,
-                      GetSymbolAddressFunction GetSymbolAddress,
-                      GetSymbolContentFunction GetSymbolContent,
-                      GetSectionLoadAddressFunction GetSectionLoadAddress,
-                      GetSectionContentFunction GetSectionContent,
-                      GetStubOffsetInSectionFunction GetStubOffsetInSection,
-                      support::endianness Endianness,
-                      MCDisassembler *Disassembler,
-                      MCInstPrinter *InstPrinter,
-                      raw_ostream &ErrStream)
+    IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
+    GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,
+    GetGOTInfoFunction GetGOTInfo, 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)),
+      GetSymbolInfo(std::move(GetSymbolInfo)),
+      GetSectionInfo(std::move(GetSectionInfo)),
+      GetStubInfo(std::move(GetStubInfo)), GetGOTInfo(std::move(GetGOTInfo)),
       Endianness(Endianness), Disassembler(Disassembler),
       InstPrinter(InstPrinter), ErrStream(ErrStream) {}
 
@@ -743,22 +730,23 @@ bool RuntimeDyldCheckerImpl::isSymbolValid(StringRef Symbol) const {
 }
 
 uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const {
-  auto Contents = GetSymbolContent(Symbol);
-  if (!Contents) {
-    logAllUnhandledErrors(Contents.takeError(), errs(), "RTDyldChecker: ");
+  auto SymInfo = GetSymbolInfo(Symbol);
+  if (!SymInfo) {
+    logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
     return 0;
   }
-  return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Contents->data()));
+  return static_cast<uint64_t>(
+      reinterpret_cast<uintptr_t>(SymInfo->Content.data()));
 }
 
 uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const {
-  auto Addr = GetSymbolAddress(Symbol);
-  if (!Addr) {
-    logAllUnhandledErrors(Addr.takeError(), errs(), "RTDyldChecker: ");
+  auto SymInfo = GetSymbolInfo(Symbol);
+  if (!SymInfo) {
+    logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
     return 0;
   }
 
-  return *Addr;
+  return SymInfo->TargetAddress;
 }
 
 uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr,
@@ -781,87 +769,79 @@ uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr,
 }
 
 StringRef RuntimeDyldCheckerImpl::getSymbolContent(StringRef Symbol) const {
-  auto Content = GetSymbolContent(Symbol);
-  if (!Content) {
-    logAllUnhandledErrors(Content.takeError(), errs(), "RTDyldChecker: ");
+  auto SymInfo = GetSymbolInfo(Symbol);
+  if (!SymInfo) {
+    logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
     return StringRef();
   }
-  return *Content;
+  return SymInfo->Content;
 }
 
 std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getSectionAddr(
     StringRef FileName, StringRef SectionName, bool IsInsideLoad) const {
 
-  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 {
+  auto SecInfo = GetSectionInfo(FileName, SectionName);
+  if (!SecInfo) {
+    std::string ErrMsg;
+    {
       raw_string_ostream ErrMsgStream(ErrMsg);
-      logAllUnhandledErrors(Content.takeError(), ErrMsgStream,
+      logAllUnhandledErrors(SecInfo.takeError(), ErrMsgStream,
                             "RTDyldChecker: ");
     }
-    return std::make_pair(Addr, std::move(ErrMsg));
+    return std::make_pair(0, std::move(ErrMsg));
   }
 
-  // ... otherwise return the target pointer.
-  if (auto LoadAddr = GetSectionLoadAddress(FileName, SectionName))
-    Addr = *LoadAddr;
-  else
-    return std::make_pair(Addr, ("Section (" + FileName + ", " +
-                                 SectionName + ") does not exist").str());
+  // If this address is being looked up in "load" mode, return the content
+  // pointer, otherwise return the target address.
 
-  return std::make_pair(Addr, std::move(ErrMsg));
-}
+  uint64_t Addr = 0;
 
-std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubAddrFor(
-    StringRef FileName, StringRef SectionName, StringRef SymbolName,
-    bool IsInsideLoad) const {
+  if (IsInsideLoad)
+    Addr = pointerToJITTargetAddress(SecInfo->Content.data());
+  else
+    Addr = SecInfo->TargetAddress;
 
-  auto SectionAddr = getSectionAddr(FileName, SectionName, IsInsideLoad);
+  return std::make_pair(Addr, "");
+}
 
-  if (!SectionAddr.second.empty())
-    return SectionAddr;
+std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubOrGOTAddrFor(
+    StringRef StubContainerName, StringRef SymbolName, bool IsInsideLoad,
+    bool IsStubAddr) const {
 
-  auto StubOffset = GetStubOffsetInSection(FileName, SectionName, SymbolName);
+  auto StubInfo = IsStubAddr ? GetStubInfo(StubContainerName, SymbolName)
+                             : GetGOTInfo(StubContainerName, SymbolName);
 
-  if (!StubOffset) {
+  if (!StubInfo) {
     std::string ErrMsg;
     {
       raw_string_ostream ErrMsgStream(ErrMsg);
-      logAllUnhandledErrors(StubOffset.takeError(), ErrMsgStream,
+      logAllUnhandledErrors(StubInfo.takeError(), ErrMsgStream,
                             "RTDyldChecker: ");
     }
     return std::make_pair((uint64_t)0, std::move(ErrMsg));
   }
 
-  return std::make_pair(SectionAddr.first + *StubOffset, "");
+  uint64_t Addr = 0;
+
+  if (IsInsideLoad)
+    Addr = pointerToJITTargetAddress(StubInfo->Content.data());
+  else
+    Addr = StubInfo->TargetAddress;
+
+  return std::make_pair(Addr, "");
 }
 
 RuntimeDyldChecker::RuntimeDyldChecker(
-                      IsSymbolValidFunction IsSymbolValid,
-                      GetSymbolAddressFunction GetSymbolAddress,
-                      GetSymbolContentFunction GetSymbolContent,
-                      GetSectionLoadAddressFunction GetSectionLoadAddress,
-                      GetSectionContentFunction GetSectionContent,
-                      GetStubOffsetInSectionFunction GetStubOffsetInSection,
-                      support::endianness Endianness,
-                      MCDisassembler *Disassembler,
-                      MCInstPrinter *InstPrinter,
-                      raw_ostream &ErrStream)
+    IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
+    GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,
+    GetGOTInfoFunction GetGOTInfo, support::endianness Endianness,
+    MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
+    raw_ostream &ErrStream)
     : Impl(::llvm::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)) {}
+          std::move(IsSymbolValid), std::move(GetSymbolInfo),
+          std::move(GetSectionInfo), std::move(GetStubInfo),
+          std::move(GetGOTInfo), Endianness, Disassembler, InstPrinter,
+          ErrStream)) {}
 
 RuntimeDyldChecker::~RuntimeDyldChecker() {}
 
index 0debd29cfd3c96b7859c50676a655c7b55a4cabb..ac9d4d4602174662c8b2ec2ba1e4205e40a40f39 100644 (file)
@@ -19,31 +19,18 @@ class RuntimeDyldCheckerImpl {
 
   using IsSymbolValidFunction =
     RuntimeDyldChecker::IsSymbolValidFunction;
-  using GetSymbolAddressFunction =
-    RuntimeDyldChecker::GetSymbolAddressFunction;
-  using GetSymbolContentFunction =
-    RuntimeDyldChecker::GetSymbolContentFunction;
-
-  using GetSectionLoadAddressFunction =
-    RuntimeDyldChecker::GetSectionLoadAddressFunction;
-  using GetSectionContentFunction =
-    RuntimeDyldChecker::GetSectionContentFunction;
-
-  using GetStubOffsetInSectionFunction =
-    RuntimeDyldChecker::GetStubOffsetInSectionFunction;
+  using GetSymbolInfoFunction = RuntimeDyldChecker::GetSymbolInfoFunction;
+  using GetSectionInfoFunction = RuntimeDyldChecker::GetSectionInfoFunction;
+  using GetStubInfoFunction = RuntimeDyldChecker::GetStubInfoFunction;
+  using GetGOTInfoFunction = RuntimeDyldChecker::GetGOTInfoFunction;
 
 public:
   RuntimeDyldCheckerImpl(
-                      IsSymbolValidFunction IsSymbolValid,
-                      GetSymbolAddressFunction GetSymbolAddress,
-                      GetSymbolContentFunction GetSymbolContent,
-                      GetSectionLoadAddressFunction GetSectionLoadAddress,
-                      GetSectionContentFunction GetSectionContent,
-                      GetStubOffsetInSectionFunction GetStubOffsetInSection,
-                      support::endianness Endianness,
-                      MCDisassembler *Disassembler,
-                      MCInstPrinter *InstPrinter,
-                      llvm::raw_ostream &ErrStream);
+      IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
+      GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,
+      GetGOTInfoFunction GetGOTInfo, support::endianness Endianness,
+      MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
+      llvm::raw_ostream &ErrStream);
 
   bool check(StringRef CheckExpr) const;
   bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
@@ -66,19 +53,17 @@ private:
                                                   StringRef SectionName,
                                                   bool IsInsideLoad) const;
 
-  std::pair<uint64_t, std::string> getStubAddrFor(StringRef FileName,
-                                                  StringRef SectionName,
-                                                  StringRef Symbol,
-                                                  bool IsInsideLoad) const;
+  std::pair<uint64_t, std::string>
+  getStubOrGOTAddrFor(StringRef StubContainerName, StringRef Symbol,
+                      bool IsInsideLoad, bool IsStubAddr) const;
 
   Optional<uint64_t> getSectionLoadAddress(void *LocalAddr) const;
 
   IsSymbolValidFunction IsSymbolValid;
-  GetSymbolAddressFunction GetSymbolAddress;
-  GetSymbolContentFunction GetSymbolContent;
-  GetSectionLoadAddressFunction GetSectionLoadAddress;
-  GetSectionContentFunction GetSectionContent;
-  GetStubOffsetInSectionFunction GetStubOffsetInSection;
+  GetSymbolInfoFunction GetSymbolInfo;
+  GetSectionInfoFunction GetSectionInfo;
+  GetStubInfoFunction GetStubInfo;
+  GetGOTInfoFunction GetGOTInfo;
   support::endianness Endianness;
   MCDisassembler *Disassembler;
   MCInstPrinter *InstPrinter;
index ec4809fd93b9780bfc9ec8e1c189234ae403d78c..ef0784e2273b88efcebb47de138ebbde00164b4c 100644 (file)
@@ -60,7 +60,7 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
   void resolveBPFRelocation(const SectionEntry &Section, uint64_t Offset,
                             uint64_t Value, uint32_t Type, int64_t Addend);
 
-  unsigned getMaxStubSize() override {
+  unsigned getMaxStubSize() const override {
     if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be)
       return 20; // movz; movk; movk; movk; br
     if (Arch == Triple::arm || Arch == Triple::thumb)
index 615a7280a3ab39b71b6fd9935951c21cfceecdcd..68b3468fbc9dc5bba8875fb4152ea33e241c1dee 100644 (file)
@@ -312,7 +312,7 @@ protected:
     RuntimeDyld::NotifyStubEmittedFunction;
   NotifyStubEmittedFunction NotifyStubEmitted;
 
-  virtual unsigned getMaxStubSize() = 0;
+  virtual unsigned getMaxStubSize() const = 0;
   virtual unsigned getStubAlignment() = 0;
 
   bool HasError;
@@ -485,8 +485,8 @@ public:
   }
 
   StringRef getSectionContent(unsigned SectionID) const {
-    return StringRef(reinterpret_cast<char*>(Sections[SectionID].getAddress()),
-                     Sections[SectionID].getSize());
+    return StringRef(reinterpret_cast<char *>(Sections[SectionID].getAddress()),
+                     Sections[SectionID].getStubOffset() + getMaxStubSize());
   }
 
   uint8_t* getSymbolLocalAddress(StringRef Name) const {
index d43aec688610a5b6b4ebe4a4e77494932754187d..40910bea0c364493c85bc6f68f20374558cb9378 100644 (file)
@@ -27,7 +27,7 @@ public:
                       JITSymbolResolver &Resolver)
       : RuntimeDyldCOFF(MM, Resolver) {}
 
-  unsigned getMaxStubSize() override {
+  unsigned getMaxStubSize() const override {
     return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad
   }
 
index 24b77d5056917570a2e7f667d1964bb6ca16e7cd..bb2e9626e0b07c538f1039b0a55395048d765b67 100644 (file)
@@ -50,7 +50,7 @@ public:
                        JITSymbolResolver &Resolver)
       : RuntimeDyldCOFF(MM, Resolver) {}
 
-  unsigned getMaxStubSize() override {
+  unsigned getMaxStubSize() const override {
     return 16; // 8-byte load instructions, 4-byte jump, 4-byte padding
   }
 
index 07a3e7bd9811baae21e4047dd0b5e7feb0d5f561..d2d74534cf902ce934a59690c9e80188f9aa8129 100644 (file)
@@ -61,7 +61,7 @@ public:
   unsigned getStubAlignment() override { return 1; }
 
   // 2-byte jmp instruction + 32-bit relative address + 64-bit absolute jump
-  unsigned getMaxStubSize() override { return 14; }
+  unsigned getMaxStubSize() const override { return 14; }
 
   // The target location for the relocation is described by RE.SectionID and
   // RE.Offset.  RE.SectionID can be used to find the SectionEntry.  Each
index c994e3032f0ab2f3655c6fe2aa077d2433f4ee08..f2ee1b06d4943b4b06667da9f763a5b9bb634ce7 100644 (file)
@@ -26,7 +26,7 @@ public:
                           JITSymbolResolver &Resolver)
       : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
 
-  unsigned getMaxStubSize() override { return 8; }
+  unsigned getMaxStubSize() const override { return 8; }
 
   unsigned getStubAlignment() override { return 8; }
 
index acc347a47621ced25de9f13b82553115adbb7c85..b7649e921c28e49f21cf8a35a9076ce36a42f743 100644 (file)
@@ -29,7 +29,7 @@ public:
                       JITSymbolResolver &Resolver)
     : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
 
-  unsigned getMaxStubSize() override { return 8; }
+  unsigned getMaxStubSize() const override { return 8; }
 
   unsigned getStubAlignment() override { return 4; }
 
index 4d216e8e0ca0a9bbe1c2942a60097ec2fee4987a..f0de27ba14bbc4455f11c4e02ac6ba0c976b48f3 100644 (file)
@@ -26,7 +26,7 @@ public:
                        JITSymbolResolver &Resolver)
       : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
 
-  unsigned getMaxStubSize() override { return 0; }
+  unsigned getMaxStubSize() const override { return 0; }
 
   unsigned getStubAlignment() override { return 1; }
 
index 0700f9af0d6e749f5ea1d3fd065aaf74c20c96c3..249f8dc0f29e559489516a863f2556a4fe408d17 100644 (file)
@@ -26,7 +26,7 @@ public:
                          JITSymbolResolver &Resolver)
       : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
 
-  unsigned getMaxStubSize() override { return 8; }
+  unsigned getMaxStubSize() const override { return 8; }
 
   unsigned getStubAlignment() override { return 1; }
 
index e9f915ece26ab302423fc32dd687fcb453da037b..ba823fb2d44a2af40d9ccc8aa6caaa9165d207a9 100644 (file)
@@ -51,9 +51,9 @@ ldr1:
 # adrp instruction and the GOT entry for ptr. ldr encodes the offset of the GOT
 # entry within the page. The ldr instruction perfroms an implicit shift on the
 # encoded immediate (imm<<3).
-# rtdyld-check:  *{8}(stub_addr(foo.o__text, _ptr)) = _ptr
-# rtdyld-check:  decode_operand(adrp2, 1) = (stub_addr(foo.o__text, _ptr)[32:12] - adrp2[32:12])
-# rtdyld-check:  decode_operand(ldr2, 2) = stub_addr(foo.o__text, _ptr)[11:3]
+# rtdyld-check:  *{8}(stub_addr(foo.o/__text, _ptr)) = _ptr
+# rtdyld-check:  decode_operand(adrp2, 1) = (stub_addr(foo.o/__text, _ptr)[32:12] - adrp2[32:12])
+# rtdyld-check:  decode_operand(ldr2, 2) = stub_addr(foo.o/__text, _ptr)[11:3]
     .globl  _test_adrp_ldr
     .align  2
 _test_got_adrp_ldr:
@@ -92,12 +92,12 @@ _subtractor_result:
     .quad _test_branch_reloc - _foo
 
 # Test 32-bit relative ARM64_RELOC_POINTER_TO_GOT
-# rtdyld-check: *{4}_pointer_to_got_32_rel = (stub_addr(foo.o__data, _dummy1) - _pointer_to_got_32_rel)
+# rtdyld-check: *{4}_pointer_to_got_32_rel = (stub_addr(foo.o/__data, _dummy1) - _pointer_to_got_32_rel)
 _pointer_to_got_32_rel:
     .long _dummy1@got - .
 
 # Test 64-bit absolute ARM64_RELOC_POINTER_TO_GOT
-# rtdyld-check: *{8}_pointer_to_got_64_abs = stub_addr(foo.o__data, _dummy1)
+# rtdyld-check: *{8}_pointer_to_got_64_abs = stub_addr(foo.o/__data, _dummy1)
 _pointer_to_got_64_abs:
     .quad _dummy1@got
 
index d3fa5fbed8073b65dc09588edce67a2522f5f825..d826b37b6b00071ab1bc0368d42ddf2082d0381f 100644 (file)
@@ -22,15 +22,15 @@ nextPC:
 # Check both the content of the stub, and the reference to the stub.
 # Stub should contain '0xe51ff004' (ldr pc, [pc, #-4]), followed by the target.
 #
-# rtdyld-check: *{4}(stub_addr(foo.o__text, baz)) = 0xe51ff004
-# rtdyld-check: *{4}(stub_addr(foo.o__text, baz) + 4) = baz
+# rtdyld-check: *{4}(stub_addr(foo.o/__text, baz)) = 0xe51ff004
+# rtdyld-check: *{4}(stub_addr(foo.o/__text, baz) + 4) = baz
 #
-# rtdyld-check: decode_operand(insn3, 0) = stub_addr(foo.o__text, baz) - (insn3 + 8)
+# rtdyld-check: decode_operand(insn3, 0) = stub_addr(foo.o/__text, baz) - (insn3 + 8)
 insn3:
         bl      baz
 
 # Check stub generation for internal symbols by referencing 'bar'.
-# rtdyld-check: *{4}(stub_addr(foo.o__text, bar) + 4) = bar
+# rtdyld-check: *{4}(stub_addr(foo.o/__text, bar) + 4) = bar
 insn4:
         bl      bar
         bx     lr
index e2e6e11e7d92d33e8da30bfe1a2613cbc24c5daf..4931b4165f878285febfbc7ca89b6c8f72602259 100644 (file)
@@ -35,14 +35,14 @@ thumb_caller:
 # Check that stubs for thumb callers use thumb code (not arm), and that thumb
 # callees have the low bit set on their addresses.
 #
-# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o__text, thumb_caller_thumb_callee)) = 0xf000f8df
-# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o__text, thumb_caller_thumb_callee) + 4) = (thumb_caller_thumb_callee | 0x1)
+# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o/__text, thumb_caller_thumb_callee)) = 0xf000f8df
+# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o/__text, thumb_caller_thumb_callee) + 4) = (thumb_caller_thumb_callee | 0x1)
         bl thumb_caller_thumb_callee
 
 # Check that arm callees do not have the low bit set on their addresses.
 #
-# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o__text, thumb_caller_arm_callee)) = 0xf000f8df
-# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o__text, thumb_caller_arm_callee) + 4) = thumb_caller_arm_callee
+# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o/__text, thumb_caller_arm_callee)) = 0xf000f8df
+# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o/__text, thumb_caller_arm_callee) + 4) = thumb_caller_arm_callee
         bl thumb_caller_arm_callee
 
         .globl  arm_caller
@@ -53,8 +53,8 @@ arm_caller:
 
 # Check that stubs for arm callers use arm code (not thumb), and that thumb
 # callees have the low bit set on their addresses.
-# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o__text, arm_caller_thumb_callee)) = 0xe51ff004
-# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o__text, arm_caller_thumb_callee) + 4) = (arm_caller_thumb_callee | 0x1)
+# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o/__text, arm_caller_thumb_callee)) = 0xe51ff004
+# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o/__text, arm_caller_thumb_callee) + 4) = (arm_caller_thumb_callee | 0x1)
         bl      arm_caller_thumb_callee
         nop
 
index fc2a277c3d22477f018b67565fbeace585fdc023..18e686706db28bf12eb4aa91a0669c48d53efab1 100644 (file)
@@ -44,7 +44,7 @@ bar:
        sd      $4, 8($fp)
 
 # Test R_MIPS_26 relocation.
-# rtdyld-check:  decode_operand(insn1, 0)[27:0] = stub_addr(test_ELF_Mips64N64.o.text, foo)[27:0]
+# rtdyld-check:  decode_operand(insn1, 0)[27:0] = stub_addr(test_ELF_Mips64N64.o/.text, foo)[27:0]
 insn1:
        .option pic0
        jal   foo
index 942979d645c55c8e636d2073422382f92667313b..46e764477ba5082d41678076e884e682f6ab246e 100644 (file)
@@ -44,7 +44,7 @@ bar:
        sd      $4, 8($fp)
 
 # Test R_MIPS_26 relocation.
-# rtdyld-check:  decode_operand(insn1, 0)[27:0] = stub_addr(test_ELF_N32.o.text, foo)[27:0]
+# rtdyld-check:  decode_operand(insn1, 0)[27:0] = stub_addr(test_ELF_N32.o/.text, foo)[27:0]
 insn1:
        .option pic0
        jal   foo
index 2a8ddff43ddfd83082814bfbbe1989690ecadb14..40002d44a10d65024a67045b688d2e73728af69e 100644 (file)
@@ -34,7 +34,7 @@ tmp1:
        .globl  bar
        .type   bar,@function
 bar:
-# rtdyld-check:  decode_operand(R_MIPS_26, 0)[27:0] = stub_addr(test_ELF_O32.o.text, foo)[27:0]
+# rtdyld-check:  decode_operand(R_MIPS_26, 0)[27:0] = stub_addr(test_ELF_O32.o/.text, foo)[27:0]
 # rtdyld-check:  decode_operand(R_MIPS_26, 0)[1:0] = 0
 R_MIPS_26:
        j   foo
index b43c84caf56c3b4a7bb1b8104f3f66b1b535dc79..852e75bb0eea8c60157ea207a82ad2cacf6aff6e 100644 (file)
@@ -25,11 +25,11 @@ bar:
        stdu 1, -32(1)
        .cfi_def_cfa_offset 32
        .cfi_offset lr, 16
-# rtdyld-check: (*{4}(stub_addr(ppc64_elf.o.text, foo) +  0)) [15:0] = foo_gep [63:48]
-# rtdyld-check: (*{4}(stub_addr(ppc64_elf.o.text, foo) +  4)) [15:0] = foo_gep [47:32]
-# rtdyld-check: (*{4}(stub_addr(ppc64_elf.o.text, foo) + 12)) [15:0] = foo_gep [31:16]
-# rtdyld-check: (*{4}(stub_addr(ppc64_elf.o.text, foo) + 16)) [15:0] = foo_gep [15:0]
-# rtdyld-check: decode_operand(foo_call, 0) = (stub_addr(ppc64_elf.o.text, foo) - foo_call) >> 2
+# rtdyld-check: (*{4}(stub_addr(ppc64_elf.o/.text, foo) +  0)) [15:0] = foo_gep [63:48]
+# rtdyld-check: (*{4}(stub_addr(ppc64_elf.o/.text, foo) +  4)) [15:0] = foo_gep [47:32]
+# rtdyld-check: (*{4}(stub_addr(ppc64_elf.o/.text, foo) + 12)) [15:0] = foo_gep [31:16]
+# rtdyld-check: (*{4}(stub_addr(ppc64_elf.o/.text, foo) + 16)) [15:0] = foo_gep [15:0]
+# rtdyld-check: decode_operand(foo_call, 0) = (stub_addr(ppc64_elf.o/.text, foo) - foo_call) >> 2
 foo_call:
        bl foo
        nop
index f5539fcb36772bcb0f862105285c5376ede9d456..dc69a150725978fc32ef40d63650fe7bf25782ef 100644 (file)
@@ -24,8 +24,8 @@ insn2:
 # Test PC-rel GOT relocation.
 # Verify both the contents of the GOT entry for y, and that the movq instruction
 # references the correct GOT entry address:
-# rtdyld-check: *{8}(stub_addr(test_x86-64.o__text, y)) = y
-# rtdyld-check: decode_operand(insn3, 4) = stub_addr(test_x86-64.o__text, y) - next_pc(insn3)
+# rtdyld-check: *{8}(stub_addr(test_x86-64.o/__text, y)) = y
+# rtdyld-check: decode_operand(insn3, 4) = stub_addr(test_x86-64.o/__text, y) - next_pc(insn3)
 insn3:
         movq   y@GOTPCREL(%rip), %rax
 
index b866ca7e0ad9adc19618a02db25a5c4bb95bf550..fde61eafac94e6a544315642e24576d95b99455e 100644 (file)
@@ -270,7 +270,6 @@ uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size,
     outs() << "allocateCodeSection(Size = " << Size << ", Alignment = "
            << Alignment << ", SectionName = " << SectionName << ")\n";
 
-  dbgs() << "  Registering code section \"" << SectionName << "\"\n";
   if (SecIDMap)
     (*SecIDMap)[SectionName] = SectionID;
 
@@ -299,7 +298,6 @@ uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size,
     outs() << "allocateDataSection(Size = " << Size << ", Alignment = "
            << Alignment << ", SectionName = " << SectionName << ")\n";
 
-  dbgs() << "  Registering code section \"" << SectionName << "\"\n";
   if (SecIDMap)
     (*SecIDMap)[SectionName] = SectionID;
 
@@ -742,28 +740,39 @@ static int linkAndVerify() {
   TrivialMemoryManager MemMgr;
   doPreallocation(MemMgr);
 
-  using StubOffsets = StringMap<uint32_t>;
-  using SectionStubs = StringMap<StubOffsets>;
-  using FileStubs = StringMap<SectionStubs>;
+  struct StubID {
+    unsigned SectionID;
+    uint32_t Offset;
+  };
+  using StubInfos = StringMap<StubID>;
+  using StubContainers = StringMap<StubInfos>;
 
-  FileStubs StubMap;
+  StubContainers StubMap;
   RuntimeDyld Dyld(MemMgr, MemMgr);
   Dyld.setProcessAllSections(true);
 
-  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();
-
+  Dyld.setNotifyStubEmitted([&StubMap](StringRef FilePath,
+                                       StringRef SectionName,
+                                       StringRef SymbolName, unsigned SectionID,
+                                       uint32_t StubOffset) {
+    std::string ContainerName =
+        (sys::path::filename(FilePath) + "/" + SectionName).str();
+    StubMap[ContainerName][SymbolName] = {SectionID, StubOffset};
+  });
+
+  auto GetSymbolInfo =
+      [&Dyld, &MemMgr](
+          StringRef Symbol) -> Expected<RuntimeDyldChecker::MemoryRegionInfo> {
+    RuntimeDyldChecker::MemoryRegionInfo SymInfo;
+
+    // First get the target address.
+    if (auto InternalSymbol = Dyld.getSymbol(Symbol))
+      SymInfo.TargetAddress = InternalSymbol.getAddress();
+    else {
+      // Symbol not found in RuntimeDyld. Fall back to external lookup.
 #ifdef _MSC_VER
-      using ExpectedLookupResult = MSVCPExpected<JITSymbolResolver::LookupResult>;
+      using ExpectedLookupResult =
+          MSVCPExpected<JITSymbolResolver::LookupResult>;
 #else
       using ExpectedLookupResult = Expected<JITSymbolResolver::LookupResult>;
 #endif
@@ -771,11 +780,10 @@ static int linkAndVerify() {
       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));
-        });
+      MemMgr.lookup(JITSymbolResolver::LookupSet({Symbol}),
+                    [=](Expected<JITSymbolResolver::LookupResult> Result) {
+                      ResultP->set_value(std::move(Result));
+                    });
 
       auto Result = ResultF.get();
       if (!Result)
@@ -784,61 +792,67 @@ static int linkAndVerify() {
       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;
+      SymInfo.TargetAddress = I->second.getAddress();
+    }
+
+    // Now find the symbol content if possible (otherwise leave content as a
+    // default-constructed StringRef).
+    if (auto *SymAddr = Dyld.getSymbolLocalAddress(Symbol)) {
+      unsigned SectionID = Dyld.getSymbolSectionID(Symbol);
+      if (SectionID != ~0U) {
+        char *CSymAddr = static_cast<char *>(SymAddr);
+        StringRef SecContent = Dyld.getSectionContent(SectionID);
+        uint64_t SymSize = SecContent.size() - (CSymAddr - SecContent.data());
+        SymInfo.Content = StringRef(CSymAddr, SymSize);
       }
-      return *Addr != 0;
-    };
+    }
+    return SymInfo;
+  };
+
+  auto IsSymbolValid = [&Dyld, GetSymbolInfo](StringRef Symbol) {
+    if (Dyld.getSymbol(Symbol))
+      return true;
+    auto SymInfo = GetSymbolInfo(Symbol);
+    if (!SymInfo) {
+      logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
+      return false;
+    }
+    return SymInfo->TargetAddress != 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];
-    };
+  auto GetSectionInfo = [&Dyld, &FileToSecIDMap](StringRef FileName,
+                                                 StringRef SectionName)
+      -> Expected<RuntimeDyldChecker::MemoryRegionInfo> {
+    auto SectionID = getSectionId(FileToSecIDMap, FileName, SectionName);
+    if (!SectionID)
+      return SectionID.takeError();
+    RuntimeDyldChecker::MemoryRegionInfo SecInfo;
+    SecInfo.TargetAddress = Dyld.getSectionLoadAddress(*SectionID);
+    SecInfo.Content = Dyld.getSectionContent(*SectionID);
+    return SecInfo;
+  };
+
+  auto GetStubInfo = [&Dyld, &StubMap](StringRef StubContainer,
+                                       StringRef SymbolName)
+      -> Expected<RuntimeDyldChecker::MemoryRegionInfo> {
+    if (!StubMap.count(StubContainer))
+      return make_error<StringError>("Stub container not found: " +
+                                         StubContainer,
+                                     inconvertibleErrorCode());
+    if (!StubMap[StubContainer].count(SymbolName))
+      return make_error<StringError>("Symbol name " + SymbolName +
+                                         " in stub container " + StubContainer,
+                                     inconvertibleErrorCode());
+    auto &SI = StubMap[StubContainer][SymbolName];
+    RuntimeDyldChecker::MemoryRegionInfo StubMemInfo;
+    StubMemInfo.TargetAddress =
+        Dyld.getSectionLoadAddress(SI.SectionID) + SI.Offset;
+    StubMemInfo.Content =
+        Dyld.getSectionContent(SI.SectionID).substr(SI.Offset);
+    return StubMemInfo;
+  };
 
   // We will initialize this below once we have the first object file and can
   // know the endianness.
@@ -869,19 +883,12 @@ 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());
+      Checker = llvm::make_unique<RuntimeDyldChecker>(
+          IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo,
+          GetStubInfo, 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