LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/RuntimeDyld - RuntimeDyldChecker.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 283 403 70.2 %
Date: 2018-06-17 00:07:59 Functions: 37 42 88.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===--- RuntimeDyldChecker.cpp - RuntimeDyld tester framework --*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "llvm/ExecutionEngine/RuntimeDyldChecker.h"
      11             : #include "RuntimeDyldCheckerImpl.h"
      12             : #include "RuntimeDyldImpl.h"
      13             : #include "llvm/ADT/STLExtras.h"
      14             : #include "llvm/MC/MCContext.h"
      15             : #include "llvm/MC/MCDisassembler/MCDisassembler.h"
      16             : #include "llvm/MC/MCInst.h"
      17             : #include "llvm/Support/Path.h"
      18             : #include <cctype>
      19             : #include <memory>
      20             : #include <utility>
      21             : 
      22             : #define DEBUG_TYPE "rtdyld"
      23             : 
      24             : using namespace llvm;
      25             : 
      26             : namespace llvm {
      27             : 
      28             : // Helper class that implements the language evaluated by RuntimeDyldChecker.
      29             : class RuntimeDyldCheckerExprEval {
      30             : public:
      31             :   RuntimeDyldCheckerExprEval(const RuntimeDyldCheckerImpl &Checker,
      32             :                              raw_ostream &ErrStream)
      33         212 :       : Checker(Checker) {}
      34             : 
      35         212 :   bool evaluate(StringRef Expr) const {
      36             :     // Expect equality expression of the form 'LHS = RHS'.
      37         212 :     Expr = Expr.trim();
      38             :     size_t EQIdx = Expr.find('=');
      39             : 
      40             :     ParseContext OutsideLoad(false);
      41             : 
      42             :     // Evaluate LHS.
      43         424 :     StringRef LHSExpr = Expr.substr(0, EQIdx).rtrim();
      44             :     StringRef RemainingExpr;
      45             :     EvalResult LHSResult;
      46             :     std::tie(LHSResult, RemainingExpr) =
      47         636 :         evalComplexExpr(evalSimpleExpr(LHSExpr, OutsideLoad), OutsideLoad);
      48         212 :     if (LHSResult.hasError())
      49           0 :       return handleError(Expr, LHSResult);
      50             :     if (RemainingExpr != "")
      51           0 :       return handleError(Expr, unexpectedToken(RemainingExpr, LHSExpr, ""));
      52             : 
      53             :     // Evaluate RHS.
      54         636 :     StringRef RHSExpr = Expr.substr(EQIdx + 1).ltrim();
      55             :     EvalResult RHSResult;
      56             :     std::tie(RHSResult, RemainingExpr) =
      57         636 :         evalComplexExpr(evalSimpleExpr(RHSExpr, OutsideLoad), OutsideLoad);
      58         212 :     if (RHSResult.hasError())
      59           0 :       return handleError(Expr, RHSResult);
      60             :     if (RemainingExpr != "")
      61           0 :       return handleError(Expr, unexpectedToken(RemainingExpr, RHSExpr, ""));
      62             : 
      63         212 :     if (LHSResult.getValue() != RHSResult.getValue()) {
      64           0 :       Checker.ErrStream << "Expression '" << Expr << "' is false: "
      65           0 :                         << format("0x%" PRIx64, LHSResult.getValue())
      66           0 :                         << " != " << format("0x%" PRIx64, RHSResult.getValue())
      67           0 :                         << "\n";
      68           0 :       return false;
      69             :     }
      70             :     return true;
      71             :   }
      72             : 
      73             : private:
      74             :   // RuntimeDyldCheckerExprEval requires some context when parsing exprs. In
      75             :   // particular, it needs to know whether a symbol is being evaluated in the
      76             :   // context of a load, in which case we want the linker's local address for
      77             :   // the symbol, or outside of a load, in which case we want the symbol's
      78             :   // address in the remote target.
      79             : 
      80             :   struct ParseContext {
      81             :     bool IsInsideLoad;
      82         329 :     ParseContext(bool IsInsideLoad) : IsInsideLoad(IsInsideLoad) {}
      83             :   };
      84             : 
      85             :   const RuntimeDyldCheckerImpl &Checker;
      86             : 
      87             :   enum class BinOpToken : unsigned {
      88             :     Invalid,
      89             :     Add,
      90             :     Sub,
      91             :     BitwiseAnd,
      92             :     BitwiseOr,
      93             :     ShiftLeft,
      94             :     ShiftRight
      95             :   };
      96             : 
      97        8669 :   class EvalResult {
      98             :   public:
      99        3594 :     EvalResult() : Value(0), ErrorMsg("") {}
     100        1724 :     EvalResult(uint64_t Value) : Value(Value), ErrorMsg("") {}
     101             :     EvalResult(std::string ErrorMsg)
     102           0 :         : Value(0), ErrorMsg(std::move(ErrorMsg)) {}
     103             :     uint64_t getValue() const { return Value; }
     104             :     bool hasError() const { return ErrorMsg != ""; }
     105             :     const std::string &getErrorMsg() const { return ErrorMsg; }
     106             : 
     107             :   private:
     108             :     uint64_t Value;
     109             :     std::string ErrorMsg;
     110             :   };
     111             : 
     112           0 :   StringRef getTokenForError(StringRef Expr) const {
     113           0 :     if (Expr.empty())
     114           0 :       return "";
     115             : 
     116           0 :     StringRef Token, Remaining;
     117           0 :     if (isalpha(Expr[0]))
     118           0 :       std::tie(Token, Remaining) = parseSymbol(Expr);
     119           0 :     else if (isdigit(Expr[0]))
     120           0 :       std::tie(Token, Remaining) = parseNumberString(Expr);
     121             :     else {
     122             :       unsigned TokLen = 1;
     123             :       if (Expr.startswith("<<") || Expr.startswith(">>"))
     124             :         TokLen = 2;
     125           0 :       Token = Expr.substr(0, TokLen);
     126             :     }
     127           0 :     return Token;
     128             :   }
     129             : 
     130           0 :   EvalResult unexpectedToken(StringRef TokenStart, StringRef SubExpr,
     131             :                              StringRef ErrText) const {
     132           0 :     std::string ErrorMsg("Encountered unexpected token '");
     133           0 :     ErrorMsg += getTokenForError(TokenStart);
     134             :     if (SubExpr != "") {
     135             :       ErrorMsg += "' while parsing subexpression '";
     136             :       ErrorMsg += SubExpr;
     137             :     }
     138             :     ErrorMsg += "'";
     139             :     if (ErrText != "") {
     140             :       ErrorMsg += " ";
     141             :       ErrorMsg += ErrText;
     142             :     }
     143           0 :     return EvalResult(std::move(ErrorMsg));
     144             :   }
     145             : 
     146           0 :   bool handleError(StringRef Expr, const EvalResult &R) const {
     147             :     assert(R.hasError() && "Not an error result.");
     148           0 :     Checker.ErrStream << "Error evaluating expression '" << Expr
     149           0 :                       << "': " << R.getErrorMsg() << "\n";
     150           0 :     return false;
     151             :   }
     152             : 
     153         431 :   std::pair<BinOpToken, StringRef> parseBinOpToken(StringRef Expr) const {
     154         431 :     if (Expr.empty())
     155             :       return std::make_pair(BinOpToken::Invalid, "");
     156             : 
     157             :     // Handle the two 2-character tokens.
     158             :     if (Expr.startswith("<<"))
     159          21 :       return std::make_pair(BinOpToken::ShiftLeft, Expr.substr(2).ltrim());
     160             :     if (Expr.startswith(">>"))
     161           3 :       return std::make_pair(BinOpToken::ShiftRight, Expr.substr(2).ltrim());
     162             : 
     163             :     // Handle one-character tokens.
     164             :     BinOpToken Op;
     165         846 :     switch (Expr[0]) {
     166         219 :     default:
     167             :       return std::make_pair(BinOpToken::Invalid, Expr);
     168             :     case '+':
     169             :       Op = BinOpToken::Add;
     170             :       break;
     171          89 :     case '-':
     172             :       Op = BinOpToken::Sub;
     173          89 :       break;
     174          15 :     case '&':
     175             :       Op = BinOpToken::BitwiseAnd;
     176          15 :       break;
     177           3 :     case '|':
     178             :       Op = BinOpToken::BitwiseOr;
     179           3 :       break;
     180             :     }
     181             : 
     182         612 :     return std::make_pair(Op, Expr.substr(1).ltrim());
     183             :   }
     184             : 
     185         212 :   EvalResult computeBinOpResult(BinOpToken Op, const EvalResult &LHSResult,
     186             :                                 const EvalResult &RHSResult) const {
     187         212 :     switch (Op) {
     188           0 :     default:
     189           0 :       llvm_unreachable("Tried to evaluate unrecognized operation.");
     190          97 :     case BinOpToken::Add:
     191          97 :       return EvalResult(LHSResult.getValue() + RHSResult.getValue());
     192          89 :     case BinOpToken::Sub:
     193          89 :       return EvalResult(LHSResult.getValue() - RHSResult.getValue());
     194          15 :     case BinOpToken::BitwiseAnd:
     195          15 :       return EvalResult(LHSResult.getValue() & RHSResult.getValue());
     196           3 :     case BinOpToken::BitwiseOr:
     197           3 :       return EvalResult(LHSResult.getValue() | RHSResult.getValue());
     198           7 :     case BinOpToken::ShiftLeft:
     199           7 :       return EvalResult(LHSResult.getValue() << RHSResult.getValue());
     200           1 :     case BinOpToken::ShiftRight:
     201           1 :       return EvalResult(LHSResult.getValue() >> RHSResult.getValue());
     202             :     }
     203             :   }
     204             : 
     205             :   // Parse a symbol and return a (string, string) pair representing the symbol
     206             :   // name and expression remaining to be parsed.
     207         673 :   std::pair<StringRef, StringRef> parseSymbol(StringRef Expr) const {
     208         673 :     size_t FirstNonSymbol = Expr.find_first_not_of("0123456789"
     209             :                                                    "abcdefghijklmnopqrstuvwxyz"
     210             :                                                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     211         673 :                                                    ":_.$");
     212             :     return std::make_pair(Expr.substr(0, FirstNonSymbol),
     213        2019 :                           Expr.substr(FirstNonSymbol).ltrim());
     214             :   }
     215             : 
     216             :   // Evaluate a call to decode_operand. Decode the instruction operand at the
     217             :   // given symbol and get the value of the requested operand.
     218             :   // Returns an error if the instruction cannot be decoded, or the requested
     219             :   // operand is not an immediate.
     220             :   // On success, returns a pair containing the value of the operand, plus
     221             :   // the expression remaining to be evaluated.
     222          96 :   std::pair<EvalResult, StringRef> evalDecodeOperand(StringRef Expr) const {
     223             :     if (!Expr.startswith("("))
     224           0 :       return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");
     225         192 :     StringRef RemainingExpr = Expr.substr(1).ltrim();
     226          96 :     StringRef Symbol;
     227         192 :     std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
     228             : 
     229          96 :     if (!Checker.isSymbolValid(Symbol))
     230           0 :       return std::make_pair(
     231           0 :           EvalResult(("Cannot decode unknown symbol '" + Symbol + "'").str()),
     232           0 :           "");
     233             : 
     234             :     if (!RemainingExpr.startswith(","))
     235           0 :       return std::make_pair(
     236           0 :           unexpectedToken(RemainingExpr, RemainingExpr, "expected ','"), "");
     237         192 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     238             : 
     239             :     EvalResult OpIdxExpr;
     240         192 :     std::tie(OpIdxExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
     241          96 :     if (OpIdxExpr.hasError())
     242           0 :       return std::make_pair(OpIdxExpr, "");
     243             : 
     244             :     if (!RemainingExpr.startswith(")"))
     245           0 :       return std::make_pair(
     246           0 :           unexpectedToken(RemainingExpr, RemainingExpr, "expected ')'"), "");
     247         192 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     248             : 
     249             :     MCInst Inst;
     250             :     uint64_t Size;
     251          96 :     if (!decodeInst(Symbol, Inst, Size))
     252           0 :       return std::make_pair(
     253           0 :           EvalResult(("Couldn't decode instruction at '" + Symbol + "'").str()),
     254           0 :           "");
     255             : 
     256          96 :     unsigned OpIdx = OpIdxExpr.getValue();
     257          96 :     if (OpIdx >= Inst.getNumOperands()) {
     258             :       std::string ErrMsg;
     259           0 :       raw_string_ostream ErrMsgStream(ErrMsg);
     260           0 :       ErrMsgStream << "Invalid operand index '" << format("%i", OpIdx)
     261           0 :                    << "' for instruction '" << Symbol
     262           0 :                    << "'. Instruction has only "
     263           0 :                    << format("%i", Inst.getNumOperands())
     264           0 :                    << " operands.\nInstruction is:\n  ";
     265           0 :       Inst.dump_pretty(ErrMsgStream, Checker.InstPrinter);
     266           0 :       return std::make_pair(EvalResult(ErrMsgStream.str()), "");
     267             :     }
     268             : 
     269             :     const MCOperand &Op = Inst.getOperand(OpIdx);
     270          96 :     if (!Op.isImm()) {
     271             :       std::string ErrMsg;
     272           0 :       raw_string_ostream ErrMsgStream(ErrMsg);
     273           0 :       ErrMsgStream << "Operand '" << format("%i", OpIdx) << "' of instruction '"
     274           0 :                    << Symbol << "' is not an immediate.\nInstruction is:\n  ";
     275           0 :       Inst.dump_pretty(ErrMsgStream, Checker.InstPrinter);
     276             : 
     277           0 :       return std::make_pair(EvalResult(ErrMsgStream.str()), "");
     278             :     }
     279             : 
     280         192 :     return std::make_pair(EvalResult(Op.getImm()), RemainingExpr);
     281             :   }
     282             : 
     283             :   // Evaluate a call to next_pc.
     284             :   // Decode the instruction at the given symbol and return the following program
     285             :   // counter.
     286             :   // Returns an error if the instruction cannot be decoded.
     287             :   // On success, returns a pair containing the next PC, plus of the
     288             :   // expression remaining to be evaluated.
     289          14 :   std::pair<EvalResult, StringRef> evalNextPC(StringRef Expr,
     290             :                                               ParseContext PCtx) const {
     291             :     if (!Expr.startswith("("))
     292           0 :       return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");
     293          28 :     StringRef RemainingExpr = Expr.substr(1).ltrim();
     294          14 :     StringRef Symbol;
     295          28 :     std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
     296             : 
     297          14 :     if (!Checker.isSymbolValid(Symbol))
     298           0 :       return std::make_pair(
     299           0 :           EvalResult(("Cannot decode unknown symbol '" + Symbol + "'").str()),
     300           0 :           "");
     301             : 
     302             :     if (!RemainingExpr.startswith(")"))
     303           0 :       return std::make_pair(
     304           0 :           unexpectedToken(RemainingExpr, RemainingExpr, "expected ')'"), "");
     305          28 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     306             : 
     307             :     MCInst Inst;
     308             :     uint64_t InstSize;
     309          14 :     if (!decodeInst(Symbol, Inst, InstSize))
     310           0 :       return std::make_pair(
     311           0 :           EvalResult(("Couldn't decode instruction at '" + Symbol + "'").str()),
     312           0 :           "");
     313             : 
     314          14 :     uint64_t SymbolAddr = PCtx.IsInsideLoad
     315          28 :                               ? Checker.getSymbolLocalAddr(Symbol)
     316          14 :                               : Checker.getSymbolRemoteAddr(Symbol);
     317          14 :     uint64_t NextPC = SymbolAddr + InstSize;
     318             : 
     319          14 :     return std::make_pair(EvalResult(NextPC), RemainingExpr);
     320             :   }
     321             : 
     322             :   // Evaluate a call to stub_addr.
     323             :   // Look up and return the address of the stub for the given
     324             :   // (<file name>, <section name>, <symbol name>) tuple.
     325             :   // On success, returns a pair containing the stub address, plus the expression
     326             :   // remaining to be evaluated.
     327          28 :   std::pair<EvalResult, StringRef> evalStubAddr(StringRef Expr,
     328             :                                                 ParseContext PCtx) const {
     329             :     if (!Expr.startswith("("))
     330           0 :       return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");
     331          56 :     StringRef RemainingExpr = Expr.substr(1).ltrim();
     332             : 
     333             :     // Handle file-name specially, as it may contain characters that aren't
     334             :     // legal for symbols.
     335             :     StringRef FileName;
     336             :     size_t ComaIdx = RemainingExpr.find(',');
     337          56 :     FileName = RemainingExpr.substr(0, ComaIdx).rtrim();
     338          56 :     RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim();
     339             : 
     340             :     if (!RemainingExpr.startswith(","))
     341           0 :       return std::make_pair(
     342           0 :           unexpectedToken(RemainingExpr, Expr, "expected ','"), "");
     343          56 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     344             : 
     345             :     StringRef SectionName;
     346          56 :     std::tie(SectionName, RemainingExpr) = parseSymbol(RemainingExpr);
     347             : 
     348             :     if (!RemainingExpr.startswith(","))
     349           0 :       return std::make_pair(
     350           0 :           unexpectedToken(RemainingExpr, Expr, "expected ','"), "");
     351          56 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     352             : 
     353             :     StringRef Symbol;
     354          56 :     std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
     355             : 
     356             :     if (!RemainingExpr.startswith(")"))
     357           0 :       return std::make_pair(
     358           0 :           unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");
     359          56 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     360             : 
     361             :     uint64_t StubAddr;
     362          28 :     std::string ErrorMsg = "";
     363          84 :     std::tie(StubAddr, ErrorMsg) = Checker.getStubAddrFor(
     364          28 :         FileName, SectionName, Symbol, PCtx.IsInsideLoad);
     365             : 
     366          28 :     if (ErrorMsg != "")
     367           0 :       return std::make_pair(EvalResult(ErrorMsg), "");
     368             : 
     369          28 :     return std::make_pair(EvalResult(StubAddr), RemainingExpr);
     370             :   }
     371             : 
     372          42 :   std::pair<EvalResult, StringRef> evalSectionAddr(StringRef Expr,
     373             :                                                    ParseContext PCtx) const {
     374             :     if (!Expr.startswith("("))
     375           0 :       return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");
     376          84 :     StringRef RemainingExpr = Expr.substr(1).ltrim();
     377             : 
     378             :     // Handle file-name specially, as it may contain characters that aren't
     379             :     // legal for symbols.
     380             :     StringRef FileName;
     381             :     size_t ComaIdx = RemainingExpr.find(',');
     382          84 :     FileName = RemainingExpr.substr(0, ComaIdx).rtrim();
     383          84 :     RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim();
     384             : 
     385             :     if (!RemainingExpr.startswith(","))
     386           0 :       return std::make_pair(
     387           0 :           unexpectedToken(RemainingExpr, Expr, "expected ','"), "");
     388          84 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     389             : 
     390             :     StringRef SectionName;
     391          84 :     std::tie(SectionName, RemainingExpr) = parseSymbol(RemainingExpr);
     392             : 
     393             :     if (!RemainingExpr.startswith(")"))
     394           0 :       return std::make_pair(
     395           0 :           unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");
     396          84 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     397             : 
     398             :     uint64_t StubAddr;
     399          42 :     std::string ErrorMsg = "";
     400         126 :     std::tie(StubAddr, ErrorMsg) = Checker.getSectionAddr(
     401          42 :         FileName, SectionName, PCtx.IsInsideLoad);
     402             : 
     403          42 :     if (ErrorMsg != "")
     404           0 :       return std::make_pair(EvalResult(ErrorMsg), "");
     405             : 
     406          42 :     return std::make_pair(EvalResult(StubAddr), RemainingExpr);
     407             :   }
     408             : 
     409             :   // Evaluate an identiefer expr, which may be a symbol, or a call to
     410             :   // one of the builtin functions: get_insn_opcode or get_insn_length.
     411             :   // Return the result, plus the expression remaining to be parsed.
     412         465 :   std::pair<EvalResult, StringRef> evalIdentifierExpr(StringRef Expr,
     413             :                                                       ParseContext PCtx) const {
     414             :     StringRef Symbol;
     415             :     StringRef RemainingExpr;
     416         930 :     std::tie(Symbol, RemainingExpr) = parseSymbol(Expr);
     417             : 
     418             :     // Check for builtin function calls.
     419             :     if (Symbol == "decode_operand")
     420          96 :       return evalDecodeOperand(RemainingExpr);
     421             :     else if (Symbol == "next_pc")
     422          14 :       return evalNextPC(RemainingExpr, PCtx);
     423             :     else if (Symbol == "stub_addr")
     424          28 :       return evalStubAddr(RemainingExpr, PCtx);
     425             :     else if (Symbol == "section_addr")
     426          42 :       return evalSectionAddr(RemainingExpr, PCtx);
     427             : 
     428         285 :     if (!Checker.isSymbolValid(Symbol)) {
     429           0 :       std::string ErrMsg("No known address for symbol '");
     430             :       ErrMsg += Symbol;
     431             :       ErrMsg += "'";
     432             :       if (Symbol.startswith("L"))
     433             :         ErrMsg += " (this appears to be an assembler local label - "
     434             :                   " perhaps drop the 'L'?)";
     435             : 
     436           0 :       return std::make_pair(EvalResult(ErrMsg), "");
     437             :     }
     438             : 
     439             :     // The value for the symbol depends on the context we're evaluating in:
     440             :     // Inside a load this is the address in the linker's memory, outside a
     441             :     // load it's the address in the target processes memory.
     442         486 :     uint64_t Value = PCtx.IsInsideLoad ? Checker.getSymbolLocalAddr(Symbol)
     443         201 :                                        : Checker.getSymbolRemoteAddr(Symbol);
     444             : 
     445             :     // Looks like a plain symbol reference.
     446         285 :     return std::make_pair(EvalResult(Value), RemainingExpr);
     447             :   }
     448             : 
     449             :   // Parse a number (hexadecimal or decimal) and return a (string, string)
     450             :   // pair representing the number and the expression remaining to be parsed.
     451         748 :   std::pair<StringRef, StringRef> parseNumberString(StringRef Expr) const {
     452             :     size_t FirstNonDigit = StringRef::npos;
     453             :     if (Expr.startswith("0x")) {
     454          80 :       FirstNonDigit = Expr.find_first_not_of("0123456789abcdefABCDEF", 2);
     455          80 :       if (FirstNonDigit == StringRef::npos)
     456             :         FirstNonDigit = Expr.size();
     457             :     } else {
     458         668 :       FirstNonDigit = Expr.find_first_not_of("0123456789");
     459         668 :       if (FirstNonDigit == StringRef::npos)
     460             :         FirstNonDigit = Expr.size();
     461             :     }
     462             :     return std::make_pair(Expr.substr(0, FirstNonDigit),
     463         748 :                           Expr.substr(FirstNonDigit));
     464             :   }
     465             : 
     466             :   // Evaluate a constant numeric expression (hexadecimal or decimal) and
     467             :   // return a pair containing the result, and the expression remaining to be
     468             :   // evaluated.
     469         748 :   std::pair<EvalResult, StringRef> evalNumberExpr(StringRef Expr) const {
     470             :     StringRef ValueStr;
     471             :     StringRef RemainingExpr;
     472        1496 :     std::tie(ValueStr, RemainingExpr) = parseNumberString(Expr);
     473             : 
     474        1496 :     if (ValueStr.empty() || !isdigit(ValueStr[0]))
     475           0 :       return std::make_pair(
     476           0 :           unexpectedToken(RemainingExpr, RemainingExpr, "expected number"), "");
     477             :     uint64_t Value;
     478             :     ValueStr.getAsInteger(0, Value);
     479         748 :     return std::make_pair(EvalResult(Value), RemainingExpr);
     480             :   }
     481             : 
     482             :   // Evaluate an expression of the form "(<expr>)" and return a pair
     483             :   // containing the result of evaluating <expr>, plus the expression
     484             :   // remaining to be parsed.
     485         192 :   std::pair<EvalResult, StringRef> evalParensExpr(StringRef Expr,
     486             :                                                   ParseContext PCtx) const {
     487             :     assert(Expr.startswith("(") && "Not a parenthesized expression");
     488             :     EvalResult SubExprResult;
     489             :     StringRef RemainingExpr;
     490             :     std::tie(SubExprResult, RemainingExpr) =
     491         768 :         evalComplexExpr(evalSimpleExpr(Expr.substr(1).ltrim(), PCtx), PCtx);
     492         192 :     if (SubExprResult.hasError())
     493           0 :       return std::make_pair(SubExprResult, "");
     494             :     if (!RemainingExpr.startswith(")"))
     495           0 :       return std::make_pair(
     496           0 :           unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");
     497         384 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     498             :     return std::make_pair(SubExprResult, RemainingExpr);
     499             :   }
     500             : 
     501             :   // Evaluate an expression in one of the following forms:
     502             :   //   *{<number>}<expr>
     503             :   // Return a pair containing the result, plus the expression remaining to be
     504             :   // parsed.
     505         117 :   std::pair<EvalResult, StringRef> evalLoadExpr(StringRef Expr) const {
     506             :     assert(Expr.startswith("*") && "Not a load expression");
     507         234 :     StringRef RemainingExpr = Expr.substr(1).ltrim();
     508             : 
     509             :     // Parse read size.
     510             :     if (!RemainingExpr.startswith("{"))
     511           0 :       return std::make_pair(EvalResult("Expected '{' following '*'."), "");
     512         234 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     513             :     EvalResult ReadSizeExpr;
     514         234 :     std::tie(ReadSizeExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
     515         117 :     if (ReadSizeExpr.hasError())
     516             :       return std::make_pair(ReadSizeExpr, RemainingExpr);
     517         117 :     uint64_t ReadSize = ReadSizeExpr.getValue();
     518         117 :     if (ReadSize < 1 || ReadSize > 8)
     519           0 :       return std::make_pair(EvalResult("Invalid size for dereference."), "");
     520             :     if (!RemainingExpr.startswith("}"))
     521           0 :       return std::make_pair(EvalResult("Missing '}' for dereference."), "");
     522         234 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     523             : 
     524             :     // Evaluate the expression representing the load address.
     525             :     ParseContext LoadCtx(true);
     526             :     EvalResult LoadAddrExprResult;
     527             :     std::tie(LoadAddrExprResult, RemainingExpr) =
     528         351 :         evalComplexExpr(evalSimpleExpr(RemainingExpr, LoadCtx), LoadCtx);
     529             : 
     530         117 :     if (LoadAddrExprResult.hasError())
     531           0 :       return std::make_pair(LoadAddrExprResult, "");
     532             : 
     533         117 :     uint64_t LoadAddr = LoadAddrExprResult.getValue();
     534             : 
     535             :     return std::make_pair(
     536         234 :         EvalResult(Checker.readMemoryAtAddr(LoadAddr, ReadSize)),
     537             :         RemainingExpr);
     538             :   }
     539             : 
     540             :   // Evaluate a "simple" expression. This is any expression that _isn't_ an
     541             :   // un-parenthesized binary expression.
     542             :   //
     543             :   // "Simple" expressions can be optionally bit-sliced. See evalSlicedExpr.
     544             :   //
     545             :   // Returns a pair containing the result of the evaluation, plus the
     546             :   // expression remaining to be parsed.
     547         945 :   std::pair<EvalResult, StringRef> evalSimpleExpr(StringRef Expr,
     548             :                                                   ParseContext PCtx) const {
     549             :     EvalResult SubExprResult;
     550         945 :     StringRef RemainingExpr;
     551             : 
     552         945 :     if (Expr.empty())
     553           0 :       return std::make_pair(EvalResult("Unexpected end of expression"), "");
     554             : 
     555         945 :     if (Expr[0] == '(')
     556         384 :       std::tie(SubExprResult, RemainingExpr) = evalParensExpr(Expr, PCtx);
     557         753 :     else if (Expr[0] == '*')
     558         234 :       std::tie(SubExprResult, RemainingExpr) = evalLoadExpr(Expr);
     559         636 :     else if (isalpha(Expr[0]) || Expr[0] == '_')
     560         930 :       std::tie(SubExprResult, RemainingExpr) = evalIdentifierExpr(Expr, PCtx);
     561         171 :     else if (isdigit(Expr[0]))
     562         342 :       std::tie(SubExprResult, RemainingExpr) = evalNumberExpr(Expr);
     563             :     else
     564           0 :       return std::make_pair(
     565           0 :           unexpectedToken(Expr, Expr,
     566           0 :                           "expected '(', '*', identifier, or number"), "");
     567             : 
     568         945 :     if (SubExprResult.hasError())
     569             :       return std::make_pair(SubExprResult, RemainingExpr);
     570             : 
     571             :     // Evaluate bit-slice if present.
     572             :     if (RemainingExpr.startswith("["))
     573             :       std::tie(SubExprResult, RemainingExpr) =
     574         546 :           evalSliceExpr(std::make_pair(SubExprResult, RemainingExpr));
     575             : 
     576             :     return std::make_pair(SubExprResult, RemainingExpr);
     577             :   }
     578             : 
     579             :   // Evaluate a bit-slice of an expression.
     580             :   // A bit-slice has the form "<expr>[high:low]". The result of evaluating a
     581             :   // slice is the bits between high and low (inclusive) in the original
     582             :   // expression, right shifted so that the "low" bit is in position 0 in the
     583             :   // result.
     584             :   // Returns a pair containing the result of the slice operation, plus the
     585             :   // expression remaining to be parsed.
     586             :   std::pair<EvalResult, StringRef>
     587         182 :   evalSliceExpr(const std::pair<EvalResult, StringRef> &Ctx) const {
     588             :     EvalResult SubExprResult;
     589             :     StringRef RemainingExpr;
     590             :     std::tie(SubExprResult, RemainingExpr) = Ctx;
     591             : 
     592             :     assert(RemainingExpr.startswith("[") && "Not a slice expr.");
     593         364 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     594             : 
     595             :     EvalResult HighBitExpr;
     596         364 :     std::tie(HighBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
     597             : 
     598         182 :     if (HighBitExpr.hasError())
     599             :       return std::make_pair(HighBitExpr, RemainingExpr);
     600             : 
     601             :     if (!RemainingExpr.startswith(":"))
     602           0 :       return std::make_pair(
     603           0 :           unexpectedToken(RemainingExpr, RemainingExpr, "expected ':'"), "");
     604         364 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     605             : 
     606             :     EvalResult LowBitExpr;
     607         364 :     std::tie(LowBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
     608             : 
     609         182 :     if (LowBitExpr.hasError())
     610             :       return std::make_pair(LowBitExpr, RemainingExpr);
     611             : 
     612             :     if (!RemainingExpr.startswith("]"))
     613           0 :       return std::make_pair(
     614           0 :           unexpectedToken(RemainingExpr, RemainingExpr, "expected ']'"), "");
     615         364 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     616             : 
     617         182 :     unsigned HighBit = HighBitExpr.getValue();
     618         182 :     unsigned LowBit = LowBitExpr.getValue();
     619         182 :     uint64_t Mask = ((uint64_t)1 << (HighBit - LowBit + 1)) - 1;
     620         182 :     uint64_t SlicedValue = (SubExprResult.getValue() >> LowBit) & Mask;
     621         182 :     return std::make_pair(EvalResult(SlicedValue), RemainingExpr);
     622             :   }
     623             : 
     624             :   // Evaluate a "complex" expression.
     625             :   // Takes an already evaluated subexpression and checks for the presence of a
     626             :   // binary operator, computing the result of the binary operation if one is
     627             :   // found. Used to make arithmetic expressions left-associative.
     628             :   // Returns a pair containing the ultimate result of evaluating the
     629             :   // expression, plus the expression remaining to be evaluated.
     630             :   std::pair<EvalResult, StringRef>
     631         945 :   evalComplexExpr(const std::pair<EvalResult, StringRef> &LHSAndRemaining,
     632             :                   ParseContext PCtx) const {
     633             :     EvalResult LHSResult;
     634             :     StringRef RemainingExpr;
     635             :     std::tie(LHSResult, RemainingExpr) = LHSAndRemaining;
     636             : 
     637             :     // If there was an error, or there's nothing left to evaluate, return the
     638             :     // result.
     639         945 :     if (LHSResult.hasError() || RemainingExpr == "")
     640             :       return std::make_pair(LHSResult, RemainingExpr);
     641             : 
     642             :     // Otherwise check if this is a binary expressioan.
     643             :     BinOpToken BinOp;
     644         862 :     std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr);
     645             : 
     646             :     // If this isn't a recognized expression just return.
     647         431 :     if (BinOp == BinOpToken::Invalid)
     648             :       return std::make_pair(LHSResult, RemainingExpr);
     649             : 
     650             :     // This is a recognized bin-op. Evaluate the RHS, then evaluate the binop.
     651             :     EvalResult RHSResult;
     652         424 :     std::tie(RHSResult, RemainingExpr) = evalSimpleExpr(RemainingExpr, PCtx);
     653             : 
     654             :     // If there was an error evaluating the RHS, return it.
     655         212 :     if (RHSResult.hasError())
     656             :       return std::make_pair(RHSResult, RemainingExpr);
     657             : 
     658             :     // This is a binary expression - evaluate and try to continue as a
     659             :     // complex expr.
     660         212 :     EvalResult ThisResult(computeBinOpResult(BinOp, LHSResult, RHSResult));
     661             : 
     662         424 :     return evalComplexExpr(std::make_pair(ThisResult, RemainingExpr), PCtx);
     663             :   }
     664             : 
     665         110 :   bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size) const {
     666         110 :     MCDisassembler *Dis = Checker.Disassembler;
     667         110 :     StringRef SectionMem = Checker.getSubsectionStartingAt(Symbol);
     668             :     ArrayRef<uint8_t> SectionBytes(
     669             :         reinterpret_cast<const uint8_t *>(SectionMem.data()),
     670             :         SectionMem.size());
     671             : 
     672             :     MCDisassembler::DecodeStatus S =
     673         110 :         Dis->getInstruction(Inst, Size, SectionBytes, 0, nulls(), nulls());
     674             : 
     675         110 :     return (S == MCDisassembler::Success);
     676             :   }
     677             : };
     678             : }
     679             : 
     680          40 : RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl(RuntimeDyld &RTDyld,
     681             :                                                MCDisassembler *Disassembler,
     682             :                                                MCInstPrinter *InstPrinter,
     683          40 :                                                raw_ostream &ErrStream)
     684             :     : RTDyld(RTDyld), Disassembler(Disassembler), InstPrinter(InstPrinter),
     685          40 :       ErrStream(ErrStream) {
     686          40 :   RTDyld.Checker = this;
     687          40 : }
     688             : 
     689         212 : bool RuntimeDyldCheckerImpl::check(StringRef CheckExpr) const {
     690         212 :   CheckExpr = CheckExpr.trim();
     691             :   LLVM_DEBUG(dbgs() << "RuntimeDyldChecker: Checking '" << CheckExpr
     692             :                     << "'...\n");
     693             :   RuntimeDyldCheckerExprEval P(*this, ErrStream);
     694         212 :   bool Result = P.evaluate(CheckExpr);
     695             :   (void)Result;
     696             :   LLVM_DEBUG(dbgs() << "RuntimeDyldChecker: '" << CheckExpr << "' "
     697             :                     << (Result ? "passed" : "FAILED") << ".\n");
     698         212 :   return Result;
     699             : }
     700             : 
     701          31 : bool RuntimeDyldCheckerImpl::checkAllRulesInBuffer(StringRef RulePrefix,
     702             :                                                    MemoryBuffer *MemBuf) const {
     703             :   bool DidAllTestsPass = true;
     704             :   unsigned NumRules = 0;
     705             : 
     706          31 :   const char *LineStart = MemBuf->getBufferStart();
     707             : 
     708             :   // Eat whitespace.
     709          31 :   while (LineStart != MemBuf->getBufferEnd() && std::isspace(*LineStart))
     710           0 :     ++LineStart;
     711             : 
     712        3823 :   while (LineStart != MemBuf->getBufferEnd() && *LineStart != '\0') {
     713             :     const char *LineEnd = LineStart;
     714      122496 :     while (LineEnd != MemBuf->getBufferEnd() && *LineEnd != '\r' &&
     715             :            *LineEnd != '\n')
     716       60300 :       ++LineEnd;
     717             : 
     718        1896 :     StringRef Line(LineStart, LineEnd - LineStart);
     719             :     if (Line.startswith(RulePrefix)) {
     720         212 :       DidAllTestsPass &= check(Line.substr(RulePrefix.size()));
     721         212 :       ++NumRules;
     722             :     }
     723             : 
     724             :     // Eat whitespace.
     725             :     LineStart = LineEnd;
     726       11286 :     while (LineStart != MemBuf->getBufferEnd() && std::isspace(*LineStart))
     727        4695 :       ++LineStart;
     728             :   }
     729          31 :   return DidAllTestsPass && (NumRules != 0);
     730             : }
     731             : 
     732         395 : bool RuntimeDyldCheckerImpl::isSymbolValid(StringRef Symbol) const {
     733         790 :   if (getRTDyld().getSymbol(Symbol))
     734             :     return true;
     735           9 :   JITSymbolResolver::LookupSet Symbols({Symbol});
     736          27 :   auto Result = getRTDyld().Resolver.lookup(Symbols);
     737           9 :   if (!Result) {
     738           0 :     logAllUnhandledErrors(Result.takeError(), errs(), "RTDyldChecker: ");
     739           0 :     return false;
     740             :   }
     741             :   assert(Result->count(Symbol) && "Missing symbol result");
     742             :   return true;
     743             : }
     744             : 
     745          84 : uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const {
     746             :   return static_cast<uint64_t>(
     747         168 :       reinterpret_cast<uintptr_t>(getRTDyld().getSymbolLocalAddress(Symbol)));
     748             : }
     749             : 
     750         215 : uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const {
     751         430 :   if (auto InternalSymbol = getRTDyld().getSymbol(Symbol))
     752         206 :     return InternalSymbol.getAddress();
     753             : 
     754           9 :   JITSymbolResolver::LookupSet Symbols({Symbol});
     755          27 :   auto Result = getRTDyld().Resolver.lookup(Symbols);
     756           9 :   if (!Result) {
     757           0 :     logAllUnhandledErrors(Result.takeError(), errs(), "RTDyldChecker: ");
     758           0 :     return 0;
     759             :   }
     760             :   auto I = Result->find(Symbol);
     761             :   assert(I != Result->end() && "Missing symbol result");
     762           9 :   return I->second.getAddress();
     763             : }
     764             : 
     765         117 : uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr,
     766             :                                                   unsigned Size) const {
     767             :   uintptr_t PtrSizedAddr = static_cast<uintptr_t>(SrcAddr);
     768             :   assert(PtrSizedAddr == SrcAddr && "Linker memory pointer out-of-range.");
     769         117 :   uint8_t *Src = reinterpret_cast<uint8_t*>(PtrSizedAddr);
     770         234 :   return getRTDyld().readBytesUnaligned(Src, Size);
     771             : }
     772             : 
     773             : 
     774             : std::pair<const RuntimeDyldCheckerImpl::SectionAddressInfo*, std::string>
     775         104 : RuntimeDyldCheckerImpl::findSectionAddrInfo(StringRef FileName,
     776             :                                             StringRef SectionName) const {
     777             : 
     778         104 :   auto SectionMapItr = Stubs.find(FileName);
     779         104 :   if (SectionMapItr == Stubs.end()) {
     780           0 :     std::string ErrorMsg = "File '";
     781             :     ErrorMsg += FileName;
     782             :     ErrorMsg += "' not found. ";
     783           0 :     if (Stubs.empty())
     784             :       ErrorMsg += "No stubs registered.";
     785             :     else {
     786             :       ErrorMsg += "Available files are:";
     787           0 :       for (const auto& StubEntry : Stubs) {
     788             :         ErrorMsg += " '";
     789             :         ErrorMsg += StubEntry.first;
     790             :         ErrorMsg += "'";
     791             :       }
     792             :     }
     793             :     ErrorMsg += "\n";
     794           0 :     return std::make_pair(nullptr, ErrorMsg);
     795             :   }
     796             : 
     797         104 :   auto SectionInfoItr = SectionMapItr->second.find(SectionName);
     798         104 :   if (SectionInfoItr == SectionMapItr->second.end())
     799           0 :     return std::make_pair(nullptr,
     800           0 :                           ("Section '" + SectionName + "' not found in file '" +
     801           0 :                            FileName + "'\n").str());
     802             : 
     803         208 :   return std::make_pair(&SectionInfoItr->second, std::string(""));
     804             : }
     805             : 
     806          76 : std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getSectionAddr(
     807             :     StringRef FileName, StringRef SectionName, bool IsInsideLoad) const {
     808             : 
     809             :   const SectionAddressInfo *SectionInfo = nullptr;
     810             :   {
     811             :     std::string ErrorMsg;
     812             :     std::tie(SectionInfo, ErrorMsg) =
     813         152 :       findSectionAddrInfo(FileName, SectionName);
     814          76 :     if (ErrorMsg != "")
     815           0 :       return std::make_pair(0, ErrorMsg);
     816             :   }
     817             : 
     818          76 :   unsigned SectionID = SectionInfo->SectionID;
     819             :   uint64_t Addr;
     820          76 :   if (IsInsideLoad)
     821          52 :     Addr = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(
     822         104 :         getRTDyld().Sections[SectionID].getAddress()));
     823             :   else
     824          48 :     Addr = getRTDyld().Sections[SectionID].getLoadAddress();
     825             : 
     826         152 :   return std::make_pair(Addr, std::string(""));
     827             : }
     828             : 
     829          28 : std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubAddrFor(
     830             :     StringRef FileName, StringRef SectionName, StringRef SymbolName,
     831             :     bool IsInsideLoad) const {
     832             : 
     833             :   const SectionAddressInfo *SectionInfo = nullptr;
     834             :   {
     835             :     std::string ErrorMsg;
     836             :     std::tie(SectionInfo, ErrorMsg) =
     837          56 :       findSectionAddrInfo(FileName, SectionName);
     838          28 :     if (ErrorMsg != "")
     839           0 :       return std::make_pair(0, ErrorMsg);
     840             :   }
     841             : 
     842          28 :   unsigned SectionID = SectionInfo->SectionID;
     843             :   const StubOffsetsMap &SymbolStubs = SectionInfo->StubOffsets;
     844          28 :   auto StubOffsetItr = SymbolStubs.find(SymbolName);
     845          28 :   if (StubOffsetItr == SymbolStubs.end())
     846           0 :     return std::make_pair(0,
     847           0 :                           ("Stub for symbol '" + SymbolName + "' not found. "
     848           0 :                            "If '" + SymbolName + "' is an internal symbol this "
     849             :                            "may indicate that the stub target offset is being "
     850           0 :                            "computed incorrectly.\n").str());
     851             : 
     852          28 :   uint64_t StubOffset = StubOffsetItr->second;
     853             : 
     854             :   uint64_t Addr;
     855          28 :   if (IsInsideLoad) {
     856             :     uintptr_t SectionBase = reinterpret_cast<uintptr_t>(
     857          30 :         getRTDyld().Sections[SectionID].getAddress());
     858          15 :     Addr = static_cast<uint64_t>(SectionBase) + StubOffset;
     859             :   } else {
     860          26 :     uint64_t SectionBase = getRTDyld().Sections[SectionID].getLoadAddress();
     861          13 :     Addr = SectionBase + StubOffset;
     862             :   }
     863             : 
     864          56 :   return std::make_pair(Addr, std::string(""));
     865             : }
     866             : 
     867             : StringRef
     868         110 : RuntimeDyldCheckerImpl::getSubsectionStartingAt(StringRef Name) const {
     869             :   RTDyldSymbolTable::const_iterator pos =
     870         330 :       getRTDyld().GlobalSymbolTable.find(Name);
     871         330 :   if (pos == getRTDyld().GlobalSymbolTable.end())
     872           0 :     return StringRef();
     873             :   const auto &SymInfo = pos->second;
     874         110 :   uint8_t *SectionAddr = getRTDyld().getSectionAddress(SymInfo.getSectionID());
     875         110 :   return StringRef(reinterpret_cast<const char *>(SectionAddr) +
     876             :                        SymInfo.getOffset(),
     877         110 :                    getRTDyld().Sections[SymInfo.getSectionID()].getSize() -
     878         220 :                        SymInfo.getOffset());
     879             : }
     880             : 
     881             : Optional<uint64_t>
     882         165 : RuntimeDyldCheckerImpl::getSectionLoadAddress(void *LocalAddress) const {
     883        1056 :   for (auto &S : getRTDyld().Sections) {
     884         528 :     if (S.getAddress() == LocalAddress)
     885         165 :       return S.getLoadAddress();
     886             :   }
     887             :   return Optional<uint64_t>();
     888             : }
     889             : 
     890         165 : void RuntimeDyldCheckerImpl::registerSection(
     891             :     StringRef FilePath, unsigned SectionID) {
     892         165 :   StringRef FileName = sys::path::filename(FilePath);
     893         165 :   const SectionEntry &Section = getRTDyld().Sections[SectionID];
     894             :   StringRef SectionName = Section.getName();
     895             : 
     896         495 :   Stubs[FileName][SectionName].SectionID = SectionID;
     897         165 : }
     898             : 
     899         114 : void RuntimeDyldCheckerImpl::registerStubMap(
     900             :     StringRef FilePath, unsigned SectionID,
     901             :     const RuntimeDyldImpl::StubMap &RTDyldStubs) {
     902         114 :   StringRef FileName = sys::path::filename(FilePath);
     903         114 :   const SectionEntry &Section = getRTDyld().Sections[SectionID];
     904             :   StringRef SectionName = Section.getName();
     905             : 
     906         342 :   Stubs[FileName][SectionName].SectionID = SectionID;
     907             : 
     908         131 :   for (auto &StubMapEntry : RTDyldStubs) {
     909          17 :     std::string SymbolName = "";
     910             : 
     911          17 :     if (StubMapEntry.first.SymbolName)
     912             :       SymbolName = StubMapEntry.first.SymbolName;
     913             :     else {
     914             :       // If this is a (Section, Offset) pair, do a reverse lookup in the
     915             :       // global symbol table to find the name.
     916          73 :       for (auto &GSTEntry : getRTDyld().GlobalSymbolTable) {
     917             :         const auto &SymInfo = GSTEntry.second;
     918          82 :         if (SymInfo.getSectionID() == StubMapEntry.first.SectionID &&
     919          23 :             SymInfo.getOffset() ==
     920          23 :               static_cast<uint64_t>(StubMapEntry.first.Offset)) {
     921          14 :           SymbolName = GSTEntry.first();
     922           7 :           break;
     923             :         }
     924             :       }
     925             :     }
     926             : 
     927          17 :     if (SymbolName != "")
     928          68 :       Stubs[FileName][SectionName].StubOffsets[SymbolName] =
     929          17 :         StubMapEntry.second;
     930             :   }
     931         114 : }
     932             : 
     933          40 : RuntimeDyldChecker::RuntimeDyldChecker(RuntimeDyld &RTDyld,
     934             :                                        MCDisassembler *Disassembler,
     935             :                                        MCInstPrinter *InstPrinter,
     936          40 :                                        raw_ostream &ErrStream)
     937             :     : Impl(make_unique<RuntimeDyldCheckerImpl>(RTDyld, Disassembler,
     938          40 :                                                InstPrinter, ErrStream)) {}
     939             : 
     940          80 : RuntimeDyldChecker::~RuntimeDyldChecker() {}
     941             : 
     942         146 : RuntimeDyld& RuntimeDyldChecker::getRTDyld() {
     943         146 :   return Impl->RTDyld;
     944             : }
     945             : 
     946           0 : const RuntimeDyld& RuntimeDyldChecker::getRTDyld() const {
     947           0 :   return Impl->RTDyld;
     948             : }
     949             : 
     950           0 : bool RuntimeDyldChecker::check(StringRef CheckExpr) const {
     951           0 :   return Impl->check(CheckExpr);
     952             : }
     953             : 
     954          31 : bool RuntimeDyldChecker::checkAllRulesInBuffer(StringRef RulePrefix,
     955             :                                                MemoryBuffer *MemBuf) const {
     956          31 :   return Impl->checkAllRulesInBuffer(RulePrefix, MemBuf);
     957             : }
     958             : 
     959             : std::pair<uint64_t, std::string>
     960          34 : RuntimeDyldChecker::getSectionAddr(StringRef FileName, StringRef SectionName,
     961             :                                    bool LocalAddress) {
     962          34 :   return Impl->getSectionAddr(FileName, SectionName, LocalAddress);
     963             : }
     964             : 
     965             : Optional<uint64_t>
     966         165 : RuntimeDyldChecker::getSectionLoadAddress(void *LocalAddress) const {
     967         165 :   return Impl->getSectionLoadAddress(LocalAddress);
     968             : }

Generated by: LCOV version 1.13