brintos

brintos / llvm-project-archived public Read only

0
0
Text · 38.6 KiB · afe3b67 Raw
1058 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ExecutionEngine/RuntimeDyldChecker.h"10#include "RuntimeDyldCheckerImpl.h"11#include "llvm/ADT/StringExtras.h"12#include "llvm/MC/MCAsmInfo.h"13#include "llvm/MC/MCContext.h"14#include "llvm/MC/MCDisassembler/MCDisassembler.h"15#include "llvm/MC/MCInst.h"16#include "llvm/MC/MCInstPrinter.h"17#include "llvm/MC/MCInstrInfo.h"18#include "llvm/MC/MCRegisterInfo.h"19#include "llvm/MC/MCSubtargetInfo.h"20#include "llvm/MC/MCTargetOptions.h"21#include "llvm/MC/TargetRegistry.h"22#include "llvm/Support/Endian.h"23#include "llvm/Support/MemoryBuffer.h"24#include <cctype>25#include <memory>26#include <utility>27 28#define DEBUG_TYPE "rtdyld"29 30using namespace llvm;31 32namespace {33struct TargetInfo {34  const Target *TheTarget;35  std::unique_ptr<MCSubtargetInfo> STI;36  std::unique_ptr<MCRegisterInfo> MRI;37  std::unique_ptr<MCAsmInfo> MAI;38  std::unique_ptr<MCContext> Ctx;39  std::unique_ptr<MCDisassembler> Disassembler;40  std::unique_ptr<MCInstrInfo> MII;41  std::unique_ptr<MCInstPrinter> InstPrinter;42};43} // anonymous namespace44 45namespace llvm {46 47// Helper class that implements the language evaluated by RuntimeDyldChecker.48class RuntimeDyldCheckerExprEval {49public:50  RuntimeDyldCheckerExprEval(const RuntimeDyldCheckerImpl &Checker,51                             raw_ostream &ErrStream)52      : Checker(Checker) {}53 54  bool evaluate(StringRef Expr) const {55    // Expect equality expression of the form 'LHS = RHS'.56    Expr = Expr.trim();57    size_t EQIdx = Expr.find('=');58 59    ParseContext OutsideLoad(false);60 61    // Evaluate LHS.62    StringRef LHSExpr = Expr.substr(0, EQIdx).rtrim();63    StringRef RemainingExpr;64    EvalResult LHSResult;65    std::tie(LHSResult, RemainingExpr) =66        evalComplexExpr(evalSimpleExpr(LHSExpr, OutsideLoad), OutsideLoad);67    if (LHSResult.hasError())68      return handleError(Expr, LHSResult);69    if (RemainingExpr != "")70      return handleError(Expr, unexpectedToken(RemainingExpr, LHSExpr, ""));71 72    // Evaluate RHS.73    StringRef RHSExpr = Expr.substr(EQIdx + 1).ltrim();74    EvalResult RHSResult;75    std::tie(RHSResult, RemainingExpr) =76        evalComplexExpr(evalSimpleExpr(RHSExpr, OutsideLoad), OutsideLoad);77    if (RHSResult.hasError())78      return handleError(Expr, RHSResult);79    if (RemainingExpr != "")80      return handleError(Expr, unexpectedToken(RemainingExpr, RHSExpr, ""));81 82    if (LHSResult.getValue() != RHSResult.getValue()) {83      Checker.ErrStream << "Expression '" << Expr << "' is false: "84                        << format("0x%" PRIx64, LHSResult.getValue())85                        << " != " << format("0x%" PRIx64, RHSResult.getValue())86                        << "\n";87      return false;88    }89    return true;90  }91 92private:93  // RuntimeDyldCheckerExprEval requires some context when parsing exprs. In94  // particular, it needs to know whether a symbol is being evaluated in the95  // context of a load, in which case we want the linker's local address for96  // the symbol, or outside of a load, in which case we want the symbol's97  // address in the remote target.98 99  struct ParseContext {100    bool IsInsideLoad;101    ParseContext(bool IsInsideLoad) : IsInsideLoad(IsInsideLoad) {}102  };103 104  const RuntimeDyldCheckerImpl &Checker;105 106  enum class BinOpToken : unsigned {107    Invalid,108    Add,109    Sub,110    BitwiseAnd,111    BitwiseOr,112    ShiftLeft,113    ShiftRight114  };115 116  class EvalResult {117  public:118    EvalResult() : Value(0) {}119    EvalResult(uint64_t Value) : Value(Value) {}120    EvalResult(std::string ErrorMsg)121        : Value(0), ErrorMsg(std::move(ErrorMsg)) {}122    uint64_t getValue() const { return Value; }123    bool hasError() const { return ErrorMsg != ""; }124    const std::string &getErrorMsg() const { return ErrorMsg; }125 126  private:127    uint64_t Value;128    std::string ErrorMsg;129  };130 131  StringRef getTokenForError(StringRef Expr) const {132    if (Expr.empty())133      return "";134 135    StringRef Token, Remaining;136    if (isalpha(Expr[0]))137      std::tie(Token, Remaining) = parseSymbol(Expr);138    else if (isdigit(Expr[0]))139      std::tie(Token, Remaining) = parseNumberString(Expr);140    else {141      unsigned TokLen = 1;142      if (Expr.starts_with("<<") || Expr.starts_with(">>"))143        TokLen = 2;144      Token = Expr.substr(0, TokLen);145    }146    return Token;147  }148 149  EvalResult unexpectedToken(StringRef TokenStart, StringRef SubExpr,150                             StringRef ErrText) const {151    std::string ErrorMsg("Encountered unexpected token '");152    ErrorMsg += getTokenForError(TokenStart);153    if (SubExpr != "") {154      ErrorMsg += "' while parsing subexpression '";155      ErrorMsg += SubExpr;156    }157    ErrorMsg += "'";158    if (ErrText != "") {159      ErrorMsg += " ";160      ErrorMsg += ErrText;161    }162    return EvalResult(std::move(ErrorMsg));163  }164 165  bool handleError(StringRef Expr, const EvalResult &R) const {166    assert(R.hasError() && "Not an error result.");167    Checker.ErrStream << "Error evaluating expression '" << Expr168                      << "': " << R.getErrorMsg() << "\n";169    return false;170  }171 172  std::pair<BinOpToken, StringRef> parseBinOpToken(StringRef Expr) const {173    if (Expr.empty())174      return std::make_pair(BinOpToken::Invalid, "");175 176    // Handle the two 2-character tokens.177    if (Expr.starts_with("<<"))178      return std::make_pair(BinOpToken::ShiftLeft, Expr.substr(2).ltrim());179    if (Expr.starts_with(">>"))180      return std::make_pair(BinOpToken::ShiftRight, Expr.substr(2).ltrim());181 182    // Handle one-character tokens.183    BinOpToken Op;184    switch (Expr[0]) {185    default:186      return std::make_pair(BinOpToken::Invalid, Expr);187    case '+':188      Op = BinOpToken::Add;189      break;190    case '-':191      Op = BinOpToken::Sub;192      break;193    case '&':194      Op = BinOpToken::BitwiseAnd;195      break;196    case '|':197      Op = BinOpToken::BitwiseOr;198      break;199    }200 201    return std::make_pair(Op, Expr.substr(1).ltrim());202  }203 204  EvalResult computeBinOpResult(BinOpToken Op, const EvalResult &LHSResult,205                                const EvalResult &RHSResult) const {206    switch (Op) {207    default:208      llvm_unreachable("Tried to evaluate unrecognized operation.");209    case BinOpToken::Add:210      return EvalResult(LHSResult.getValue() + RHSResult.getValue());211    case BinOpToken::Sub:212      return EvalResult(LHSResult.getValue() - RHSResult.getValue());213    case BinOpToken::BitwiseAnd:214      return EvalResult(LHSResult.getValue() & RHSResult.getValue());215    case BinOpToken::BitwiseOr:216      return EvalResult(LHSResult.getValue() | RHSResult.getValue());217    case BinOpToken::ShiftLeft:218      return EvalResult(LHSResult.getValue() << RHSResult.getValue());219    case BinOpToken::ShiftRight:220      return EvalResult(LHSResult.getValue() >> RHSResult.getValue());221    }222  }223 224  // Parse a symbol and return a (string, string) pair representing the symbol225  // name and expression remaining to be parsed.226  std::pair<StringRef, StringRef> parseSymbol(StringRef Expr) const {227    size_t FirstNonSymbol = Expr.find_first_not_of("0123456789"228                                                   "abcdefghijklmnopqrstuvwxyz"229                                                   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"230                                                   ":_.$");231    return std::make_pair(Expr.substr(0, FirstNonSymbol),232                          Expr.substr(FirstNonSymbol).ltrim());233  }234 235  // Evaluate a call to decode_operand. Decode the instruction operand at the236  // given symbol and get the value of the requested operand.237  // Returns an error if the instruction cannot be decoded, or the requested238  // operand is not an immediate.239  // On success, returns a pair containing the value of the operand, plus240  // the expression remaining to be evaluated.241  std::pair<EvalResult, StringRef> evalDecodeOperand(StringRef Expr) const {242    if (!Expr.starts_with("("))243      return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");244    StringRef RemainingExpr = Expr.substr(1).ltrim();245    StringRef Symbol;246    std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);247 248    if (!Checker.isSymbolValid(Symbol))249      return std::make_pair(250          EvalResult(("Cannot decode unknown symbol '" + Symbol + "'").str()),251          "");252 253    // if there is an offset number expr254    int64_t Offset = 0;255    BinOpToken BinOp;256    std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr);257    switch (BinOp) {258    case BinOpToken::Add: {259      EvalResult Number;260      std::tie(Number, RemainingExpr) = evalNumberExpr(RemainingExpr);261      Offset = Number.getValue();262      break;263    }264    case BinOpToken::Invalid:265      break;266    default:267      return std::make_pair(268          unexpectedToken(RemainingExpr, RemainingExpr,269                          "expected '+' for offset or ',' if no offset"),270          "");271    }272 273    if (!RemainingExpr.starts_with(","))274      return std::make_pair(275          unexpectedToken(RemainingExpr, RemainingExpr, "expected ','"), "");276    RemainingExpr = RemainingExpr.substr(1).ltrim();277 278    EvalResult OpIdxExpr;279    std::tie(OpIdxExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);280    if (OpIdxExpr.hasError())281      return std::make_pair(OpIdxExpr, "");282 283    if (!RemainingExpr.starts_with(")"))284      return std::make_pair(285          unexpectedToken(RemainingExpr, RemainingExpr, "expected ')'"), "");286    RemainingExpr = RemainingExpr.substr(1).ltrim();287 288    MCInst Inst;289    uint64_t Size;290    if (!decodeInst(Symbol, Inst, Size, Offset))291      return std::make_pair(292          EvalResult(("Couldn't decode instruction at '" + Symbol + "'").str()),293          "");294 295    unsigned OpIdx = OpIdxExpr.getValue();296 297    auto printInst = [this](StringRef Symbol, MCInst Inst,298                            raw_string_ostream &ErrMsgStream) {299      auto TT = Checker.getTripleForSymbol(Checker.getTargetFlag(Symbol));300      auto TI = getTargetInfo(TT, Checker.getCPU(), Checker.getFeatures());301      if (auto E = TI.takeError()) {302        errs() << "Error obtaining instruction printer: "303               << toString(std::move(E)) << "\n";304        return;305      }306      Inst.dump_pretty(ErrMsgStream, TI->InstPrinter.get());307      return;308    };309 310    if (OpIdx >= Inst.getNumOperands()) {311      std::string ErrMsg;312      raw_string_ostream ErrMsgStream(ErrMsg);313      ErrMsgStream << "Invalid operand index '" << format("%i", OpIdx)314                   << "' for instruction '" << Symbol315                   << "'. Instruction has only "316                   << format("%i", Inst.getNumOperands())317                   << " operands.\nInstruction is:\n  ";318 319      printInst(Symbol, Inst, ErrMsgStream);320      return {EvalResult(std::move(ErrMsg)), ""};321    }322 323    const MCOperand &Op = Inst.getOperand(OpIdx);324    if (!Op.isImm()) {325      std::string ErrMsg;326      raw_string_ostream ErrMsgStream(ErrMsg);327      ErrMsgStream << "Operand '" << format("%i", OpIdx) << "' of instruction '"328                   << Symbol << "' is not an immediate.\nInstruction is:\n  ";329 330      printInst(Symbol, Inst, ErrMsgStream);331      return {EvalResult(std::move(ErrMsg)), ""};332    }333 334    return std::make_pair(EvalResult(Op.getImm()), RemainingExpr);335  }336 337  // Evaluate a call to next_pc.338  // Decode the instruction at the given symbol and return the following program339  // counter.340  // Returns an error if the instruction cannot be decoded.341  // On success, returns a pair containing the next PC, plus of the342  // expression remaining to be evaluated.343  std::pair<EvalResult, StringRef> evalNextPC(StringRef Expr,344                                              ParseContext PCtx) const {345    if (!Expr.starts_with("("))346      return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");347    StringRef RemainingExpr = Expr.substr(1).ltrim();348    StringRef Symbol;349    std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);350 351    if (!Checker.isSymbolValid(Symbol))352      return std::make_pair(353          EvalResult(("Cannot decode unknown symbol '" + Symbol + "'").str()),354          "");355 356    if (!RemainingExpr.starts_with(")"))357      return std::make_pair(358          unexpectedToken(RemainingExpr, RemainingExpr, "expected ')'"), "");359    RemainingExpr = RemainingExpr.substr(1).ltrim();360 361    MCInst Inst;362    uint64_t InstSize;363    if (!decodeInst(Symbol, Inst, InstSize, 0))364      return std::make_pair(365          EvalResult(("Couldn't decode instruction at '" + Symbol + "'").str()),366          "");367 368    uint64_t SymbolAddr = PCtx.IsInsideLoad369                              ? Checker.getSymbolLocalAddr(Symbol)370                              : Checker.getSymbolRemoteAddr(Symbol);371 372    // ARM PC offset is 8 instead of 4, because it accounts for an additional373    // prefetch instruction that increments PC even though it is implicit.374    auto TT = Checker.getTripleForSymbol(Checker.getTargetFlag(Symbol));375    uint64_t PCOffset = TT.getArch() == Triple::ArchType::arm ? 4 : 0;376 377    uint64_t NextPC = SymbolAddr + InstSize + PCOffset;378 379    return std::make_pair(EvalResult(NextPC), RemainingExpr);380  }381 382  // Evaluate a call to stub_addr/got_addr.383  // Look up and return the address of the stub for the given384  // (<file name>, <section name>, <symbol name>) tuple.385  // On success, returns a pair containing the stub address, plus the expression386  // remaining to be evaluated.387  std::pair<EvalResult, StringRef>388  evalStubOrGOTAddr(StringRef Expr, ParseContext PCtx, bool IsStubAddr) const {389    if (!Expr.starts_with("("))390      return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");391    StringRef RemainingExpr = Expr.substr(1).ltrim();392 393    // Handle file-name specially, as it may contain characters that aren't394    // legal for symbols.395    StringRef StubContainerName;396    size_t ComaIdx = RemainingExpr.find(',');397    StubContainerName = RemainingExpr.substr(0, ComaIdx).rtrim();398    RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim();399 400    if (!RemainingExpr.starts_with(","))401      return std::make_pair(402          unexpectedToken(RemainingExpr, Expr, "expected ','"), "");403    RemainingExpr = RemainingExpr.substr(1).ltrim();404 405    StringRef Symbol;406    std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);407 408    // Parse optional parameter to filter by stub kind409    StringRef KindNameFilter;410    if (RemainingExpr.starts_with(",")) {411      RemainingExpr = RemainingExpr.substr(1).ltrim();412      size_t ClosingBracket = RemainingExpr.find(")");413      KindNameFilter = RemainingExpr.substr(0, ClosingBracket);414      RemainingExpr = RemainingExpr.substr(ClosingBracket);415    }416 417    if (!RemainingExpr.starts_with(")"))418      return std::make_pair(419          unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");420    RemainingExpr = RemainingExpr.substr(1).ltrim();421 422    uint64_t StubAddr;423    std::string ErrorMsg;424    std::tie(StubAddr, ErrorMsg) =425        Checker.getStubOrGOTAddrFor(StubContainerName, Symbol, KindNameFilter,426                                    PCtx.IsInsideLoad, IsStubAddr);427 428    if (ErrorMsg != "")429      return std::make_pair(EvalResult(ErrorMsg), "");430 431    return std::make_pair(EvalResult(StubAddr), RemainingExpr);432  }433 434  std::pair<EvalResult, StringRef> evalSectionAddr(StringRef Expr,435                                                   ParseContext PCtx) const {436    if (!Expr.starts_with("("))437      return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");438    StringRef RemainingExpr = Expr.substr(1).ltrim();439 440    // Handle file-name specially, as it may contain characters that aren't441    // legal for symbols.442    StringRef FileName;443    size_t ComaIdx = RemainingExpr.find(',');444    FileName = RemainingExpr.substr(0, ComaIdx).rtrim();445    RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim();446 447    if (!RemainingExpr.starts_with(","))448      return std::make_pair(449          unexpectedToken(RemainingExpr, Expr, "expected ','"), "");450    RemainingExpr = RemainingExpr.substr(1).ltrim();451 452    StringRef SectionName;453    size_t CloseParensIdx = RemainingExpr.find(')');454    SectionName = RemainingExpr.substr(0, CloseParensIdx).rtrim();455    RemainingExpr = RemainingExpr.substr(CloseParensIdx).ltrim();456 457    if (!RemainingExpr.starts_with(")"))458      return std::make_pair(459          unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");460    RemainingExpr = RemainingExpr.substr(1).ltrim();461 462    uint64_t StubAddr;463    std::string ErrorMsg;464    std::tie(StubAddr, ErrorMsg) = Checker.getSectionAddr(465        FileName, SectionName, PCtx.IsInsideLoad);466 467    if (ErrorMsg != "")468      return std::make_pair(EvalResult(ErrorMsg), "");469 470    return std::make_pair(EvalResult(StubAddr), RemainingExpr);471  }472 473  // Evaluate an identifier expr, which may be a symbol, or a call to474  // one of the builtin functions: get_insn_opcode or get_insn_length.475  // Return the result, plus the expression remaining to be parsed.476  std::pair<EvalResult, StringRef> evalIdentifierExpr(StringRef Expr,477                                                      ParseContext PCtx) const {478    StringRef Symbol;479    StringRef RemainingExpr;480    std::tie(Symbol, RemainingExpr) = parseSymbol(Expr);481 482    // Check for builtin function calls.483    if (Symbol == "decode_operand")484      return evalDecodeOperand(RemainingExpr);485    else if (Symbol == "next_pc")486      return evalNextPC(RemainingExpr, PCtx);487    else if (Symbol == "stub_addr")488      return evalStubOrGOTAddr(RemainingExpr, PCtx, true);489    else if (Symbol == "got_addr")490      return evalStubOrGOTAddr(RemainingExpr, PCtx, false);491    else if (Symbol == "section_addr")492      return evalSectionAddr(RemainingExpr, PCtx);493 494    if (!Checker.isSymbolValid(Symbol)) {495      std::string ErrMsg("No known address for symbol '");496      ErrMsg += Symbol;497      ErrMsg += "'";498      if (Symbol.starts_with("L"))499        ErrMsg += " (this appears to be an assembler local label - "500                  " perhaps drop the 'L'?)";501 502      return std::make_pair(EvalResult(ErrMsg), "");503    }504 505    // The value for the symbol depends on the context we're evaluating in:506    // Inside a load this is the address in the linker's memory, outside a507    // load it's the address in the target processes memory.508    uint64_t Value = PCtx.IsInsideLoad ? Checker.getSymbolLocalAddr(Symbol)509                                       : Checker.getSymbolRemoteAddr(Symbol);510 511    // Looks like a plain symbol reference.512    return std::make_pair(EvalResult(Value), RemainingExpr);513  }514 515  // Parse a number (hexadecimal or decimal) and return a (string, string)516  // pair representing the number and the expression remaining to be parsed.517  std::pair<StringRef, StringRef> parseNumberString(StringRef Expr) const {518    size_t FirstNonDigit = StringRef::npos;519    if (Expr.starts_with("0x")) {520      FirstNonDigit = Expr.find_first_not_of("0123456789abcdefABCDEF", 2);521      if (FirstNonDigit == StringRef::npos)522        FirstNonDigit = Expr.size();523    } else {524      FirstNonDigit = Expr.find_first_not_of("0123456789");525      if (FirstNonDigit == StringRef::npos)526        FirstNonDigit = Expr.size();527    }528    return std::make_pair(Expr.substr(0, FirstNonDigit),529                          Expr.substr(FirstNonDigit));530  }531 532  // Evaluate a constant numeric expression (hexadecimal or decimal) and533  // return a pair containing the result, and the expression remaining to be534  // evaluated.535  std::pair<EvalResult, StringRef> evalNumberExpr(StringRef Expr) const {536    StringRef ValueStr;537    StringRef RemainingExpr;538    std::tie(ValueStr, RemainingExpr) = parseNumberString(Expr);539 540    if (ValueStr.empty() || !isdigit(ValueStr[0]))541      return std::make_pair(542          unexpectedToken(RemainingExpr, RemainingExpr, "expected number"), "");543    uint64_t Value;544    ValueStr.getAsInteger(0, Value);545    return std::make_pair(EvalResult(Value), RemainingExpr);546  }547 548  // Evaluate an expression of the form "(<expr>)" and return a pair549  // containing the result of evaluating <expr>, plus the expression550  // remaining to be parsed.551  std::pair<EvalResult, StringRef> evalParensExpr(StringRef Expr,552                                                  ParseContext PCtx) const {553    assert(Expr.starts_with("(") && "Not a parenthesized expression");554    EvalResult SubExprResult;555    StringRef RemainingExpr;556    std::tie(SubExprResult, RemainingExpr) =557        evalComplexExpr(evalSimpleExpr(Expr.substr(1).ltrim(), PCtx), PCtx);558    if (SubExprResult.hasError())559      return std::make_pair(SubExprResult, "");560    if (!RemainingExpr.starts_with(")"))561      return std::make_pair(562          unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");563    RemainingExpr = RemainingExpr.substr(1).ltrim();564    return std::make_pair(SubExprResult, RemainingExpr);565  }566 567  // Evaluate an expression in one of the following forms:568  //   *{<number>}<expr>569  // Return a pair containing the result, plus the expression remaining to be570  // parsed.571  std::pair<EvalResult, StringRef> evalLoadExpr(StringRef Expr) const {572    assert(Expr.starts_with("*") && "Not a load expression");573    StringRef RemainingExpr = Expr.substr(1).ltrim();574 575    // Parse read size.576    if (!RemainingExpr.starts_with("{"))577      return std::make_pair(EvalResult("Expected '{' following '*'."), "");578    RemainingExpr = RemainingExpr.substr(1).ltrim();579    EvalResult ReadSizeExpr;580    std::tie(ReadSizeExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);581    if (ReadSizeExpr.hasError())582      return std::make_pair(ReadSizeExpr, RemainingExpr);583    uint64_t ReadSize = ReadSizeExpr.getValue();584    if (ReadSize < 1 || ReadSize > 8)585      return std::make_pair(EvalResult("Invalid size for dereference."), "");586    if (!RemainingExpr.starts_with("}"))587      return std::make_pair(EvalResult("Missing '}' for dereference."), "");588    RemainingExpr = RemainingExpr.substr(1).ltrim();589 590    // Evaluate the expression representing the load address.591    ParseContext LoadCtx(true);592    EvalResult LoadAddrExprResult;593    std::tie(LoadAddrExprResult, RemainingExpr) =594        evalComplexExpr(evalSimpleExpr(RemainingExpr, LoadCtx), LoadCtx);595 596    if (LoadAddrExprResult.hasError())597      return std::make_pair(LoadAddrExprResult, "");598 599    uint64_t LoadAddr = LoadAddrExprResult.getValue();600 601    // If there is no error but the content pointer is null then this is a602    // zero-fill symbol/section.603    if (LoadAddr == 0)604      return std::make_pair(0, RemainingExpr);605 606    return std::make_pair(607        EvalResult(Checker.readMemoryAtAddr(LoadAddr, ReadSize)),608        RemainingExpr);609  }610 611  // Evaluate a "simple" expression. This is any expression that _isn't_ an612  // un-parenthesized binary expression.613  //614  // "Simple" expressions can be optionally bit-sliced. See evalSlicedExpr.615  //616  // Returns a pair containing the result of the evaluation, plus the617  // expression remaining to be parsed.618  std::pair<EvalResult, StringRef> evalSimpleExpr(StringRef Expr,619                                                  ParseContext PCtx) const {620    EvalResult SubExprResult;621    StringRef RemainingExpr;622 623    if (Expr.empty())624      return std::make_pair(EvalResult("Unexpected end of expression"), "");625 626    if (Expr[0] == '(')627      std::tie(SubExprResult, RemainingExpr) = evalParensExpr(Expr, PCtx);628    else if (Expr[0] == '*')629      std::tie(SubExprResult, RemainingExpr) = evalLoadExpr(Expr);630    else if (isalpha(Expr[0]) || Expr[0] == '_')631      std::tie(SubExprResult, RemainingExpr) = evalIdentifierExpr(Expr, PCtx);632    else if (isdigit(Expr[0]))633      std::tie(SubExprResult, RemainingExpr) = evalNumberExpr(Expr);634    else635      return std::make_pair(636          unexpectedToken(Expr, Expr,637                          "expected '(', '*', identifier, or number"), "");638 639    if (SubExprResult.hasError())640      return std::make_pair(SubExprResult, RemainingExpr);641 642    // Evaluate bit-slice if present.643    if (RemainingExpr.starts_with("["))644      std::tie(SubExprResult, RemainingExpr) =645          evalSliceExpr(std::make_pair(SubExprResult, RemainingExpr));646 647    return std::make_pair(SubExprResult, RemainingExpr);648  }649 650  // Evaluate a bit-slice of an expression.651  // A bit-slice has the form "<expr>[high:low]". The result of evaluating a652  // slice is the bits between high and low (inclusive) in the original653  // expression, right shifted so that the "low" bit is in position 0 in the654  // result.655  // Returns a pair containing the result of the slice operation, plus the656  // expression remaining to be parsed.657  std::pair<EvalResult, StringRef>658  evalSliceExpr(const std::pair<EvalResult, StringRef> &Ctx) const {659    EvalResult SubExprResult;660    StringRef RemainingExpr;661    std::tie(SubExprResult, RemainingExpr) = Ctx;662 663    assert(RemainingExpr.starts_with("[") && "Not a slice expr.");664    RemainingExpr = RemainingExpr.substr(1).ltrim();665 666    EvalResult HighBitExpr;667    std::tie(HighBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);668 669    if (HighBitExpr.hasError())670      return std::make_pair(HighBitExpr, RemainingExpr);671 672    if (!RemainingExpr.starts_with(":"))673      return std::make_pair(674          unexpectedToken(RemainingExpr, RemainingExpr, "expected ':'"), "");675    RemainingExpr = RemainingExpr.substr(1).ltrim();676 677    EvalResult LowBitExpr;678    std::tie(LowBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);679 680    if (LowBitExpr.hasError())681      return std::make_pair(LowBitExpr, RemainingExpr);682 683    if (!RemainingExpr.starts_with("]"))684      return std::make_pair(685          unexpectedToken(RemainingExpr, RemainingExpr, "expected ']'"), "");686    RemainingExpr = RemainingExpr.substr(1).ltrim();687 688    unsigned HighBit = HighBitExpr.getValue();689    unsigned LowBit = LowBitExpr.getValue();690    uint64_t Mask = ((uint64_t)1 << (HighBit - LowBit + 1)) - 1;691    uint64_t SlicedValue = (SubExprResult.getValue() >> LowBit) & Mask;692    return std::make_pair(EvalResult(SlicedValue), RemainingExpr);693  }694 695  // Evaluate a "complex" expression.696  // Takes an already evaluated subexpression and checks for the presence of a697  // binary operator, computing the result of the binary operation if one is698  // found. Used to make arithmetic expressions left-associative.699  // Returns a pair containing the ultimate result of evaluating the700  // expression, plus the expression remaining to be evaluated.701  std::pair<EvalResult, StringRef>702  evalComplexExpr(const std::pair<EvalResult, StringRef> &LHSAndRemaining,703                  ParseContext PCtx) const {704    EvalResult LHSResult;705    StringRef RemainingExpr;706    std::tie(LHSResult, RemainingExpr) = LHSAndRemaining;707 708    // If there was an error, or there's nothing left to evaluate, return the709    // result.710    if (LHSResult.hasError() || RemainingExpr == "")711      return std::make_pair(LHSResult, RemainingExpr);712 713    // Otherwise check if this is a binary expression.714    BinOpToken BinOp;715    std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr);716 717    // If this isn't a recognized expression just return.718    if (BinOp == BinOpToken::Invalid)719      return std::make_pair(LHSResult, RemainingExpr);720 721    // This is a recognized bin-op. Evaluate the RHS, then evaluate the binop.722    EvalResult RHSResult;723    std::tie(RHSResult, RemainingExpr) = evalSimpleExpr(RemainingExpr, PCtx);724 725    // If there was an error evaluating the RHS, return it.726    if (RHSResult.hasError())727      return std::make_pair(RHSResult, RemainingExpr);728 729    // This is a binary expression - evaluate and try to continue as a730    // complex expr.731    EvalResult ThisResult(computeBinOpResult(BinOp, LHSResult, RHSResult));732 733    return evalComplexExpr(std::make_pair(ThisResult, RemainingExpr), PCtx);734  }735 736  bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size,737                  int64_t Offset) const {738    auto TT = Checker.getTripleForSymbol(Checker.getTargetFlag(Symbol));739    auto TI = getTargetInfo(TT, Checker.getCPU(), Checker.getFeatures());740 741    if (auto E = TI.takeError()) {742      errs() << "Error obtaining disassembler: " << toString(std::move(E))743             << "\n";744      return false;745    }746 747    StringRef SymbolMem = Checker.getSymbolContent(Symbol);748    ArrayRef<uint8_t> SymbolBytes(SymbolMem.bytes_begin() + Offset,749                                  SymbolMem.size() - Offset);750 751    MCDisassembler::DecodeStatus S =752        TI->Disassembler->getInstruction(Inst, Size, SymbolBytes, 0, nulls());753 754    return (S == MCDisassembler::Success);755  }756 757  Expected<TargetInfo> getTargetInfo(const Triple &TT, const StringRef &CPU,758                                     const SubtargetFeatures &TF) const {759    std::string ErrorStr;760    const Target *TheTarget = TargetRegistry::lookupTarget(TT, ErrorStr);761    if (!TheTarget)762      return make_error<StringError>("Error accessing target '" + TT.str() +763                                         "': " + ErrorStr,764                                     inconvertibleErrorCode());765 766    std::unique_ptr<MCSubtargetInfo> STI(767        TheTarget->createMCSubtargetInfo(TT, CPU, TF.getString()));768    if (!STI)769      return make_error<StringError>("Unable to create subtarget for " +770                                         TT.str(),771                                     inconvertibleErrorCode());772 773    std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));774    if (!MRI)775      return make_error<StringError>("Unable to create target register info "776                                     "for " +777                                         TT.str(),778                                     inconvertibleErrorCode());779 780    MCTargetOptions MCOptions;781    std::unique_ptr<MCAsmInfo> MAI(782        TheTarget->createMCAsmInfo(*MRI, TT, MCOptions));783    if (!MAI)784      return make_error<StringError>("Unable to create target asm info " +785                                         TT.str(),786                                     inconvertibleErrorCode());787 788    auto Ctx = std::make_unique<MCContext>(Triple(TT.str()), MAI.get(),789                                           MRI.get(), STI.get());790 791    std::unique_ptr<MCDisassembler> Disassembler(792        TheTarget->createMCDisassembler(*STI, *Ctx));793    if (!Disassembler)794      return make_error<StringError>("Unable to create disassembler for " +795                                         TT.str(),796                                     inconvertibleErrorCode());797 798    std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());799    if (!MII)800      return make_error<StringError>("Unable to create instruction info for" +801                                         TT.str(),802                                     inconvertibleErrorCode());803 804    std::unique_ptr<MCInstPrinter> InstPrinter(805        TheTarget->createMCInstPrinter(TT, 0, *MAI, *MII, *MRI));806    if (!InstPrinter)807      return make_error<StringError>(808          "Unable to create instruction printer for" + TT.str(),809          inconvertibleErrorCode());810 811    return TargetInfo({TheTarget, std::move(STI), std::move(MRI),812                       std::move(MAI), std::move(Ctx), std::move(Disassembler),813                       std::move(MII), std::move(InstPrinter)});814  }815};816} // namespace llvm817 818RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl(819    IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,820    GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,821    GetGOTInfoFunction GetGOTInfo, llvm::endianness Endianness, Triple TT,822    StringRef CPU, SubtargetFeatures TF, raw_ostream &ErrStream)823    : IsSymbolValid(std::move(IsSymbolValid)),824      GetSymbolInfo(std::move(GetSymbolInfo)),825      GetSectionInfo(std::move(GetSectionInfo)),826      GetStubInfo(std::move(GetStubInfo)), GetGOTInfo(std::move(GetGOTInfo)),827      Endianness(Endianness), TT(std::move(TT)), CPU(std::move(CPU)),828      TF(std::move(TF)), ErrStream(ErrStream) {}829 830bool RuntimeDyldCheckerImpl::check(StringRef CheckExpr) const {831  CheckExpr = CheckExpr.trim();832  LLVM_DEBUG(dbgs() << "RuntimeDyldChecker: Checking '" << CheckExpr833                    << "'...\n");834  RuntimeDyldCheckerExprEval P(*this, ErrStream);835  bool Result = P.evaluate(CheckExpr);836  (void)Result;837  LLVM_DEBUG(dbgs() << "RuntimeDyldChecker: '" << CheckExpr << "' "838                    << (Result ? "passed" : "FAILED") << ".\n");839  return Result;840}841 842bool RuntimeDyldCheckerImpl::checkAllRulesInBuffer(StringRef RulePrefix,843                                                   MemoryBuffer *MemBuf) const {844  bool DidAllTestsPass = true;845  unsigned NumRules = 0;846 847  std::string CheckExpr;848  const char *LineStart = MemBuf->getBufferStart();849 850  // Eat whitespace.851  while (LineStart != MemBuf->getBufferEnd() && isSpace(*LineStart))852    ++LineStart;853 854  while (LineStart != MemBuf->getBufferEnd() && *LineStart != '\0') {855    const char *LineEnd = LineStart;856    while (LineEnd != MemBuf->getBufferEnd() && *LineEnd != '\r' &&857           *LineEnd != '\n')858      ++LineEnd;859 860    StringRef Line(LineStart, LineEnd - LineStart);861    if (Line.starts_with(RulePrefix))862      CheckExpr += Line.substr(RulePrefix.size()).str();863 864    // If there's a check expr string...865    if (!CheckExpr.empty()) {866      // ... and it's complete then run it, otherwise remove the trailer '\'.867      if (CheckExpr.back() != '\\') {868        DidAllTestsPass &= check(CheckExpr);869        CheckExpr.clear();870        ++NumRules;871      } else872        CheckExpr.pop_back();873    }874 875    // Eat whitespace.876    LineStart = LineEnd;877    while (LineStart != MemBuf->getBufferEnd() && isSpace(*LineStart))878      ++LineStart;879  }880  return DidAllTestsPass && (NumRules != 0);881}882 883bool RuntimeDyldCheckerImpl::isSymbolValid(StringRef Symbol) const {884  return IsSymbolValid(Symbol);885}886 887uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const {888  auto SymInfo = GetSymbolInfo(Symbol);889  if (!SymInfo) {890    logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");891    return 0;892  }893 894  if (SymInfo->isZeroFill())895    return 0;896 897  return static_cast<uint64_t>(898      reinterpret_cast<uintptr_t>(SymInfo->getContent().data()));899}900 901uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const {902  auto SymInfo = GetSymbolInfo(Symbol);903  if (!SymInfo) {904    logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");905    return 0;906  }907 908  return SymInfo->getTargetAddress();909}910 911uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr,912                                                  unsigned Size) const {913  uintptr_t PtrSizedAddr = static_cast<uintptr_t>(SrcAddr);914  assert(PtrSizedAddr == SrcAddr && "Linker memory pointer out-of-range.");915  void *Ptr = reinterpret_cast<void*>(PtrSizedAddr);916 917  switch (Size) {918  case 1:919    return support::endian::read<uint8_t>(Ptr, Endianness);920  case 2:921    return support::endian::read<uint16_t>(Ptr, Endianness);922  case 4:923    return support::endian::read<uint32_t>(Ptr, Endianness);924  case 8:925    return support::endian::read<uint64_t>(Ptr, Endianness);926  }927  llvm_unreachable("Unsupported read size");928}929 930StringRef RuntimeDyldCheckerImpl::getSymbolContent(StringRef Symbol) const {931  auto SymInfo = GetSymbolInfo(Symbol);932  if (!SymInfo) {933    logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");934    return StringRef();935  }936  return {SymInfo->getContent().data(), SymInfo->getContent().size()};937}938 939TargetFlagsType RuntimeDyldCheckerImpl::getTargetFlag(StringRef Symbol) const {940  auto SymInfo = GetSymbolInfo(Symbol);941  if (!SymInfo) {942    logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");943    return TargetFlagsType{};944  }945  return SymInfo->getTargetFlags();946}947 948Triple949RuntimeDyldCheckerImpl::getTripleForSymbol(TargetFlagsType Flag) const {950  Triple TheTriple = TT;951 952  switch (TT.getArch()) {953  case Triple::ArchType::arm:954    if (~Flag & 0x1)955      return TT;956    TheTriple.setArchName((Twine("thumb") + TT.getArchName().substr(3)).str());957    return TheTriple;958  case Triple::ArchType::thumb:959    if (Flag & 0x1)960      return TT;961    TheTriple.setArchName((Twine("arm") + TT.getArchName().substr(5)).str());962    return TheTriple;963 964  default:965    return TT;966  }967}968 969std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getSectionAddr(970    StringRef FileName, StringRef SectionName, bool IsInsideLoad) const {971 972  auto SecInfo = GetSectionInfo(FileName, SectionName);973  if (!SecInfo) {974    std::string ErrMsg;975    {976      raw_string_ostream ErrMsgStream(ErrMsg);977      logAllUnhandledErrors(SecInfo.takeError(), ErrMsgStream,978                            "RTDyldChecker: ");979    }980    return std::make_pair(0, std::move(ErrMsg));981  }982 983  // If this address is being looked up in "load" mode, return the content984  // pointer, otherwise return the target address.985 986  uint64_t Addr = 0;987 988  if (IsInsideLoad) {989    if (SecInfo->isZeroFill())990      Addr = 0;991    else992      Addr = pointerToJITTargetAddress(SecInfo->getContent().data());993  } else994    Addr = SecInfo->getTargetAddress();995 996  return std::make_pair(Addr, "");997}998 999std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubOrGOTAddrFor(1000    StringRef StubContainerName, StringRef SymbolName, StringRef StubKindFilter,1001    bool IsInsideLoad, bool IsStubAddr) const {1002 1003  assert((StubKindFilter.empty() || IsStubAddr) &&1004         "Kind name filter only supported for stubs");1005  auto StubInfo =1006      IsStubAddr ? GetStubInfo(StubContainerName, SymbolName, StubKindFilter)1007                 : GetGOTInfo(StubContainerName, SymbolName);1008 1009  if (!StubInfo) {1010    std::string ErrMsg;1011    {1012      raw_string_ostream ErrMsgStream(ErrMsg);1013      logAllUnhandledErrors(StubInfo.takeError(), ErrMsgStream,1014                            "RTDyldChecker: ");1015    }1016    return std::make_pair((uint64_t)0, std::move(ErrMsg));1017  }1018 1019  uint64_t Addr = 0;1020 1021  if (IsInsideLoad) {1022    if (StubInfo->isZeroFill())1023      return std::make_pair((uint64_t)0, "Detected zero-filled stub/GOT entry");1024    Addr = pointerToJITTargetAddress(StubInfo->getContent().data());1025  } else1026    Addr = StubInfo->getTargetAddress();1027 1028  return std::make_pair(Addr, "");1029}1030 1031RuntimeDyldChecker::RuntimeDyldChecker(1032    IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,1033    GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,1034    GetGOTInfoFunction GetGOTInfo, llvm::endianness Endianness, Triple TT,1035    StringRef CPU, SubtargetFeatures TF, raw_ostream &ErrStream)1036    : Impl(::std::make_unique<RuntimeDyldCheckerImpl>(1037          std::move(IsSymbolValid), std::move(GetSymbolInfo),1038          std::move(GetSectionInfo), std::move(GetStubInfo),1039          std::move(GetGOTInfo), Endianness, std::move(TT), std::move(CPU),1040          std::move(TF), ErrStream)) {}1041 1042RuntimeDyldChecker::~RuntimeDyldChecker() = default;1043 1044bool RuntimeDyldChecker::check(StringRef CheckExpr) const {1045  return Impl->check(CheckExpr);1046}1047 1048bool RuntimeDyldChecker::checkAllRulesInBuffer(StringRef RulePrefix,1049                                               MemoryBuffer *MemBuf) const {1050  return Impl->checkAllRulesInBuffer(RulePrefix, MemBuf);1051}1052 1053std::pair<uint64_t, std::string>1054RuntimeDyldChecker::getSectionAddr(StringRef FileName, StringRef SectionName,1055                                   bool LocalAddress) {1056  return Impl->getSectionAddr(FileName, SectionName, LocalAddress);1057}1058