aboutsummaryrefslogtreecommitdiff
path: root/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp')
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp354
1 files changed, 120 insertions, 234 deletions
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
index 6eb6256080ff..ec31ea4e573c 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
@@ -1,23 +1,21 @@
//===--- RuntimeDyldChecker.cpp - RuntimeDyld tester framework --*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#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>
@@ -321,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(","))
@@ -344,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);
@@ -362,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), "");
@@ -423,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);
@@ -534,6 +526,11 @@ private:
uint64_t LoadAddr = LoadAddrExprResult.getValue();
+ // If there is no error but the content pointer is null then this is a
+ // zero-fill symbol/section.
+ if (LoadAddr == 0)
+ return std::make_pair(0, RemainingExpr);
+
return std::make_pair(
EvalResult(Checker.readMemoryAtAddr(LoadAddr, ReadSize)),
RemainingExpr);
@@ -666,27 +663,29 @@ private:
bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size) const {
MCDisassembler *Dis = Checker.Disassembler;
- StringRef SectionMem = Checker.getSubsectionStartingAt(Symbol);
- ArrayRef<uint8_t> SectionBytes(
- reinterpret_cast<const uint8_t *>(SectionMem.data()),
- 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, GetSymbolInfoFunction GetSymbolInfo,
+ GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,
+ GetGOTInfoFunction GetGOTInfo, support::endianness Endianness,
+ MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
+ raw_ostream &ErrStream)
+ : IsSymbolValid(std::move(IsSymbolValid)),
+ GetSymbolInfo(std::move(GetSymbolInfo)),
+ GetSectionInfo(std::move(GetSectionInfo)),
+ GetStubInfo(std::move(GetStubInfo)), GetGOTInfo(std::move(GetGOTInfo)),
+ Endianness(Endianness), Disassembler(Disassembler),
+ InstPrinter(InstPrinter), ErrStream(ErrStream) {}
bool RuntimeDyldCheckerImpl::check(StringRef CheckExpr) const {
CheckExpr = CheckExpr.trim();
@@ -731,242 +730,134 @@ bool RuntimeDyldCheckerImpl::checkAllRulesInBuffer(StringRef RulePrefix,
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});
+ return IsSymbolValid(Symbol);
+}
- if (!Result) {
- logAllUnhandledErrors(Result.takeError(), errs(), "RTDyldChecker: ");
- return false;
+uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const {
+ auto SymInfo = GetSymbolInfo(Symbol);
+ if (!SymInfo) {
+ logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
+ return 0;
}
- assert(Result->count(Symbol) && "Missing symbol result");
- return true;
-}
+ if (SymInfo->isZeroFill())
+ return 0;
-uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const {
return static_cast<uint64_t>(
- reinterpret_cast<uintptr_t>(getRTDyld().getSymbolLocalAddress(Symbol)));
+ reinterpret_cast<uintptr_t>(SymInfo->getContent().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 SymInfo = GetSymbolInfo(Symbol);
+ if (!SymInfo) {
+ logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
return 0;
}
- auto I = Result->find(Symbol);
- assert(I != Result->end() && "Missing symbol result");
- return I->second.getAddress();
+
+ return SymInfo->getTargetAddress();
}
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);
+ void *Ptr = reinterpret_cast<void*>(PtrSizedAddr);
+
+ 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");
}
-
-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);
+StringRef RuntimeDyldCheckerImpl::getSymbolContent(StringRef Symbol) const {
+ auto SymInfo = GetSymbolInfo(Symbol);
+ if (!SymInfo) {
+ logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
+ return StringRef();
}
-
- 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(""));
+ return SymInfo->getContent();
}
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].getAddress()));
- else
- Addr = getRTDyld().Sections[SectionID].getLoadAddress();
-
- return std::make_pair(Addr, std::string(""));
-}
-
-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 SecInfo = GetSectionInfo(FileName, SectionName);
+ if (!SecInfo) {
+ std::string ErrMsg;
+ {
+ raw_string_ostream ErrMsgStream(ErrMsg);
+ logAllUnhandledErrors(SecInfo.takeError(), ErrMsgStream,
+ "RTDyldChecker: ");
+ }
+ return std::make_pair(0, std::move(ErrMsg));
}
- 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 this address is being looked up in "load" mode, return the content
+ // pointer, otherwise return the target address.
- uint64_t StubOffset = StubOffsetItr->second;
+ uint64_t Addr = 0;
- 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();
- }
- 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();
+ if (SecInfo->isZeroFill())
+ Addr = 0;
+ else
+ Addr = pointerToJITTargetAddress(SecInfo->getContent().data());
+ } else
+ Addr = SecInfo->getTargetAddress();
- Stubs[FileName][SectionName].SectionID = SectionID;
+ return std::make_pair(Addr, "");
}
-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;
+std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubOrGOTAddrFor(
+ StringRef StubContainerName, StringRef SymbolName, bool IsInsideLoad,
+ bool IsStubAddr) const {
- for (auto &StubMapEntry : RTDyldStubs) {
- std::string SymbolName = "";
+ auto StubInfo = IsStubAddr ? GetStubInfo(StubContainerName, SymbolName)
+ : GetGOTInfo(StubContainerName, 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 (!StubInfo) {
+ std::string ErrMsg;
+ {
+ raw_string_ostream ErrMsgStream(ErrMsg);
+ logAllUnhandledErrors(StubInfo.takeError(), ErrMsgStream,
+ "RTDyldChecker: ");
}
-
- if (SymbolName != "")
- Stubs[FileName][SectionName].StubOffsets[SymbolName] =
- StubMapEntry.second;
+ return std::make_pair((uint64_t)0, std::move(ErrMsg));
}
-}
-RuntimeDyldChecker::RuntimeDyldChecker(RuntimeDyld &RTDyld,
- MCDisassembler *Disassembler,
- MCInstPrinter *InstPrinter,
- raw_ostream &ErrStream)
- : Impl(make_unique<RuntimeDyldCheckerImpl>(RTDyld, Disassembler,
- InstPrinter, ErrStream)) {}
+ uint64_t Addr = 0;
-RuntimeDyldChecker::~RuntimeDyldChecker() {}
+ if (IsInsideLoad) {
+ if (StubInfo->isZeroFill())
+ return std::make_pair((uint64_t)0, "Detected zero-filled stub/GOT entry");
+ Addr = pointerToJITTargetAddress(StubInfo->getContent().data());
+ } else
+ Addr = StubInfo->getTargetAddress();
-RuntimeDyld& RuntimeDyldChecker::getRTDyld() {
- return Impl->RTDyld;
+ return std::make_pair(Addr, "");
}
-const RuntimeDyld& RuntimeDyldChecker::getRTDyld() const {
- return Impl->RTDyld;
-}
+RuntimeDyldChecker::RuntimeDyldChecker(
+ 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(GetSymbolInfo),
+ std::move(GetSectionInfo), std::move(GetStubInfo),
+ std::move(GetGOTInfo), Endianness, Disassembler, InstPrinter,
+ ErrStream)) {}
+
+RuntimeDyldChecker::~RuntimeDyldChecker() {}
bool RuntimeDyldChecker::check(StringRef CheckExpr) const {
return Impl->check(CheckExpr);
@@ -982,8 +873,3 @@ RuntimeDyldChecker::getSectionAddr(StringRef FileName, StringRef SectionName,
bool LocalAddress) {
return Impl->getSectionAddr(FileName, SectionName, LocalAddress);
}
-
-Optional<uint64_t>
-RuntimeDyldChecker::getSectionLoadAddress(void *LocalAddress) const {
- return Impl->getSectionLoadAddress(LocalAddress);
-}