[MCJIT] Add a 'section_addr' builtin function to RuntimeDyldChecker.
authorLang Hames <lhames@gmail.com>
Wed, 3 Sep 2014 05:01:46 +0000 (05:01 +0000)
committerLang Hames <lhames@gmail.com>
Wed, 3 Sep 2014 05:01:46 +0000 (05:01 +0000)
The syntax of the new builtin is 'section_addr(<filename>, <section-name>)'
(similar to the stub_addr builtin, but without a symbol name). It returns the
base address of the given section in the given object file. This builtin makes
it possible to refer to the contents of sections that cannot contain symbols,
e.g. sections added by the linker itself, like __eh_frame.

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

lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h

index 537a683..d1b17ce 100644 (file)
@@ -550,6 +550,10 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
   }
 
   Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData));
+
+  if (Checker)
+    Checker->registerSection(Obj.getImageName(), SectionID);
+
   return SectionID;
 }
 
index aa44802..c42287a 100644 (file)
@@ -372,6 +372,43 @@ private:
     return std::make_pair(EvalResult(StubAddr), RemainingExpr);
   }
 
+  std::pair<EvalResult, StringRef> evalSectionAddr(StringRef Expr,
+                                                   ParseContext PCtx) 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;
+    size_t ComaIdx = RemainingExpr.find(',');
+    FileName = RemainingExpr.substr(0, ComaIdx).rtrim();
+    RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim();
+
+    if (!RemainingExpr.startswith(","))
+      return std::make_pair(
+          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();
+
+    uint64_t StubAddr;
+    std::string ErrorMsg = "";
+    std::tie(StubAddr, ErrorMsg) = Checker.getSectionAddr(
+        FileName, SectionName, PCtx.IsInsideLoad);
+
+    if (ErrorMsg != "")
+      return std::make_pair(EvalResult(ErrorMsg), "");
+
+    return std::make_pair(EvalResult(StubAddr), RemainingExpr);
+  }
+
   // Evaluate an identiefer expr, which may be a symbol, or a call to
   // one of the builtin functions: get_insn_opcode or get_insn_length.
   // Return the result, plus the expression remaining to be parsed.
@@ -388,6 +425,8 @@ private:
       return evalNextPC(RemainingExpr, PCtx);
     else if (Symbol == "stub_addr")
       return evalStubAddr(RemainingExpr, PCtx);
+    else if (Symbol == "section_addr")
+      return evalSectionAddr(RemainingExpr, PCtx);
 
     if (!Checker.isSymbolValid(Symbol)) {
       std::string ErrMsg("No known address for symbol '");
@@ -524,6 +563,10 @@ private:
       std::tie(SubExprResult, RemainingExpr) = evalIdentifierExpr(Expr, PCtx);
     else if (isdigit(Expr[0]))
       std::tie(SubExprResult, RemainingExpr) = evalNumberExpr(Expr);
+    else
+      return std::make_pair(
+          unexpectedToken(Expr, Expr,
+                          "expected '(', '*', identifier, or number"), "");
 
     if (SubExprResult.hasError())
       return std::make_pair(SubExprResult, RemainingExpr);
@@ -707,12 +750,13 @@ uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr,
   return getRTDyld().readBytesUnaligned(Src, Size);
 }
 
-std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubAddrFor(
-    StringRef FileName, StringRef SectionName, StringRef SymbolName,
-    bool IsInsideLoad) const {
 
-  auto SI1 = Stubs.find(FileName);
-  if (SI1 == Stubs.end()) {
+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. ";
@@ -727,23 +771,63 @@ std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubAddrFor(
       }
     }
     ErrorMsg += "\n";
-    return std::make_pair(0, ErrorMsg);
+    return std::make_pair(nullptr, ErrorMsg);
   }
 
-  const SectionStubMap &SectionStubs = SI1->second;
-  auto SI2 = SectionStubs.find(SectionName);
-  if (SI2 == SectionStubs.end())
-    return std::make_pair(0,
-                          ("Section '" + SectionName + "' not found.\n").str());
+  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());
+
+  return std::make_pair(&SectionInfoItr->second, std::string(""));
+}
+
+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);
+  }
+
+  unsigned SectionID = SectionInfo->SectionID;
+  uint64_t Addr;
+  if (IsInsideLoad)
+    Addr =
+      static_cast<uint64_t>(
+        reinterpret_cast<uintptr_t>(getRTDyld().Sections[SectionID].Address));
+  else
+    Addr = getRTDyld().Sections[SectionID].LoadAddress;
+
+  return std::make_pair(Addr, std::string(""));
+}
 
-  const SymbolStubMap &SymbolStubs = SI2->second;
-  auto SI3 = SymbolStubs.find(SymbolName);
-  if (SI3 == SymbolStubs.end())
+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);
+  }
+
+  unsigned SectionID = SectionInfo->SectionID;
+  const StubOffsetsMap &SymbolStubs = SectionInfo->StubOffsets;
+  auto StubOffsetItr = SymbolStubs.find(SymbolName);
+  if (StubOffsetItr == SymbolStubs.end())
     return std::make_pair(0,
                           ("Symbol '" + SymbolName + "' not found.\n").str());
 
-  unsigned SectionID = SI3->second.first;
-  uint64_t StubOffset = SI3->second.second;
+  uint64_t StubOffset = StubOffsetItr->second;
 
   uint64_t Addr;
   if (IsInsideLoad) {
@@ -770,12 +854,25 @@ RuntimeDyldCheckerImpl::getSubsectionStartingAt(StringRef Name) const {
                    getRTDyld().Sections[Loc.first].Size - Loc.second);
 }
 
+void RuntimeDyldCheckerImpl::registerSection(
+    StringRef FilePath, unsigned SectionID) {
+  StringRef FileName = sys::path::filename(FilePath);
+  const SectionEntry &Section = getRTDyld().Sections[SectionID];
+  StringRef SectionName = Section.Name;
+
+  dbgs() << "Registering " << SectionName << "\n";
+  Stubs[FileName][SectionName].SectionID = SectionID;
+}
+
 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.Name;
+
+  Stubs[FileName][SectionName].SectionID = SectionID;
+
   for (auto &StubMapEntry : RTDyldStubs) {
     std::string SymbolName = "";
 
@@ -795,8 +892,8 @@ void RuntimeDyldCheckerImpl::registerStubMap(
     }
 
     if (SymbolName != "")
-      Stubs[FileName][SectionName][SymbolName] =
-          StubLoc(SectionID, StubMapEntry.second);
+      Stubs[FileName][SectionName].StubOffsets[SymbolName] =
+        StubMapEntry.second;
   }
 }
 
index fd61865..2c8d9a5 100644 (file)
@@ -28,19 +28,39 @@ public:
   bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
 
 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; }
 
   bool isSymbolValid(StringRef Symbol) const;
   uint64_t getSymbolLinkerAddr(StringRef Symbol) const;
   uint64_t getSymbolRemoteAddr(StringRef Symbol) const;
   uint64_t readMemoryAtAddr(uint64_t Addr, unsigned Size) const;
-  std::pair<uint64_t, std::string> getStubAddrFor(StringRef FilePath,
+
+  std::pair<const SectionAddressInfo*, std::string> findSectionAddrInfo(
+                                                   StringRef FileName,
+                                                   StringRef SectionName) const;
+
+  std::pair<uint64_t, std::string> getSectionAddr(StringRef FileName,
+                                                  StringRef SectionName,
+                                                  bool IsInsideLoad) const;
+
+  std::pair<uint64_t, std::string> getStubAddrFor(StringRef FileName,
                                                   StringRef SectionName,
                                                   StringRef Symbol,
                                                   bool IsInsideLoad) const;
   StringRef getSubsectionStartingAt(StringRef Name) const;
 
-  void registerStubMap(StringRef FileName, unsigned SectionID,
+  void registerSection(StringRef FilePath, unsigned SectionID);
+  void registerStubMap(StringRef FilePath, unsigned SectionID,
                        const RuntimeDyldImpl::StubMap &RTDyldStubs);
 
   RuntimeDyld &RTDyld;
@@ -48,11 +68,6 @@ private:
   MCInstPrinter *InstPrinter;
   llvm::raw_ostream &ErrStream;
 
-  // StubMap typedefs.
-  typedef std::pair<unsigned, uint64_t> StubLoc;
-  typedef std::map<std::string, StubLoc> SymbolStubMap;
-  typedef std::map<std::string, SymbolStubMap> SectionStubMap;
-  typedef std::map<std::string, SectionStubMap> StubMap;
   StubMap Stubs;
 };
 }