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