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