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