LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/RuntimeDyld - RuntimeDyldChecker.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 367 506 72.5 %
Date: 2017-09-14 15:23:50 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         195 :       : Checker(Checker) {}
      34             : 
      35         195 :   bool evaluate(StringRef Expr) const {
      36             :     // Expect equality expression of the form 'LHS = RHS'.
      37         390 :     Expr = Expr.trim();
      38         195 :     size_t EQIdx = Expr.find('=');
      39             : 
      40         195 :     ParseContext OutsideLoad(false);
      41             : 
      42             :     // Evaluate LHS.
      43         390 :     StringRef LHSExpr = Expr.substr(0, EQIdx).rtrim();
      44         195 :     StringRef RemainingExpr;
      45         390 :     EvalResult LHSResult;
      46         195 :     std::tie(LHSResult, RemainingExpr) =
      47         780 :         evalComplexExpr(evalSimpleExpr(LHSExpr, OutsideLoad), OutsideLoad);
      48         195 :     if (LHSResult.hasError())
      49           0 :       return handleError(Expr, LHSResult);
      50         390 :     if (RemainingExpr != "")
      51           0 :       return handleError(Expr, unexpectedToken(RemainingExpr, LHSExpr, ""));
      52             : 
      53             :     // Evaluate RHS.
      54         585 :     StringRef RHSExpr = Expr.substr(EQIdx + 1).ltrim();
      55         195 :     EvalResult RHSResult;
      56         195 :     std::tie(RHSResult, RemainingExpr) =
      57         780 :         evalComplexExpr(evalSimpleExpr(RHSExpr, OutsideLoad), OutsideLoad);
      58         195 :     if (RHSResult.hasError())
      59           0 :       return handleError(Expr, RHSResult);
      60         390 :     if (RemainingExpr != "")
      61           0 :       return handleError(Expr, unexpectedToken(RemainingExpr, RHSExpr, ""));
      62             : 
      63         195 :     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         296 :     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       26767 :   class EvalResult {
      98             :   public:
      99        6626 :     EvalResult() : Value(0), ErrorMsg("") {}
     100        3214 :     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        6282 :     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           0 :       unsigned TokLen = 1;
     123           0 :       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           0 :     if (SubExpr != "") {
     135           0 :       ErrorMsg += "' while parsing subexpression '";
     136             :       ErrorMsg += SubExpr;
     137             :     }
     138           0 :     ErrorMsg += "'";
     139           0 :     if (ErrText != "") {
     140           0 :       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         392 :   std::pair<BinOpToken, StringRef> parseBinOpToken(StringRef Expr) const {
     154         392 :     if (Expr.empty())
     155           0 :       return std::make_pair(BinOpToken::Invalid, "");
     156             : 
     157             :     // Handle the two 2-character tokens.
     158         399 :     if (Expr.startswith("<<"))
     159          21 :       return std::make_pair(BinOpToken::ShiftLeft, Expr.substr(2).ltrim());
     160         385 :     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         770 :     switch (Expr[0]) {
     166         190 :     default:
     167         380 :       return std::make_pair(BinOpToken::Invalid, Expr);
     168             :     case '+':
     169             :       Op = BinOpToken::Add;
     170             :       break;
     171          89 :     case '-':
     172          89 :       Op = BinOpToken::Sub;
     173          89 :       break;
     174          12 :     case '&':
     175          12 :       Op = BinOpToken::BitwiseAnd;
     176          12 :       break;
     177           1 :     case '|':
     178           1 :       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         616 :   std::pair<StringRef, StringRef> parseSymbol(StringRef Expr) const {
     208        1232 :     size_t FirstNonSymbol = Expr.find_first_not_of("0123456789"
     209             :                                                    "abcdefghijklmnopqrstuvwxyz"
     210             :                                                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     211         616 :                                                    ":_.$");
     212         616 :     return std::make_pair(Expr.substr(0, FirstNonSymbol),
     213        1848 :                           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         190 :     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         285 :     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         190 :     if (!RemainingExpr.startswith(","))
     235           0 :       return std::make_pair(
     236           0 :           unexpectedToken(RemainingExpr, RemainingExpr, "expected ','"), "");
     237         190 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     238             : 
     239          95 :     EvalResult OpIdxExpr;
     240         380 :     std::tie(OpIdxExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
     241          95 :     if (OpIdxExpr.hasError())
     242           0 :       return std::make_pair(OpIdxExpr, "");
     243             : 
     244         190 :     if (!RemainingExpr.startswith(")"))
     245           0 :       return std::make_pair(
     246           0 :           unexpectedToken(RemainingExpr, RemainingExpr, "expected ')'"), "");
     247         190 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     248             : 
     249          95 :     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           0 :       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         190 :     const MCOperand &Op = Inst.getOperand(OpIdx);
     270          95 :     if (!Op.isImm()) {
     271           0 :       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         380 :     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          28 :     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          42 :     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          28 :     if (!RemainingExpr.startswith(")"))
     303           0 :       return std::make_pair(
     304           0 :           unexpectedToken(RemainingExpr, RemainingExpr, "expected ')'"), "");
     305          28 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     306             : 
     307          14 :     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          28 :                               : Checker.getSymbolRemoteAddr(Symbol);
     317          14 :     uint64_t NextPC = SymbolAddr + InstSize;
     318             : 
     319          42 :     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          15 :   std::pair<EvalResult, StringRef> evalStubAddr(StringRef Expr,
     328             :                                                 ParseContext PCtx) const {
     329          30 :     if (!Expr.startswith("("))
     330           0 :       return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");
     331          30 :     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          15 :     StringRef FileName;
     336          15 :     size_t ComaIdx = RemainingExpr.find(',');
     337          30 :     FileName = RemainingExpr.substr(0, ComaIdx).rtrim();
     338          30 :     RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim();
     339             : 
     340          30 :     if (!RemainingExpr.startswith(","))
     341           0 :       return std::make_pair(
     342           0 :           unexpectedToken(RemainingExpr, Expr, "expected ','"), "");
     343          30 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     344             : 
     345             :     StringRef SectionName;
     346          45 :     std::tie(SectionName, RemainingExpr) = parseSymbol(RemainingExpr);
     347             : 
     348          30 :     if (!RemainingExpr.startswith(","))
     349           0 :       return std::make_pair(
     350           0 :           unexpectedToken(RemainingExpr, Expr, "expected ','"), "");
     351          30 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     352             : 
     353             :     StringRef Symbol;
     354          45 :     std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
     355             : 
     356          30 :     if (!RemainingExpr.startswith(")"))
     357           0 :       return std::make_pair(
     358           0 :           unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");
     359          30 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     360             : 
     361             :     uint64_t StubAddr;
     362          30 :     std::string ErrorMsg = "";
     363          60 :     std::tie(StubAddr, ErrorMsg) = Checker.getStubAddrFor(
     364          30 :         FileName, SectionName, Symbol, PCtx.IsInsideLoad);
     365             : 
     366          15 :     if (ErrorMsg != "")
     367           0 :       return std::make_pair(EvalResult(ErrorMsg), "");
     368             : 
     369          60 :     return std::make_pair(EvalResult(StubAddr), RemainingExpr);
     370             :   }
     371             : 
     372          40 :   std::pair<EvalResult, StringRef> evalSectionAddr(StringRef Expr,
     373             :                                                    ParseContext PCtx) const {
     374          80 :     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          40 :     StringRef FileName;
     381          40 :     size_t ComaIdx = RemainingExpr.find(',');
     382          80 :     FileName = RemainingExpr.substr(0, ComaIdx).rtrim();
     383          80 :     RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim();
     384             : 
     385          80 :     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         120 :     std::tie(SectionName, RemainingExpr) = parseSymbol(RemainingExpr);
     392             : 
     393          80 :     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          80 :     std::string ErrorMsg = "";
     400         160 :     std::tie(StubAddr, ErrorMsg) = Checker.getSectionAddr(
     401          80 :         FileName, SectionName, PCtx.IsInsideLoad);
     402             : 
     403          40 :     if (ErrorMsg != "")
     404           0 :       return std::make_pair(EvalResult(ErrorMsg), "");
     405             : 
     406         160 :     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         437 :   std::pair<EvalResult, StringRef> evalIdentifierExpr(StringRef Expr,
     413             :                                                       ParseContext PCtx) const {
     414             :     StringRef Symbol;
     415             :     StringRef RemainingExpr;
     416        1311 :     std::tie(Symbol, RemainingExpr) = parseSymbol(Expr);
     417             : 
     418             :     // Check for builtin function calls.
     419         532 :     if (Symbol == "decode_operand")
     420          95 :       return evalDecodeOperand(RemainingExpr);
     421         356 :     else if (Symbol == "next_pc")
     422          14 :       return evalNextPC(RemainingExpr, PCtx);
     423         343 :     else if (Symbol == "stub_addr")
     424          15 :       return evalStubAddr(RemainingExpr, PCtx);
     425         353 :     else if (Symbol == "section_addr")
     426          40 :       return evalSectionAddr(RemainingExpr, PCtx);
     427             : 
     428         273 :     if (!Checker.isSymbolValid(Symbol)) {
     429           0 :       std::string ErrMsg("No known address for symbol '");
     430           0 :       ErrMsg += Symbol;
     431           0 :       ErrMsg += "'";
     432           0 :       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         471 :     uint64_t Value = PCtx.IsInsideLoad ? Checker.getSymbolLocalAddr(Symbol)
     443         471 :                                        : Checker.getSymbolRemoteAddr(Symbol);
     444             : 
     445             :     // Looks like a plain symbol reference.
     446         819 :     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         695 :   std::pair<StringRef, StringRef> parseNumberString(StringRef Expr) const {
     452         695 :     size_t FirstNonDigit = StringRef::npos;
     453         772 :     if (Expr.startswith("0x")) {
     454          77 :       FirstNonDigit = Expr.find_first_not_of("0123456789abcdefABCDEF", 2);
     455          77 :       if (FirstNonDigit == StringRef::npos)
     456          38 :         FirstNonDigit = Expr.size();
     457             :     } else {
     458         618 :       FirstNonDigit = Expr.find_first_not_of("0123456789");
     459         618 :       if (FirstNonDigit == StringRef::npos)
     460          22 :         FirstNonDigit = Expr.size();
     461             :     }
     462         695 :     return std::make_pair(Expr.substr(0, FirstNonDigit),
     463        1390 :                           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         695 :   std::pair<EvalResult, StringRef> evalNumberExpr(StringRef Expr) const {
     470             :     StringRef ValueStr;
     471             :     StringRef RemainingExpr;
     472        2085 :     std::tie(ValueStr, RemainingExpr) = parseNumberString(Expr);
     473             : 
     474        1390 :     if (ValueStr.empty() || !isdigit(ValueStr[0]))
     475           0 :       return std::make_pair(
     476           0 :           unexpectedToken(RemainingExpr, RemainingExpr, "expected number"), "");
     477             :     uint64_t Value;
     478         695 :     ValueStr.getAsInteger(0, Value);
     479        2780 :     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         174 :   std::pair<EvalResult, StringRef> evalParensExpr(StringRef Expr,
     486             :                                                   ParseContext PCtx) const {
     487             :     assert(Expr.startswith("(") && "Not a parenthesized expression");
     488         348 :     EvalResult SubExprResult;
     489         174 :     StringRef RemainingExpr;
     490         174 :     std::tie(SubExprResult, RemainingExpr) =
     491         870 :         evalComplexExpr(evalSimpleExpr(Expr.substr(1).ltrim(), PCtx), PCtx);
     492         174 :     if (SubExprResult.hasError())
     493           0 :       return std::make_pair(SubExprResult, "");
     494         348 :     if (!RemainingExpr.startswith(")"))
     495           0 :       return std::make_pair(
     496           0 :           unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");
     497         348 :     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         101 :   std::pair<EvalResult, StringRef> evalLoadExpr(StringRef Expr) const {
     506             :     assert(Expr.startswith("*") && "Not a load expression");
     507         202 :     StringRef RemainingExpr = Expr.substr(1).ltrim();
     508             : 
     509             :     // Parse read size.
     510         202 :     if (!RemainingExpr.startswith("{"))
     511           0 :       return std::make_pair(EvalResult("Expected '{' following '*'."), "");
     512         202 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     513         101 :     EvalResult ReadSizeExpr;
     514         404 :     std::tie(ReadSizeExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
     515         101 :     if (ReadSizeExpr.hasError())
     516             :       return std::make_pair(ReadSizeExpr, RemainingExpr);
     517         101 :     uint64_t ReadSize = ReadSizeExpr.getValue();
     518         101 :     if (ReadSize < 1 || ReadSize > 8)
     519           0 :       return std::make_pair(EvalResult("Invalid size for dereference."), "");
     520         202 :     if (!RemainingExpr.startswith("}"))
     521           0 :       return std::make_pair(EvalResult("Missing '}' for dereference."), "");
     522         202 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     523             : 
     524             :     // Evaluate the expression representing the load address.
     525         101 :     ParseContext LoadCtx(true);
     526         101 :     EvalResult LoadAddrExprResult;
     527         101 :     std::tie(LoadAddrExprResult, RemainingExpr) =
     528         404 :         evalComplexExpr(evalSimpleExpr(RemainingExpr, LoadCtx), LoadCtx);
     529             : 
     530         101 :     if (LoadAddrExprResult.hasError())
     531           0 :       return std::make_pair(LoadAddrExprResult, "");
     532             : 
     533         101 :     uint64_t LoadAddr = LoadAddrExprResult.getValue();
     534             : 
     535             :     return std::make_pair(
     536         303 :         EvalResult(Checker.readMemoryAtAddr(LoadAddr, ReadSize)),
     537         101 :         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         867 :   std::pair<EvalResult, StringRef> evalSimpleExpr(StringRef Expr,
     548             :                                                   ParseContext PCtx) const {
     549        1734 :     EvalResult SubExprResult;
     550         867 :     StringRef RemainingExpr;
     551             : 
     552         867 :     if (Expr.empty())
     553           0 :       return std::make_pair(EvalResult("Unexpected end of expression"), "");
     554             : 
     555        1734 :     if (Expr[0] == '(')
     556         696 :       std::tie(SubExprResult, RemainingExpr) = evalParensExpr(Expr, PCtx);
     557         693 :     else if (Expr[0] == '*')
     558         404 :       std::tie(SubExprResult, RemainingExpr) = evalLoadExpr(Expr);
     559         592 :     else if (isalpha(Expr[0]) || Expr[0] == '_')
     560        1748 :       std::tie(SubExprResult, RemainingExpr) = evalIdentifierExpr(Expr, PCtx);
     561         155 :     else if (isdigit(Expr[0]))
     562         620 :       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         867 :     if (SubExprResult.hasError())
     569             :       return std::make_pair(SubExprResult, RemainingExpr);
     570             : 
     571             :     // Evaluate bit-slice if present.
     572        1039 :     if (RemainingExpr.startswith("["))
     573         172 :       std::tie(SubExprResult, RemainingExpr) =
     574         688 :           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         172 :   evalSliceExpr(const std::pair<EvalResult, StringRef> &Ctx) const {
     588         344 :     EvalResult SubExprResult;
     589         172 :     StringRef RemainingExpr;
     590         344 :     std::tie(SubExprResult, RemainingExpr) = Ctx;
     591             : 
     592             :     assert(RemainingExpr.startswith("[") && "Not a slice expr.");
     593         344 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     594             : 
     595         344 :     EvalResult HighBitExpr;
     596         688 :     std::tie(HighBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
     597             : 
     598         172 :     if (HighBitExpr.hasError())
     599             :       return std::make_pair(HighBitExpr, RemainingExpr);
     600             : 
     601         344 :     if (!RemainingExpr.startswith(":"))
     602           0 :       return std::make_pair(
     603           0 :           unexpectedToken(RemainingExpr, RemainingExpr, "expected ':'"), "");
     604         344 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     605             : 
     606         172 :     EvalResult LowBitExpr;
     607         688 :     std::tie(LowBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
     608             : 
     609         172 :     if (LowBitExpr.hasError())
     610             :       return std::make_pair(LowBitExpr, RemainingExpr);
     611             : 
     612         344 :     if (!RemainingExpr.startswith("]"))
     613           0 :       return std::make_pair(
     614           0 :           unexpectedToken(RemainingExpr, RemainingExpr, "expected ']'"), "");
     615         344 :     RemainingExpr = RemainingExpr.substr(1).ltrim();
     616             : 
     617         172 :     unsigned HighBit = HighBitExpr.getValue();
     618         172 :     unsigned LowBit = LowBitExpr.getValue();
     619         172 :     uint64_t Mask = ((uint64_t)1 << (HighBit - LowBit + 1)) - 1;
     620         172 :     uint64_t SlicedValue = (SubExprResult.getValue() >> LowBit) & Mask;
     621         516 :     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         867 :   evalComplexExpr(const std::pair<EvalResult, StringRef> &LHSAndRemaining,
     632             :                   ParseContext PCtx) const {
     633        1734 :     EvalResult LHSResult;
     634         867 :     StringRef RemainingExpr;
     635        1734 :     std::tie(LHSResult, RemainingExpr) = LHSAndRemaining;
     636             : 
     637             :     // If there was an error, or there's nothing left to evaluate, return the
     638             :     // result.
     639        1259 :     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        1176 :     std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr);
     645             : 
     646             :     // If this isn't a recognized expression just return.
     647         392 :     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         202 :     EvalResult RHSResult;
     652         808 :     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         109 :         reinterpret_cast<const uint8_t *>(SectionMem.data()),
     670         218 :         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          72 :       ErrStream(ErrStream) {
     686          36 :   RTDyld.Checker = this;
     687          36 : }
     688             : 
     689         195 : bool RuntimeDyldCheckerImpl::check(StringRef CheckExpr) const {
     690         390 :   CheckExpr = CheckExpr.trim();
     691             :   DEBUG(dbgs() << "RuntimeDyldChecker: Checking '" << CheckExpr << "'...\n");
     692         390 :   RuntimeDyldCheckerExprEval P(*this, ErrStream);
     693         195 :   bool Result = P.evaluate(CheckExpr);
     694             :   (void)Result;
     695             :   DEBUG(dbgs() << "RuntimeDyldChecker: '" << CheckExpr << "' "
     696             :                << (Result ? "passed" : "FAILED") << ".\n");
     697         195 :   return Result;
     698             : }
     699             : 
     700          27 : bool RuntimeDyldCheckerImpl::checkAllRulesInBuffer(StringRef RulePrefix,
     701             :                                                    MemoryBuffer *MemBuf) const {
     702          27 :   bool DidAllTestsPass = true;
     703          27 :   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        3423 :   while (LineStart != MemBuf->getBufferEnd() && *LineStart != '\0') {
     712             :     const char *LineEnd = LineStart;
     713      110076 :     while (LineEnd != MemBuf->getBufferEnd() && *LineEnd != '\r' &&
     714             :            *LineEnd != '\n')
     715       54189 :       ++LineEnd;
     716             : 
     717        3396 :     StringRef Line(LineStart, LineEnd - LineStart);
     718             :     if (Line.startswith(RulePrefix)) {
     719         390 :       DidAllTestsPass &= check(Line.substr(RulePrefix.size()));
     720         195 :       ++NumRules;
     721             :     }
     722             : 
     723             :     // Eat whitespace.
     724        1698 :     LineStart = LineEnd;
     725       10088 :     while (LineStart != MemBuf->getBufferEnd() && std::isspace(*LineStart))
     726        4195 :       ++LineStart;
     727             :   }
     728          27 :   return DidAllTestsPass && (NumRules != 0);
     729             : }
     730             : 
     731         382 : bool RuntimeDyldCheckerImpl::isSymbolValid(StringRef Symbol) const {
     732         764 :   if (getRTDyld().getSymbol(Symbol))
     733             :     return true;
     734          30 :   return !!getRTDyld().Resolver.findSymbol(Symbol);
     735             : }
     736             : 
     737          75 : uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const {
     738             :   return static_cast<uint64_t>(
     739         150 :       reinterpret_cast<uintptr_t>(getRTDyld().getSymbolLocalAddress(Symbol)));
     740             : }
     741             : 
     742         212 : uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const {
     743         424 :   if (auto InternalSymbol = getRTDyld().getSymbol(Symbol))
     744         206 :     return InternalSymbol.getAddress();
     745          36 :   return cantFail(getRTDyld().Resolver.findSymbol(Symbol).getAddress());
     746             : }
     747             : 
     748         101 : uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr,
     749             :                                                   unsigned Size) const {
     750         101 :   uintptr_t PtrSizedAddr = static_cast<uintptr_t>(SrcAddr);
     751             :   assert(PtrSizedAddr == SrcAddr && "Linker memory pointer out-of-range.");
     752         101 :   uint8_t *Src = reinterpret_cast<uint8_t*>(PtrSizedAddr);
     753         202 :   return getRTDyld().readBytesUnaligned(Src, Size);
     754             : }
     755             : 
     756             : 
     757             : std::pair<const RuntimeDyldCheckerImpl::SectionAddressInfo*, std::string>
     758          89 : RuntimeDyldCheckerImpl::findSectionAddrInfo(StringRef FileName,
     759             :                                             StringRef SectionName) const {
     760             : 
     761         356 :   auto SectionMapItr = Stubs.find(FileName);
     762         178 :   if (SectionMapItr == Stubs.end()) {
     763           0 :     std::string ErrorMsg = "File '";
     764           0 :     ErrorMsg += FileName;
     765           0 :     ErrorMsg += "' not found. ";
     766           0 :     if (Stubs.empty())
     767             :       ErrorMsg += "No stubs registered.";
     768             :     else {
     769           0 :       ErrorMsg += "Available files are:";
     770           0 :       for (const auto& StubEntry : Stubs) {
     771           0 :         ErrorMsg += " '";
     772           0 :         ErrorMsg += StubEntry.first;
     773           0 :         ErrorMsg += "'";
     774             :       }
     775             :     }
     776           0 :     ErrorMsg += "\n";
     777           0 :     return std::make_pair(nullptr, ErrorMsg);
     778             :   }
     779             : 
     780         356 :   auto SectionInfoItr = SectionMapItr->second.find(SectionName);
     781         178 :   if (SectionInfoItr == SectionMapItr->second.end())
     782           0 :     return std::make_pair(nullptr,
     783           0 :                           ("Section '" + SectionName + "' not found in file '" +
     784           0 :                            FileName + "'\n").str());
     785             : 
     786         445 :   return std::make_pair(&SectionInfoItr->second, std::string(""));
     787             : }
     788             : 
     789          74 : std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getSectionAddr(
     790             :     StringRef FileName, StringRef SectionName, bool IsInsideLoad) const {
     791             : 
     792          74 :   const SectionAddressInfo *SectionInfo = nullptr;
     793             :   {
     794         148 :     std::string ErrorMsg;
     795          74 :     std::tie(SectionInfo, ErrorMsg) =
     796         222 :       findSectionAddrInfo(FileName, SectionName);
     797          74 :     if (ErrorMsg != "")
     798           0 :       return std::make_pair(0, ErrorMsg);
     799             :   }
     800             : 
     801          74 :   unsigned SectionID = SectionInfo->SectionID;
     802             :   uint64_t Addr;
     803          74 :   if (IsInsideLoad)
     804          52 :     Addr = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(
     805         156 :         getRTDyld().Sections[SectionID].getAddress()));
     806             :   else
     807          66 :     Addr = getRTDyld().Sections[SectionID].getLoadAddress();
     808             : 
     809         296 :   return std::make_pair(Addr, std::string(""));
     810             : }
     811             : 
     812          15 : std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubAddrFor(
     813             :     StringRef FileName, StringRef SectionName, StringRef SymbolName,
     814             :     bool IsInsideLoad) const {
     815             : 
     816          15 :   const SectionAddressInfo *SectionInfo = nullptr;
     817             :   {
     818          30 :     std::string ErrorMsg;
     819          15 :     std::tie(SectionInfo, ErrorMsg) =
     820          45 :       findSectionAddrInfo(FileName, SectionName);
     821          15 :     if (ErrorMsg != "")
     822           0 :       return std::make_pair(0, ErrorMsg);
     823             :   }
     824             : 
     825          15 :   unsigned SectionID = SectionInfo->SectionID;
     826          15 :   const StubOffsetsMap &SymbolStubs = SectionInfo->StubOffsets;
     827          45 :   auto StubOffsetItr = SymbolStubs.find(SymbolName);
     828          15 :   if (StubOffsetItr == SymbolStubs.end())
     829           0 :     return std::make_pair(0,
     830           0 :                           ("Stub for symbol '" + SymbolName + "' not found. "
     831           0 :                            "If '" + SymbolName + "' is an internal symbol this "
     832             :                            "may indicate that the stub target offset is being "
     833           0 :                            "computed incorrectly.\n").str());
     834             : 
     835          15 :   uint64_t StubOffset = StubOffsetItr->second;
     836             : 
     837             :   uint64_t Addr;
     838          15 :   if (IsInsideLoad) {
     839             :     uintptr_t SectionBase = reinterpret_cast<uintptr_t>(
     840          24 :         getRTDyld().Sections[SectionID].getAddress());
     841           8 :     Addr = static_cast<uint64_t>(SectionBase) + StubOffset;
     842             :   } else {
     843          21 :     uint64_t SectionBase = getRTDyld().Sections[SectionID].getLoadAddress();
     844           7 :     Addr = SectionBase + StubOffset;
     845             :   }
     846             : 
     847          60 :   return std::make_pair(Addr, std::string(""));
     848             : }
     849             : 
     850             : StringRef
     851         109 : RuntimeDyldCheckerImpl::getSubsectionStartingAt(StringRef Name) const {
     852             :   RTDyldSymbolTable::const_iterator pos =
     853         327 :       getRTDyld().GlobalSymbolTable.find(Name);
     854         436 :   if (pos == getRTDyld().GlobalSymbolTable.end())
     855           0 :     return StringRef();
     856         109 :   const auto &SymInfo = pos->second;
     857         327 :   uint8_t *SectionAddr = getRTDyld().getSectionAddress(SymInfo.getSectionID());
     858         218 :   return StringRef(reinterpret_cast<const char *>(SectionAddr) +
     859         109 :                        SymInfo.getOffset(),
     860         327 :                    getRTDyld().Sections[SymInfo.getSectionID()].getSize() -
     861         218 :                        SymInfo.getOffset());
     862             : }
     863             : 
     864             : Optional<uint64_t>
     865         147 : RuntimeDyldCheckerImpl::getSectionLoadAddress(void *LocalAddress) const {
     866         913 :   for (auto &S : getRTDyld().Sections) {
     867         472 :     if (S.getAddress() == LocalAddress)
     868         294 :       return S.getLoadAddress();
     869             :   }
     870             :   return Optional<uint64_t>();
     871             : }
     872             : 
     873         147 : void RuntimeDyldCheckerImpl::registerSection(
     874             :     StringRef FilePath, unsigned SectionID) {
     875         147 :   StringRef FileName = sys::path::filename(FilePath);
     876         441 :   const SectionEntry &Section = getRTDyld().Sections[SectionID];
     877         147 :   StringRef SectionName = Section.getName();
     878             : 
     879         588 :   Stubs[FileName][SectionName].SectionID = SectionID;
     880         147 : }
     881             : 
     882          98 : void RuntimeDyldCheckerImpl::registerStubMap(
     883             :     StringRef FilePath, unsigned SectionID,
     884             :     const RuntimeDyldImpl::StubMap &RTDyldStubs) {
     885          98 :   StringRef FileName = sys::path::filename(FilePath);
     886         294 :   const SectionEntry &Section = getRTDyld().Sections[SectionID];
     887          98 :   StringRef SectionName = Section.getName();
     888             : 
     889         392 :   Stubs[FileName][SectionName].SectionID = SectionID;
     890             : 
     891         302 :   for (auto &StubMapEntry : RTDyldStubs) {
     892          24 :     std::string SymbolName = "";
     893             : 
     894           8 :     if (StubMapEntry.first.SymbolName)
     895           2 :       SymbolName = StubMapEntry.first.SymbolName;
     896             :     else {
     897             :       // If this is a (Section, Offset) pair, do a reverse lookup in the
     898             :       // global symbol table to find the name.
     899         138 :       for (auto &GSTEntry : getRTDyld().GlobalSymbolTable) {
     900          57 :         const auto &SymInfo = GSTEntry.second;
     901          70 :         if (SymInfo.getSectionID() == StubMapEntry.first.SectionID &&
     902          13 :             SymInfo.getOffset() ==
     903          13 :               static_cast<uint64_t>(StubMapEntry.first.Offset)) {
     904          18 :           SymbolName = GSTEntry.first();
     905           6 :           break;
     906             :         }
     907             :       }
     908             :     }
     909             : 
     910           8 :     if (SymbolName != "")
     911          40 :       Stubs[FileName][SectionName].StubOffsets[SymbolName] =
     912           8 :         StubMapEntry.second;
     913             :   }
     914          98 : }
     915             : 
     916          36 : RuntimeDyldChecker::RuntimeDyldChecker(RuntimeDyld &RTDyld,
     917             :                                        MCDisassembler *Disassembler,
     918             :                                        MCInstPrinter *InstPrinter,
     919          36 :                                        raw_ostream &ErrStream)
     920             :     : Impl(make_unique<RuntimeDyldCheckerImpl>(RTDyld, Disassembler,
     921          72 :                                                InstPrinter, ErrStream)) {}
     922             : 
     923          72 : RuntimeDyldChecker::~RuntimeDyldChecker() {}
     924             : 
     925         130 : RuntimeDyld& RuntimeDyldChecker::getRTDyld() {
     926         260 :   return Impl->RTDyld;
     927             : }
     928             : 
     929           0 : const RuntimeDyld& RuntimeDyldChecker::getRTDyld() const {
     930           0 :   return Impl->RTDyld;
     931             : }
     932             : 
     933           0 : bool RuntimeDyldChecker::check(StringRef CheckExpr) const {
     934           0 :   return Impl->check(CheckExpr);
     935             : }
     936             : 
     937          27 : bool RuntimeDyldChecker::checkAllRulesInBuffer(StringRef RulePrefix,
     938             :                                                MemoryBuffer *MemBuf) const {
     939          54 :   return Impl->checkAllRulesInBuffer(RulePrefix, MemBuf);
     940             : }
     941             : 
     942             : std::pair<uint64_t, std::string>
     943          34 : RuntimeDyldChecker::getSectionAddr(StringRef FileName, StringRef SectionName,
     944             :                                    bool LocalAddress) {
     945          68 :   return Impl->getSectionAddr(FileName, SectionName, LocalAddress);
     946             : }
     947             : 
     948             : Optional<uint64_t>
     949         147 : RuntimeDyldChecker::getSectionLoadAddress(void *LocalAddress) const {
     950         294 :   return Impl->getSectionLoadAddress(LocalAddress);
     951             : }

Generated by: LCOV version 1.13