LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/RuntimeDyld - RuntimeDyldChecker.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 280 403 69.5 %
Date: 2018-02-20 03:34:22 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         198 :       : Checker(Checker) {}
      34             : 
      35         198 :   bool evaluate(StringRef Expr) const {
      36             :     // Expect equality expression of the form 'LHS = RHS'.
      37         198 :     Expr = Expr.trim();
      38             :     size_t EQIdx = Expr.find('=');
      39             : 
      40             :     ParseContext OutsideLoad(false);
      41             : 
      42             :     // Evaluate LHS.
      43         396 :     StringRef LHSExpr = Expr.substr(0, EQIdx).rtrim();
      44             :     StringRef RemainingExpr;
      45             :     EvalResult LHSResult;
      46             :     std::tie(LHSResult, RemainingExpr) =
      47         594 :         evalComplexExpr(evalSimpleExpr(LHSExpr, OutsideLoad), OutsideLoad);
      48         198 :     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         594 :     StringRef RHSExpr = Expr.substr(EQIdx + 1).ltrim();
      55             :     EvalResult RHSResult;
      56             :     std::tie(RHSResult, RemainingExpr) =
      57         594 :         evalComplexExpr(evalSimpleExpr(RHSExpr, OutsideLoad), OutsideLoad);
      58         198 :     if (RHSResult.hasError())
      59           0 :       return handleError(Expr, RHSResult);
      60             :     if (RemainingExpr != "")
      61           0 :       return handleError(Expr, unexpectedToken(RemainingExpr, RHSExpr, ""));
      62             : 
      63         198 :     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         302 :     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        8118 :   class EvalResult {
      98             :   public:
      99        3358 :     EvalResult() : Value(0), ErrorMsg("") {}
     100        1625 :     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         398 :   std::pair<BinOpToken, StringRef> parseBinOpToken(StringRef Expr) const {
     154         398 :     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           0 :       return std::make_pair(BinOpToken::ShiftRight, Expr.substr(2).ltrim());
     162             : 
     163             :     // Handle one-character tokens.
     164             :     BinOpToken Op;
     165         782 :     switch (Expr[0]) {
     166         196 :     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          12 :     case '&':
     175             :       Op = BinOpToken::BitwiseAnd;
     176          12 :       break;
     177           1 :     case '|':
     178             :       Op = BinOpToken::BitwiseOr;
     179           1 :       break;
     180             :     }
     181             : 
     182         585 :     return std::make_pair(Op, Expr.substr(1).ltrim());
     183             :   }
     184             : 
     185         202 :   EvalResult computeBinOpResult(BinOpToken Op, const EvalResult &LHSResult,
     186             :                                 const EvalResult &RHSResult) const {
     187         202 :     switch (Op) {
     188           0 :     default:
     189           0 :       llvm_unreachable("Tried to evaluate unrecognized operation.");
     190          93 :     case BinOpToken::Add:
     191          93 :       return EvalResult(LHSResult.getValue() + RHSResult.getValue());
     192          89 :     case BinOpToken::Sub:
     193          89 :       return EvalResult(LHSResult.getValue() - RHSResult.getValue());
     194          12 :     case BinOpToken::BitwiseAnd:
     195          12 :       return EvalResult(LHSResult.getValue() & RHSResult.getValue());
     196           1 :     case BinOpToken::BitwiseOr:
     197           1 :       return EvalResult(LHSResult.getValue() | RHSResult.getValue());
     198           7 :     case BinOpToken::ShiftLeft:
     199           7 :       return EvalResult(LHSResult.getValue() << RHSResult.getValue());
     200           0 :     case BinOpToken::ShiftRight:
     201           0 :       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         630 :   std::pair<StringRef, StringRef> parseSymbol(StringRef Expr) const {
     208         630 :     size_t FirstNonSymbol = Expr.find_first_not_of("0123456789"
     209             :                                                    "abcdefghijklmnopqrstuvwxyz"
     210             :                                                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     211         630 :                                                    ":_.$");
     212             :     return std::make_pair(Expr.substr(0, FirstNonSymbol),
     213        1890 :                           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          95 :   std::pair<EvalResult, StringRef> evalDecodeOperand(StringRef Expr) const {
     223             :     if (!Expr.startswith("("))
     224           0 :       return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");
     225         190 :     StringRef RemainingExpr = Expr.substr(1).ltrim();
     226          95 :     StringRef Symbol;
     227         190 :     std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
     228             : 
     229          95 :     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         190 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     238             : 
     239             :     EvalResult OpIdxExpr;
     240         190 :     std::tie(OpIdxExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
     241          95 :     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         190 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     248             : 
     249             :     MCInst Inst;
     250             :     uint64_t Size;
     251          95 :     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          95 :     unsigned OpIdx = OpIdxExpr.getValue();
     257          95 :     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          95 :     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         190 :     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          19 :   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          38 :     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          38 :     FileName = RemainingExpr.substr(0, ComaIdx).rtrim();
     338          38 :     RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim();
     339             : 
     340             :     if (!RemainingExpr.startswith(","))
     341           0 :       return std::make_pair(
     342           0 :           unexpectedToken(RemainingExpr, Expr, "expected ','"), "");
     343          38 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     344             : 
     345             :     StringRef SectionName;
     346          38 :     std::tie(SectionName, RemainingExpr) = parseSymbol(RemainingExpr);
     347             : 
     348             :     if (!RemainingExpr.startswith(","))
     349           0 :       return std::make_pair(
     350           0 :           unexpectedToken(RemainingExpr, Expr, "expected ','"), "");
     351          38 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     352             : 
     353             :     StringRef Symbol;
     354          38 :     std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
     355             : 
     356             :     if (!RemainingExpr.startswith(")"))
     357           0 :       return std::make_pair(
     358           0 :           unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");
     359          38 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     360             : 
     361             :     uint64_t StubAddr;
     362          19 :     std::string ErrorMsg = "";
     363          57 :     std::tie(StubAddr, ErrorMsg) = Checker.getStubAddrFor(
     364          19 :         FileName, SectionName, Symbol, PCtx.IsInsideLoad);
     365             : 
     366          19 :     if (ErrorMsg != "")
     367           0 :       return std::make_pair(EvalResult(ErrorMsg), "");
     368             : 
     369          19 :     return std::make_pair(EvalResult(StubAddr), RemainingExpr);
     370             :   }
     371             : 
     372          40 :   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          80 :     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          80 :     FileName = RemainingExpr.substr(0, ComaIdx).rtrim();
     383          80 :     RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim();
     384             : 
     385             :     if (!RemainingExpr.startswith(","))
     386           0 :       return std::make_pair(
     387           0 :           unexpectedToken(RemainingExpr, Expr, "expected ','"), "");
     388          80 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     389             : 
     390             :     StringRef SectionName;
     391          80 :     std::tie(SectionName, RemainingExpr) = parseSymbol(RemainingExpr);
     392             : 
     393             :     if (!RemainingExpr.startswith(")"))
     394           0 :       return std::make_pair(
     395           0 :           unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");
     396          80 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     397             : 
     398             :     uint64_t StubAddr;
     399          40 :     std::string ErrorMsg = "";
     400         120 :     std::tie(StubAddr, ErrorMsg) = Checker.getSectionAddr(
     401          40 :         FileName, SectionName, PCtx.IsInsideLoad);
     402             : 
     403          40 :     if (ErrorMsg != "")
     404           0 :       return std::make_pair(EvalResult(ErrorMsg), "");
     405             : 
     406          40 :     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         443 :   std::pair<EvalResult, StringRef> evalIdentifierExpr(StringRef Expr,
     413             :                                                       ParseContext PCtx) const {
     414             :     StringRef Symbol;
     415             :     StringRef RemainingExpr;
     416         886 :     std::tie(Symbol, RemainingExpr) = parseSymbol(Expr);
     417             : 
     418             :     // Check for builtin function calls.
     419             :     if (Symbol == "decode_operand")
     420          95 :       return evalDecodeOperand(RemainingExpr);
     421             :     else if (Symbol == "next_pc")
     422          14 :       return evalNextPC(RemainingExpr, PCtx);
     423             :     else if (Symbol == "stub_addr")
     424          19 :       return evalStubAddr(RemainingExpr, PCtx);
     425             :     else if (Symbol == "section_addr")
     426          40 :       return evalSectionAddr(RemainingExpr, PCtx);
     427             : 
     428         275 :     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         472 :     uint64_t Value = PCtx.IsInsideLoad ? Checker.getSymbolLocalAddr(Symbol)
     443         197 :                                        : Checker.getSymbolRemoteAddr(Symbol);
     444             : 
     445             :     // Looks like a plain symbol reference.
     446         275 :     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         702 :   std::pair<StringRef, StringRef> parseNumberString(StringRef Expr) const {
     452             :     size_t FirstNonDigit = StringRef::npos;
     453             :     if (Expr.startswith("0x")) {
     454          77 :       FirstNonDigit = Expr.find_first_not_of("0123456789abcdefABCDEF", 2);
     455          77 :       if (FirstNonDigit == StringRef::npos)
     456             :         FirstNonDigit = Expr.size();
     457             :     } else {
     458         625 :       FirstNonDigit = Expr.find_first_not_of("0123456789");
     459         625 :       if (FirstNonDigit == StringRef::npos)
     460             :         FirstNonDigit = Expr.size();
     461             :     }
     462             :     return std::make_pair(Expr.substr(0, FirstNonDigit),
     463         702 :                           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         702 :   std::pair<EvalResult, StringRef> evalNumberExpr(StringRef Expr) const {
     470             :     StringRef ValueStr;
     471             :     StringRef RemainingExpr;
     472        1404 :     std::tie(ValueStr, RemainingExpr) = parseNumberString(Expr);
     473             : 
     474        1404 :     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         702 :     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         177 :   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         708 :         evalComplexExpr(evalSimpleExpr(Expr.substr(1).ltrim(), PCtx), PCtx);
     492         177 :     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         354 :     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         104 :   std::pair<EvalResult, StringRef> evalLoadExpr(StringRef Expr) const {
     506             :     assert(Expr.startswith("*") && "Not a load expression");
     507         208 :     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         208 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     513             :     EvalResult ReadSizeExpr;
     514         208 :     std::tie(ReadSizeExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
     515         104 :     if (ReadSizeExpr.hasError())
     516             :       return std::make_pair(ReadSizeExpr, RemainingExpr);
     517         104 :     uint64_t ReadSize = ReadSizeExpr.getValue();
     518         104 :     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         208 :     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         312 :         evalComplexExpr(evalSimpleExpr(RemainingExpr, LoadCtx), LoadCtx);
     529             : 
     530         104 :     if (LoadAddrExprResult.hasError())
     531           0 :       return std::make_pair(LoadAddrExprResult, "");
     532             : 
     533         104 :     uint64_t LoadAddr = LoadAddrExprResult.getValue();
     534             : 
     535             :     return std::make_pair(
     536         208 :         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         879 :   std::pair<EvalResult, StringRef> evalSimpleExpr(StringRef Expr,
     548             :                                                   ParseContext PCtx) const {
     549             :     EvalResult SubExprResult;
     550         879 :     StringRef RemainingExpr;
     551             : 
     552         879 :     if (Expr.empty())
     553           0 :       return std::make_pair(EvalResult("Unexpected end of expression"), "");
     554             : 
     555         879 :     if (Expr[0] == '(')
     556         354 :       std::tie(SubExprResult, RemainingExpr) = evalParensExpr(Expr, PCtx);
     557         702 :     else if (Expr[0] == '*')
     558         208 :       std::tie(SubExprResult, RemainingExpr) = evalLoadExpr(Expr);
     559         598 :     else if (isalpha(Expr[0]) || Expr[0] == '_')
     560         886 :       std::tie(SubExprResult, RemainingExpr) = evalIdentifierExpr(Expr, PCtx);
     561         155 :     else if (isdigit(Expr[0]))
     562         310 :       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         879 :     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         522 :           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         174 :   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         348 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     594             : 
     595             :     EvalResult HighBitExpr;
     596         348 :     std::tie(HighBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
     597             : 
     598         174 :     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         348 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     605             : 
     606             :     EvalResult LowBitExpr;
     607         348 :     std::tie(LowBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
     608             : 
     609         174 :     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         348 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     616             : 
     617         174 :     unsigned HighBit = HighBitExpr.getValue();
     618         174 :     unsigned LowBit = LowBitExpr.getValue();
     619         174 :     uint64_t Mask = ((uint64_t)1 << (HighBit - LowBit + 1)) - 1;
     620         174 :     uint64_t SlicedValue = (SubExprResult.getValue() >> LowBit) & Mask;
     621         174 :     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         879 :   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         879 :     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         796 :     std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr);
     645             : 
     646             :     // If this isn't a recognized expression just return.
     647         398 :     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         404 :     std::tie(RHSResult, RemainingExpr) = evalSimpleExpr(RemainingExpr, PCtx);
     653             : 
     654             :     // If there was an error evaluating the RHS, return it.
     655         202 :     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         202 :     EvalResult ThisResult(computeBinOpResult(BinOp, LHSResult, RHSResult));
     661             : 
     662         404 :     return evalComplexExpr(std::make_pair(ThisResult, RemainingExpr), PCtx);
     663             :   }
     664             : 
     665         109 :   bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size) const {
     666         109 :     MCDisassembler *Dis = Checker.Disassembler;
     667         109 :     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         109 :         Dis->getInstruction(Inst, Size, SectionBytes, 0, nulls(), nulls());
     674             : 
     675         109 :     return (S == MCDisassembler::Success);
     676             :   }
     677             : };
     678             : }
     679             : 
     680          36 : RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl(RuntimeDyld &RTDyld,
     681             :                                                MCDisassembler *Disassembler,
     682             :                                                MCInstPrinter *InstPrinter,
     683          36 :                                                raw_ostream &ErrStream)
     684             :     : RTDyld(RTDyld), Disassembler(Disassembler), InstPrinter(InstPrinter),
     685          36 :       ErrStream(ErrStream) {
     686          36 :   RTDyld.Checker = this;
     687          36 : }
     688             : 
     689         198 : bool RuntimeDyldCheckerImpl::check(StringRef CheckExpr) const {
     690         198 :   CheckExpr = CheckExpr.trim();
     691             :   DEBUG(dbgs() << "RuntimeDyldChecker: Checking '" << CheckExpr << "'...\n");
     692             :   RuntimeDyldCheckerExprEval P(*this, ErrStream);
     693         198 :   bool Result = P.evaluate(CheckExpr);
     694             :   (void)Result;
     695             :   DEBUG(dbgs() << "RuntimeDyldChecker: '" << CheckExpr << "' "
     696             :                << (Result ? "passed" : "FAILED") << ".\n");
     697         198 :   return Result;
     698             : }
     699             : 
     700          27 : bool RuntimeDyldCheckerImpl::checkAllRulesInBuffer(StringRef RulePrefix,
     701             :                                                    MemoryBuffer *MemBuf) const {
     702             :   bool DidAllTestsPass = true;
     703             :   unsigned NumRules = 0;
     704             : 
     705          27 :   const char *LineStart = MemBuf->getBufferStart();
     706             : 
     707             :   // Eat whitespace.
     708          27 :   while (LineStart != MemBuf->getBufferEnd() && std::isspace(*LineStart))
     709           0 :     ++LineStart;
     710             : 
     711        3451 :   while (LineStart != MemBuf->getBufferEnd() && *LineStart != '\0') {
     712             :     const char *LineEnd = LineStart;
     713      111244 :     while (LineEnd != MemBuf->getBufferEnd() && *LineEnd != '\r' &&
     714             :            *LineEnd != '\n')
     715       54766 :       ++LineEnd;
     716             : 
     717        1712 :     StringRef Line(LineStart, LineEnd - LineStart);
     718             :     if (Line.startswith(RulePrefix)) {
     719         198 :       DidAllTestsPass &= check(Line.substr(RulePrefix.size()));
     720         198 :       ++NumRules;
     721             :     }
     722             : 
     723             :     // Eat whitespace.
     724             :     LineStart = LineEnd;
     725       10126 :     while (LineStart != MemBuf->getBufferEnd() && std::isspace(*LineStart))
     726        4207 :       ++LineStart;
     727             :   }
     728          27 :   return DidAllTestsPass && (NumRules != 0);
     729             : }
     730             : 
     731         384 : bool RuntimeDyldCheckerImpl::isSymbolValid(StringRef Symbol) const {
     732         768 :   if (getRTDyld().getSymbol(Symbol))
     733             :     return true;
     734           9 :   JITSymbolResolver::LookupSet Symbols({Symbol});
     735          27 :   auto Result = getRTDyld().Resolver.lookup(Symbols);
     736           9 :   if (!Result) {
     737           0 :     logAllUnhandledErrors(Result.takeError(), errs(), "RTDyldChecker: ");
     738           0 :     return false;
     739             :   }
     740             :   assert(Result->count(Symbol) && "Missing symbol result");
     741             :   return true;
     742             : }
     743             : 
     744          78 : uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const {
     745             :   return static_cast<uint64_t>(
     746         156 :       reinterpret_cast<uintptr_t>(getRTDyld().getSymbolLocalAddress(Symbol)));
     747             : }
     748             : 
     749         211 : uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const {
     750         422 :   if (auto InternalSymbol = getRTDyld().getSymbol(Symbol))
     751         202 :     return InternalSymbol.getAddress();
     752             : 
     753           9 :   JITSymbolResolver::LookupSet Symbols({Symbol});
     754          27 :   auto Result = getRTDyld().Resolver.lookup(Symbols);
     755           9 :   if (!Result) {
     756           0 :     logAllUnhandledErrors(Result.takeError(), errs(), "RTDyldChecker: ");
     757           0 :     return 0;
     758             :   }
     759             :   auto I = Result->find(Symbol);
     760             :   assert(I != Result->end() && "Missing symbol result");
     761           9 :   return I->second.getAddress();
     762             : }
     763             : 
     764         104 : uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr,
     765             :                                                   unsigned Size) const {
     766             :   uintptr_t PtrSizedAddr = static_cast<uintptr_t>(SrcAddr);
     767             :   assert(PtrSizedAddr == SrcAddr && "Linker memory pointer out-of-range.");
     768         104 :   uint8_t *Src = reinterpret_cast<uint8_t*>(PtrSizedAddr);
     769         208 :   return getRTDyld().readBytesUnaligned(Src, Size);
     770             : }
     771             : 
     772             : 
     773             : std::pair<const RuntimeDyldCheckerImpl::SectionAddressInfo*, std::string>
     774          93 : RuntimeDyldCheckerImpl::findSectionAddrInfo(StringRef FileName,
     775             :                                             StringRef SectionName) const {
     776             : 
     777          93 :   auto SectionMapItr = Stubs.find(FileName);
     778          93 :   if (SectionMapItr == Stubs.end()) {
     779           0 :     std::string ErrorMsg = "File '";
     780             :     ErrorMsg += FileName;
     781             :     ErrorMsg += "' not found. ";
     782           0 :     if (Stubs.empty())
     783             :       ErrorMsg += "No stubs registered.";
     784             :     else {
     785             :       ErrorMsg += "Available files are:";
     786           0 :       for (const auto& StubEntry : Stubs) {
     787             :         ErrorMsg += " '";
     788             :         ErrorMsg += StubEntry.first;
     789             :         ErrorMsg += "'";
     790             :       }
     791             :     }
     792             :     ErrorMsg += "\n";
     793           0 :     return std::make_pair(nullptr, ErrorMsg);
     794             :   }
     795             : 
     796          93 :   auto SectionInfoItr = SectionMapItr->second.find(SectionName);
     797          93 :   if (SectionInfoItr == SectionMapItr->second.end())
     798           0 :     return std::make_pair(nullptr,
     799           0 :                           ("Section '" + SectionName + "' not found in file '" +
     800           0 :                            FileName + "'\n").str());
     801             : 
     802         186 :   return std::make_pair(&SectionInfoItr->second, std::string(""));
     803             : }
     804             : 
     805          74 : std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getSectionAddr(
     806             :     StringRef FileName, StringRef SectionName, bool IsInsideLoad) const {
     807             : 
     808             :   const SectionAddressInfo *SectionInfo = nullptr;
     809             :   {
     810             :     std::string ErrorMsg;
     811             :     std::tie(SectionInfo, ErrorMsg) =
     812         148 :       findSectionAddrInfo(FileName, SectionName);
     813          74 :     if (ErrorMsg != "")
     814           0 :       return std::make_pair(0, ErrorMsg);
     815             :   }
     816             : 
     817          74 :   unsigned SectionID = SectionInfo->SectionID;
     818             :   uint64_t Addr;
     819          74 :   if (IsInsideLoad)
     820          52 :     Addr = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(
     821         104 :         getRTDyld().Sections[SectionID].getAddress()));
     822             :   else
     823          44 :     Addr = getRTDyld().Sections[SectionID].getLoadAddress();
     824             : 
     825         148 :   return std::make_pair(Addr, std::string(""));
     826             : }
     827             : 
     828          19 : std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubAddrFor(
     829             :     StringRef FileName, StringRef SectionName, StringRef SymbolName,
     830             :     bool IsInsideLoad) const {
     831             : 
     832             :   const SectionAddressInfo *SectionInfo = nullptr;
     833             :   {
     834             :     std::string ErrorMsg;
     835             :     std::tie(SectionInfo, ErrorMsg) =
     836          38 :       findSectionAddrInfo(FileName, SectionName);
     837          19 :     if (ErrorMsg != "")
     838           0 :       return std::make_pair(0, ErrorMsg);
     839             :   }
     840             : 
     841          19 :   unsigned SectionID = SectionInfo->SectionID;
     842             :   const StubOffsetsMap &SymbolStubs = SectionInfo->StubOffsets;
     843          19 :   auto StubOffsetItr = SymbolStubs.find(SymbolName);
     844          19 :   if (StubOffsetItr == SymbolStubs.end())
     845           0 :     return std::make_pair(0,
     846           0 :                           ("Stub for symbol '" + SymbolName + "' not found. "
     847           0 :                            "If '" + SymbolName + "' is an internal symbol this "
     848             :                            "may indicate that the stub target offset is being "
     849           0 :                            "computed incorrectly.\n").str());
     850             : 
     851          19 :   uint64_t StubOffset = StubOffsetItr->second;
     852             : 
     853             :   uint64_t Addr;
     854          19 :   if (IsInsideLoad) {
     855             :     uintptr_t SectionBase = reinterpret_cast<uintptr_t>(
     856          16 :         getRTDyld().Sections[SectionID].getAddress());
     857           8 :     Addr = static_cast<uint64_t>(SectionBase) + StubOffset;
     858             :   } else {
     859          22 :     uint64_t SectionBase = getRTDyld().Sections[SectionID].getLoadAddress();
     860          11 :     Addr = SectionBase + StubOffset;
     861             :   }
     862             : 
     863          38 :   return std::make_pair(Addr, std::string(""));
     864             : }
     865             : 
     866             : StringRef
     867         109 : RuntimeDyldCheckerImpl::getSubsectionStartingAt(StringRef Name) const {
     868             :   RTDyldSymbolTable::const_iterator pos =
     869         327 :       getRTDyld().GlobalSymbolTable.find(Name);
     870         327 :   if (pos == getRTDyld().GlobalSymbolTable.end())
     871           0 :     return StringRef();
     872             :   const auto &SymInfo = pos->second;
     873         109 :   uint8_t *SectionAddr = getRTDyld().getSectionAddress(SymInfo.getSectionID());
     874         109 :   return StringRef(reinterpret_cast<const char *>(SectionAddr) +
     875             :                        SymInfo.getOffset(),
     876         109 :                    getRTDyld().Sections[SymInfo.getSectionID()].getSize() -
     877         218 :                        SymInfo.getOffset());
     878             : }
     879             : 
     880             : Optional<uint64_t>
     881         147 : RuntimeDyldCheckerImpl::getSectionLoadAddress(void *LocalAddress) const {
     882         944 :   for (auto &S : getRTDyld().Sections) {
     883         472 :     if (S.getAddress() == LocalAddress)
     884         147 :       return S.getLoadAddress();
     885             :   }
     886             :   return Optional<uint64_t>();
     887             : }
     888             : 
     889         147 : void RuntimeDyldCheckerImpl::registerSection(
     890             :     StringRef FilePath, unsigned SectionID) {
     891         147 :   StringRef FileName = sys::path::filename(FilePath);
     892         147 :   const SectionEntry &Section = getRTDyld().Sections[SectionID];
     893             :   StringRef SectionName = Section.getName();
     894             : 
     895         441 :   Stubs[FileName][SectionName].SectionID = SectionID;
     896         147 : }
     897             : 
     898          98 : void RuntimeDyldCheckerImpl::registerStubMap(
     899             :     StringRef FilePath, unsigned SectionID,
     900             :     const RuntimeDyldImpl::StubMap &RTDyldStubs) {
     901          98 :   StringRef FileName = sys::path::filename(FilePath);
     902          98 :   const SectionEntry &Section = getRTDyld().Sections[SectionID];
     903             :   StringRef SectionName = Section.getName();
     904             : 
     905         294 :   Stubs[FileName][SectionName].SectionID = SectionID;
     906             : 
     907         110 :   for (auto &StubMapEntry : RTDyldStubs) {
     908          12 :     std::string SymbolName = "";
     909             : 
     910          12 :     if (StubMapEntry.first.SymbolName)
     911             :       SymbolName = StubMapEntry.first.SymbolName;
     912             :     else {
     913             :       // If this is a (Section, Offset) pair, do a reverse lookup in the
     914             :       // global symbol table to find the name.
     915          69 :       for (auto &GSTEntry : getRTDyld().GlobalSymbolTable) {
     916             :         const auto &SymInfo = GSTEntry.second;
     917          70 :         if (SymInfo.getSectionID() == StubMapEntry.first.SectionID &&
     918          13 :             SymInfo.getOffset() ==
     919          13 :               static_cast<uint64_t>(StubMapEntry.first.Offset)) {
     920          12 :           SymbolName = GSTEntry.first();
     921           6 :           break;
     922             :         }
     923             :       }
     924             :     }
     925             : 
     926          12 :     if (SymbolName != "")
     927          48 :       Stubs[FileName][SectionName].StubOffsets[SymbolName] =
     928          12 :         StubMapEntry.second;
     929             :   }
     930          98 : }
     931             : 
     932          36 : RuntimeDyldChecker::RuntimeDyldChecker(RuntimeDyld &RTDyld,
     933             :                                        MCDisassembler *Disassembler,
     934             :                                        MCInstPrinter *InstPrinter,
     935          36 :                                        raw_ostream &ErrStream)
     936             :     : Impl(make_unique<RuntimeDyldCheckerImpl>(RTDyld, Disassembler,
     937          36 :                                                InstPrinter, ErrStream)) {}
     938             : 
     939          72 : RuntimeDyldChecker::~RuntimeDyldChecker() {}
     940             : 
     941         130 : RuntimeDyld& RuntimeDyldChecker::getRTDyld() {
     942         130 :   return Impl->RTDyld;
     943             : }
     944             : 
     945           0 : const RuntimeDyld& RuntimeDyldChecker::getRTDyld() const {
     946           0 :   return Impl->RTDyld;
     947             : }
     948             : 
     949           0 : bool RuntimeDyldChecker::check(StringRef CheckExpr) const {
     950           0 :   return Impl->check(CheckExpr);
     951             : }
     952             : 
     953          27 : bool RuntimeDyldChecker::checkAllRulesInBuffer(StringRef RulePrefix,
     954             :                                                MemoryBuffer *MemBuf) const {
     955          27 :   return Impl->checkAllRulesInBuffer(RulePrefix, MemBuf);
     956             : }
     957             : 
     958             : std::pair<uint64_t, std::string>
     959          34 : RuntimeDyldChecker::getSectionAddr(StringRef FileName, StringRef SectionName,
     960             :                                    bool LocalAddress) {
     961          34 :   return Impl->getSectionAddr(FileName, SectionName, LocalAddress);
     962             : }
     963             : 
     964             : Optional<uint64_t>
     965         147 : RuntimeDyldChecker::getSectionLoadAddress(void *LocalAddress) const {
     966         147 :   return Impl->getSectionLoadAddress(LocalAddress);
     967             : }

Generated by: LCOV version 1.13