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