xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
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