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