llvm-6502/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
Lang Hames 5cfcad187b [RuntimeDyld] Improve error diagnostic in RuntimeDyldChecker.
The compiler often emits assembler-local labels (beginning with 'L') for use in
relocation expressions, however these aren't included in the object files.
Teach RuntimeDyldChecker to warn the user if they try to use one of these in an
expression, since it will never work.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@212777 91177308-0d34-0410-b5e6-96231b3b80d8
2014-07-10 23:26:20 +00:00

653 lines
25 KiB
C++

//===--- 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.
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/RuntimeDyldChecker.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Support/StringRefMemoryObject.h"
#include "RuntimeDyldImpl.h"
#include <cctype>
#include <memory>
#define DEBUG_TYPE "rtdyld"
using namespace llvm;
namespace llvm {
// Helper class that implements the language evaluated by RuntimeDyldChecker.
class RuntimeDyldCheckerExprEval {
public:
RuntimeDyldCheckerExprEval(const RuntimeDyldChecker &Checker,
llvm::raw_ostream &ErrStream)
: Checker(Checker), ErrStream(ErrStream) {}
bool evaluate(StringRef Expr) const {
// Expect equality expression of the form 'LHS = RHS'.
Expr = Expr.trim();
size_t EQIdx = Expr.find('=');
// Evaluate LHS.
StringRef LHSExpr = Expr.substr(0, EQIdx).rtrim();
StringRef RemainingExpr;
EvalResult LHSResult;
std::tie(LHSResult, RemainingExpr) =
evalComplexExpr(evalSimpleExpr(LHSExpr));
if (LHSResult.hasError())
return handleError(Expr, LHSResult);
if (RemainingExpr != "")
return handleError(Expr, unexpectedToken(RemainingExpr, LHSExpr, ""));
// Evaluate RHS.
StringRef RHSExpr = Expr.substr(EQIdx + 1).ltrim();
EvalResult RHSResult;
std::tie(RHSResult, RemainingExpr) =
evalComplexExpr(evalSimpleExpr(RHSExpr));
if (RHSResult.hasError())
return handleError(Expr, RHSResult);
if (RemainingExpr != "")
return handleError(Expr, unexpectedToken(RemainingExpr, RHSExpr, ""));
if (LHSResult.getValue() != RHSResult.getValue()) {
ErrStream << "Expression '" << Expr << "' is false: "
<< format("0x%lx", LHSResult.getValue()) << " != "
<< format("0x%lx", RHSResult.getValue()) << "\n";
return false;
}
return true;
}
private:
const RuntimeDyldChecker &Checker;
llvm::raw_ostream &ErrStream;
enum class BinOpToken : unsigned { Invalid, Add, Sub, BitwiseAnd,
BitwiseOr, ShiftLeft, ShiftRight };
class EvalResult {
public:
EvalResult()
: Value(0), ErrorMsg("") {}
EvalResult(uint64_t Value)
: Value(Value), ErrorMsg("") {}
EvalResult(std::string ErrorMsg)
: Value(0), ErrorMsg(ErrorMsg) {}
uint64_t getValue() const { return Value; }
bool hasError() const { return ErrorMsg != ""; }
const std::string& getErrorMsg() const { return ErrorMsg; }
private:
uint64_t Value;
std::string ErrorMsg;
};
StringRef getTokenForError(StringRef Expr) const {
if (Expr.empty())
return "";
StringRef Token, Remaining;
if (isalpha(Expr[0]))
std::tie(Token, Remaining) = parseSymbol(Expr);
else if (isdigit(Expr[0]))
std::tie(Token, Remaining) = parseNumberString(Expr);
else {
unsigned TokLen = 1;
if (Expr.startswith("<<") || Expr.startswith(">>"))
TokLen = 2;
Token = Expr.substr(0, TokLen);
}
return Token;
}
EvalResult unexpectedToken(StringRef TokenStart,
StringRef SubExpr,
StringRef ErrText) const {
std::string ErrorMsg("Encountered unexpected token '");
ErrorMsg += getTokenForError(TokenStart);
if (SubExpr != "") {
ErrorMsg += "' while parsing subexpression '";
ErrorMsg += SubExpr;
}
ErrorMsg += "'";
if (ErrText != "") {
ErrorMsg += " ";
ErrorMsg += ErrText;
}
return EvalResult(std::move(ErrorMsg));
}
bool handleError(StringRef Expr, const EvalResult &R) const {
assert(R.hasError() && "Not an error result.");
ErrStream << "Error evaluating expression '" << Expr << "': "
<< R.getErrorMsg() << "\n";
return false;
}
std::pair<BinOpToken, StringRef> parseBinOpToken(StringRef Expr) const {
if (Expr.empty())
return std::make_pair(BinOpToken::Invalid, "");
// Handle the two 2-character tokens.
if (Expr.startswith("<<"))
return std::make_pair(BinOpToken::ShiftLeft,
Expr.substr(2).ltrim());
if (Expr.startswith(">>"))
return std::make_pair(BinOpToken::ShiftRight,
Expr.substr(2).ltrim());
// Handle one-character tokens.
BinOpToken Op;
switch (Expr[0]) {
default: return std::make_pair(BinOpToken::Invalid, Expr);
case '+': Op = BinOpToken::Add; break;
case '-': Op = BinOpToken::Sub; break;
case '&': Op = BinOpToken::BitwiseAnd; break;
case '|': Op = BinOpToken::BitwiseOr; break;
}
return std::make_pair(Op, Expr.substr(1).ltrim());
}
EvalResult computeBinOpResult(BinOpToken Op, const EvalResult &LHSResult,
const EvalResult &RHSResult) const {
switch (Op) {
default: llvm_unreachable("Tried to evaluate unrecognized operation.");
case BinOpToken::Add:
return EvalResult(LHSResult.getValue() + RHSResult.getValue());
case BinOpToken::Sub:
return EvalResult(LHSResult.getValue() - RHSResult.getValue());
case BinOpToken::BitwiseAnd:
return EvalResult(LHSResult.getValue() & RHSResult.getValue());
case BinOpToken::BitwiseOr:
return EvalResult(LHSResult.getValue() | RHSResult.getValue());
case BinOpToken::ShiftLeft:
return EvalResult(LHSResult.getValue() << RHSResult.getValue());
case BinOpToken::ShiftRight:
return EvalResult(LHSResult.getValue() >> RHSResult.getValue());
}
}
// Parse a symbol and return a (string, string) pair representing the symbol
// name and expression remaining to be parsed.
std::pair<StringRef, StringRef> parseSymbol(StringRef Expr) const {
size_t FirstNonSymbol =
Expr.find_first_not_of("0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
":_");
return std::make_pair(Expr.substr(0, FirstNonSymbol),
Expr.substr(FirstNonSymbol).ltrim());
}
// Evaluate a call to decode_operand. Decode the instruction operand at the
// given symbol and get the value of the requested operand.
// Returns an error if the instruction cannot be decoded, or the requested
// operand is not an immediate.
// On success, retuns a pair containing the value of the operand, plus
// the expression remaining to be evaluated.
std::pair<EvalResult, StringRef> evalDecodeOperand(StringRef Expr) const {
if (!Expr.startswith("("))
return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");
StringRef RemainingExpr = Expr.substr(1).ltrim();
StringRef Symbol;
std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
if (!Checker.isSymbolValid(Symbol))
return std::make_pair(EvalResult(("Cannot decode unknown symbol '" +
Symbol + "'").str()),
"");
if (!RemainingExpr.startswith(","))
return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr,
"expected ','"),
"");
RemainingExpr = RemainingExpr.substr(1).ltrim();
EvalResult OpIdxExpr;
std::tie(OpIdxExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
if (OpIdxExpr.hasError())
return std::make_pair(OpIdxExpr, "");
if (!RemainingExpr.startswith(")"))
return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr,
"expected ')'"),
"");
RemainingExpr = RemainingExpr.substr(1).ltrim();
MCInst Inst;
uint64_t Size;
if (!decodeInst(Symbol, Inst, Size))
return std::make_pair(EvalResult(("Couldn't decode instruction at '" +
Symbol + "'").str()),
"");
unsigned OpIdx = OpIdxExpr.getValue();
if (OpIdx >= Inst.getNumOperands()) {
std::string ErrMsg;
raw_string_ostream ErrMsgStream(ErrMsg);
ErrMsgStream << "Invalid operand index '" << format("%i", OpIdx)
<< " for instruction '" << Symbol
<< ". Instruction has only "
<< format("%i", Inst.getNumOperands()) << " operands.";
return std::make_pair(EvalResult(ErrMsgStream.str()), "");
}
const MCOperand &Op = Inst.getOperand(OpIdx);
if (!Op.isImm()) {
std::string ErrMsg;
raw_string_ostream ErrMsgStream(ErrMsg);
ErrMsgStream << "Operand '" << format("%i", OpIdx)
<< "' of instruction '" << Symbol
<< "' is not an immediate.\nInstruction is:\n ";
Inst.dump_pretty(ErrMsgStream,
Checker.Disassembler->getContext().getAsmInfo(),
Checker.InstPrinter);
return std::make_pair(EvalResult(ErrMsgStream.str()), "");
}
return std::make_pair(EvalResult(Op.getImm()), RemainingExpr);
}
// Evaluate a call to next_pc. Decode the instruction at the given
// symbol and return the following program counter..
// Returns an error if the instruction cannot be decoded.
// On success, returns a pair containing the next PC, plus the length of the
// expression remaining to be evaluated.
std::pair<EvalResult, StringRef> evalNextPC(StringRef Expr) const {
if (!Expr.startswith("("))
return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");
StringRef RemainingExpr = Expr.substr(1).ltrim();
StringRef Symbol;
std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
if (!Checker.isSymbolValid(Symbol))
return std::make_pair(EvalResult(("Cannot decode unknown symbol '"
+ Symbol + "'").str()),
"");
if (!RemainingExpr.startswith(")"))
return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr,
"expected ')'"),
"");
RemainingExpr = RemainingExpr.substr(1).ltrim();
MCInst Inst;
uint64_t Size;
if (!decodeInst(Symbol, Inst, Size))
return std::make_pair(EvalResult(("Couldn't decode instruction at '" +
Symbol + "'").str()),
"");
uint64_t NextPC = Checker.getSymbolAddress(Symbol) + Size;
return std::make_pair(EvalResult(NextPC), 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.
std::pair<EvalResult, StringRef> evalIdentifierExpr(StringRef Expr) const {
StringRef Symbol;
StringRef RemainingExpr;
std::tie(Symbol, RemainingExpr) = parseSymbol(Expr);
// Check for builtin function calls.
if (Symbol == "decode_operand")
return evalDecodeOperand(RemainingExpr);
else if (Symbol == "next_pc")
return evalNextPC(RemainingExpr);
if (!Checker.isSymbolValid(Symbol)) {
std::string ErrMsg("No known address for symbol '");
ErrMsg += Symbol;
ErrMsg += "'";
if (Symbol.startswith("L"))
ErrMsg += " (this appears to be an assembler local label - "
" perhaps drop the 'L'?)";
return std::make_pair(EvalResult(ErrMsg), "");
}
// Looks like a plain symbol reference.
return std::make_pair(EvalResult(Checker.getSymbolAddress(Symbol)),
RemainingExpr);
}
// Parse a number (hexadecimal or decimal) and return a (string, string)
// pair representing the number and the expression remaining to be parsed.
std::pair<StringRef, StringRef> parseNumberString(StringRef Expr) const {
size_t FirstNonDigit = StringRef::npos;
if (Expr.startswith("0x")) {
FirstNonDigit = Expr.find_first_not_of("0123456789abcdefABCDEF", 2);
if (FirstNonDigit == StringRef::npos)
FirstNonDigit = Expr.size();
} else {
FirstNonDigit = Expr.find_first_not_of("0123456789");
if (FirstNonDigit == StringRef::npos)
FirstNonDigit = Expr.size();
}
return std::make_pair(Expr.substr(0, FirstNonDigit),
Expr.substr(FirstNonDigit));
}
// Evaluate a constant numeric expression (hexidecimal or decimal) and
// return a pair containing the result, and the expression remaining to be
// evaluated.
std::pair<EvalResult, StringRef> evalNumberExpr(StringRef Expr) const {
StringRef ValueStr;
StringRef RemainingExpr;
std::tie(ValueStr, RemainingExpr) = parseNumberString(Expr);
if (ValueStr.empty() || !isdigit(ValueStr[0]))
return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr,
"expected number"),
"");
uint64_t Value;
ValueStr.getAsInteger(0, Value);
return std::make_pair(EvalResult(Value), RemainingExpr);
}
// Evaluate an expression of the form "(<expr>)" and return a pair
// containing the result of evaluating <expr>, plus the expression
// remaining to be parsed.
std::pair<EvalResult, StringRef> evalParensExpr(StringRef Expr) const {
assert(Expr.startswith("(") && "Not a parenthesized expression");
EvalResult SubExprResult;
StringRef RemainingExpr;
std::tie(SubExprResult, RemainingExpr) =
evalComplexExpr(evalSimpleExpr(Expr.substr(1).ltrim()));
if (SubExprResult.hasError())
return std::make_pair(SubExprResult, "");
if (!RemainingExpr.startswith(")"))
return std::make_pair(unexpectedToken(RemainingExpr, Expr,
"expected ')'"),
"");
RemainingExpr = RemainingExpr.substr(1).ltrim();
return std::make_pair(SubExprResult, RemainingExpr);
}
// Evaluate an expression in one of the following forms:
// *{<number>}<symbol>
// *{<number>}(<symbol> + <number>)
// *{<number>}(<symbol> - <number>)
// Return a pair containing the result, plus the expression remaining to be
// parsed.
std::pair<EvalResult, StringRef> evalLoadExpr(StringRef Expr) const {
assert(Expr.startswith("*") && "Not a load expression");
StringRef RemainingExpr = Expr.substr(1).ltrim();
// Parse read size.
if (!RemainingExpr.startswith("{"))
return std::make_pair(EvalResult("Expected '{' following '*'."), "");
RemainingExpr = RemainingExpr.substr(1).ltrim();
EvalResult ReadSizeExpr;
std::tie(ReadSizeExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
if (ReadSizeExpr.hasError())
return std::make_pair(ReadSizeExpr, RemainingExpr);
uint64_t ReadSize = ReadSizeExpr.getValue();
if (ReadSize < 1 || ReadSize > 8)
return std::make_pair(EvalResult("Invalid size for dereference."), "");
if (!RemainingExpr.startswith("}"))
return std::make_pair(EvalResult("Missing '}' for dereference."), "");
RemainingExpr = RemainingExpr.substr(1).ltrim();
// Check for '(symbol +/- constant)' form.
bool SymbolPlusConstant = false;
if (RemainingExpr.startswith("(")) {
SymbolPlusConstant = true;
RemainingExpr = RemainingExpr.substr(1).ltrim();
}
// Read symbol.
StringRef Symbol;
std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
if (!Checker.isSymbolValid(Symbol))
return std::make_pair(EvalResult(("Cannot dereference unknown symbol '"
+ Symbol + "'").str()),
"");
// Set up defaut offset.
int64_t Offset = 0;
// Handle "+/- constant)" portion if necessary.
if (SymbolPlusConstant) {
char OpChar = RemainingExpr[0];
if (OpChar != '+' && OpChar != '-')
return std::make_pair(EvalResult("Invalid operator in load address."),
"");
RemainingExpr = RemainingExpr.substr(1).ltrim();
EvalResult OffsetExpr;
std::tie(OffsetExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
Offset = (OpChar == '+') ?
OffsetExpr.getValue() : -1 * OffsetExpr.getValue();
if (!RemainingExpr.startswith(")"))
return std::make_pair(EvalResult("Missing ')' in load address."),
"");
RemainingExpr = RemainingExpr.substr(1).ltrim();
}
return std::make_pair(
EvalResult(Checker.readMemoryAtSymbol(Symbol, Offset, ReadSize)),
RemainingExpr);
}
// Evaluate a "simple" expression. This is any expression that _isn't_ an
// un-parenthesized binary expression.
//
// "Simple" expressions can be optionally bit-sliced. See evalSlicedExpr.
//
// Returns a pair containing the result of the evaluation, plus the
// expression remaining to be parsed.
std::pair<EvalResult, StringRef> evalSimpleExpr(StringRef Expr) const {
EvalResult SubExprResult;
StringRef RemainingExpr;
if (Expr.empty())
return std::make_pair(EvalResult("Unexpected end of expression"), "");
if (Expr[0] == '(')
std::tie(SubExprResult, RemainingExpr) = evalParensExpr(Expr);
else if (Expr[0] == '*')
std::tie(SubExprResult, RemainingExpr) = evalLoadExpr(Expr);
else if (isalpha(Expr[0]))
std::tie(SubExprResult, RemainingExpr) = evalIdentifierExpr(Expr);
else if (isdigit(Expr[0]))
std::tie(SubExprResult, RemainingExpr) = evalNumberExpr(Expr);
if (SubExprResult.hasError())
return std::make_pair(SubExprResult, RemainingExpr);
// Evaluate bit-slice if present.
if (RemainingExpr.startswith("["))
std::tie(SubExprResult, RemainingExpr) =
evalSliceExpr(std::make_pair(SubExprResult, RemainingExpr));
return std::make_pair(SubExprResult, RemainingExpr);
}
// Evaluate a bit-slice of an expression.
// A bit-slice has the form "<expr>[high:low]". The result of evaluating a
// slice is the bits between high and low (inclusive) in the original
// expression, right shifted so that the "low" bit is in position 0 in the
// result.
// Returns a pair containing the result of the slice operation, plus the
// expression remaining to be parsed.
std::pair<EvalResult, StringRef> evalSliceExpr(
std::pair<EvalResult, StringRef> Ctx) const{
EvalResult SubExprResult;
StringRef RemainingExpr;
std::tie(SubExprResult, RemainingExpr) = Ctx;
assert(RemainingExpr.startswith("[") && "Not a slice expr.");
RemainingExpr = RemainingExpr.substr(1).ltrim();
EvalResult HighBitExpr;
std::tie(HighBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
if (HighBitExpr.hasError())
return std::make_pair(HighBitExpr, RemainingExpr);
if (!RemainingExpr.startswith(":"))
return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr,
"expected ':'"),
"");
RemainingExpr = RemainingExpr.substr(1).ltrim();
EvalResult LowBitExpr;
std::tie(LowBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
if (LowBitExpr.hasError())
return std::make_pair(LowBitExpr, RemainingExpr);
if (!RemainingExpr.startswith("]"))
return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr,
"expected ']'"),
"");
RemainingExpr = RemainingExpr.substr(1).ltrim();
unsigned HighBit = HighBitExpr.getValue();
unsigned LowBit = LowBitExpr.getValue();
uint64_t Mask = ((uint64_t)1 << (HighBit - LowBit + 1)) - 1;
uint64_t SlicedValue = (SubExprResult.getValue() >> LowBit) & Mask;
return std::make_pair(EvalResult(SlicedValue), RemainingExpr);
}
// Evaluate a "complex" expression.
// Takes an already evaluated subexpression and checks for the presence of a
// binary operator, computing the result of the binary operation if one is
// found. Used to make arithmetic expressions left-associative.
// Returns a pair containing the ultimate result of evaluating the
// expression, plus the expression remaining to be evaluated.
std::pair<EvalResult, StringRef> evalComplexExpr(
std::pair<EvalResult, StringRef> Ctx) const {
EvalResult LHSResult;
StringRef RemainingExpr;
std::tie(LHSResult, RemainingExpr) = Ctx;
// If there was an error, or there's nothing left to evaluate, return the
// result.
if (LHSResult.hasError() || RemainingExpr == "")
return std::make_pair(LHSResult, RemainingExpr);
// Otherwise check if this is a binary expressioan.
BinOpToken BinOp;
std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr);
// If this isn't a recognized expression just return.
if (BinOp == BinOpToken::Invalid)
return std::make_pair(LHSResult, RemainingExpr);
// This is a recognized bin-op. Evaluate the RHS, then evaluate the binop.
EvalResult RHSResult;
std::tie(RHSResult, RemainingExpr) = evalSimpleExpr(RemainingExpr);
// If there was an error evaluating the RHS, return it.
if (RHSResult.hasError())
return std::make_pair(RHSResult, RemainingExpr);
// This is a binary expression - evaluate and try to continue as a
// complex expr.
EvalResult ThisResult(computeBinOpResult(BinOp, LHSResult, RHSResult));
return evalComplexExpr(std::make_pair(ThisResult, RemainingExpr));
}
bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size) const {
MCDisassembler *Dis = Checker.Disassembler;
StringRef SectionMem = Checker.getSubsectionStartingAt(Symbol);
StringRefMemoryObject SectionBytes(SectionMem, 0);
MCDisassembler::DecodeStatus S =
Dis->getInstruction(Inst, Size, SectionBytes, 0, nulls(), nulls());
return (S == MCDisassembler::Success);
}
};
}
bool RuntimeDyldChecker::check(StringRef CheckExpr) const {
CheckExpr = CheckExpr.trim();
DEBUG(llvm::dbgs() << "RuntimeDyldChecker: Checking '" << CheckExpr
<< "'...\n");
RuntimeDyldCheckerExprEval P(*this, ErrStream);
bool Result = P.evaluate(CheckExpr);
(void)Result;
DEBUG(llvm::dbgs() << "RuntimeDyldChecker: '" << CheckExpr << "' "
<< (Result ? "passed" : "FAILED") << ".\n");
return Result;
}
bool RuntimeDyldChecker::checkAllRulesInBuffer(StringRef RulePrefix,
MemoryBuffer* MemBuf) const {
bool DidAllTestsPass = true;
unsigned NumRules = 0;
const char *LineStart = MemBuf->getBufferStart();
// Eat whitespace.
while (LineStart != MemBuf->getBufferEnd() &&
std::isspace(*LineStart))
++LineStart;
while (LineStart != MemBuf->getBufferEnd() && *LineStart != '\0') {
const char *LineEnd = LineStart;
while (LineEnd != MemBuf->getBufferEnd() &&
*LineEnd != '\r' && *LineEnd != '\n')
++LineEnd;
StringRef Line(LineStart, LineEnd - LineStart);
if (Line.startswith(RulePrefix)) {
DidAllTestsPass &= check(Line.substr(RulePrefix.size()));
++NumRules;
}
// Eat whitespace.
LineStart = LineEnd;
while (LineStart != MemBuf->getBufferEnd() &&
std::isspace(*LineStart))
++LineStart;
}
return DidAllTestsPass && (NumRules != 0);
}
bool RuntimeDyldChecker::isSymbolValid(StringRef Symbol) const {
return RTDyld.getSymbolAddress(Symbol) != nullptr;
}
uint64_t RuntimeDyldChecker::getSymbolAddress(StringRef Symbol) const {
return RTDyld.getAnySymbolRemoteAddress(Symbol);
}
uint64_t RuntimeDyldChecker::readMemoryAtSymbol(StringRef Symbol,
int64_t Offset,
unsigned Size) const {
uint8_t *Src = RTDyld.getSymbolAddress(Symbol);
uint64_t Result = 0;
memcpy(&Result, Src + Offset, Size);
return Result;
}
StringRef RuntimeDyldChecker::getSubsectionStartingAt(StringRef Name) const {
RuntimeDyldImpl::SymbolTableMap::const_iterator pos =
RTDyld.GlobalSymbolTable.find(Name);
if (pos == RTDyld.GlobalSymbolTable.end())
return StringRef();
RuntimeDyldImpl::SymbolLoc Loc = pos->second;
uint8_t *SectionAddr = RTDyld.getSectionAddress(Loc.first);
return StringRef(reinterpret_cast<const char*>(SectionAddr) + Loc.second,
RTDyld.Sections[Loc.first].Size - Loc.second);
}