LLVM API Documentation
00001 //===--- RuntimeDyldChecker.cpp - RuntimeDyld tester framework --*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "llvm/ADT/STLExtras.h" 00011 #include "llvm/ExecutionEngine/RuntimeDyldChecker.h" 00012 #include "llvm/MC/MCContext.h" 00013 #include "llvm/MC/MCDisassembler.h" 00014 #include "llvm/MC/MCInst.h" 00015 #include "llvm/Support/StringRefMemoryObject.h" 00016 #include "llvm/Support/Path.h" 00017 #include "RuntimeDyldCheckerImpl.h" 00018 #include "RuntimeDyldImpl.h" 00019 #include <cctype> 00020 #include <memory> 00021 00022 #define DEBUG_TYPE "rtdyld" 00023 00024 using namespace llvm; 00025 00026 namespace llvm { 00027 00028 // Helper class that implements the language evaluated by RuntimeDyldChecker. 00029 class RuntimeDyldCheckerExprEval { 00030 public: 00031 RuntimeDyldCheckerExprEval(const RuntimeDyldCheckerImpl &Checker, 00032 raw_ostream &ErrStream) 00033 : Checker(Checker) {} 00034 00035 bool evaluate(StringRef Expr) const { 00036 // Expect equality expression of the form 'LHS = RHS'. 00037 Expr = Expr.trim(); 00038 size_t EQIdx = Expr.find('='); 00039 00040 ParseContext OutsideLoad(false); 00041 00042 // Evaluate LHS. 00043 StringRef LHSExpr = Expr.substr(0, EQIdx).rtrim(); 00044 StringRef RemainingExpr; 00045 EvalResult LHSResult; 00046 std::tie(LHSResult, RemainingExpr) = 00047 evalComplexExpr(evalSimpleExpr(LHSExpr, OutsideLoad), OutsideLoad); 00048 if (LHSResult.hasError()) 00049 return handleError(Expr, LHSResult); 00050 if (RemainingExpr != "") 00051 return handleError(Expr, unexpectedToken(RemainingExpr, LHSExpr, "")); 00052 00053 // Evaluate RHS. 00054 StringRef RHSExpr = Expr.substr(EQIdx + 1).ltrim(); 00055 EvalResult RHSResult; 00056 std::tie(RHSResult, RemainingExpr) = 00057 evalComplexExpr(evalSimpleExpr(RHSExpr, OutsideLoad), OutsideLoad); 00058 if (RHSResult.hasError()) 00059 return handleError(Expr, RHSResult); 00060 if (RemainingExpr != "") 00061 return handleError(Expr, unexpectedToken(RemainingExpr, RHSExpr, "")); 00062 00063 if (LHSResult.getValue() != RHSResult.getValue()) { 00064 Checker.ErrStream << "Expression '" << Expr << "' is false: " 00065 << format("0x%" PRIx64, LHSResult.getValue()) 00066 << " != " << format("0x%" PRIx64, RHSResult.getValue()) 00067 << "\n"; 00068 return false; 00069 } 00070 return true; 00071 } 00072 00073 private: 00074 // RuntimeDyldCheckerExprEval requires some context when parsing exprs. In 00075 // particular, it needs to know whether a symbol is being evaluated in the 00076 // context of a load, in which case we want the linker's local address for 00077 // the symbol, or outside of a load, in which case we want the symbol's 00078 // address in the remote target. 00079 00080 struct ParseContext { 00081 bool IsInsideLoad; 00082 ParseContext(bool IsInsideLoad) : IsInsideLoad(IsInsideLoad) {} 00083 }; 00084 00085 const RuntimeDyldCheckerImpl &Checker; 00086 00087 enum class BinOpToken : unsigned { 00088 Invalid, 00089 Add, 00090 Sub, 00091 BitwiseAnd, 00092 BitwiseOr, 00093 ShiftLeft, 00094 ShiftRight 00095 }; 00096 00097 class EvalResult { 00098 public: 00099 EvalResult() : Value(0), ErrorMsg("") {} 00100 EvalResult(uint64_t Value) : Value(Value), ErrorMsg("") {} 00101 EvalResult(std::string ErrorMsg) : Value(0), ErrorMsg(ErrorMsg) {} 00102 uint64_t getValue() const { return Value; } 00103 bool hasError() const { return ErrorMsg != ""; } 00104 const std::string &getErrorMsg() const { return ErrorMsg; } 00105 00106 private: 00107 uint64_t Value; 00108 std::string ErrorMsg; 00109 }; 00110 00111 StringRef getTokenForError(StringRef Expr) const { 00112 if (Expr.empty()) 00113 return ""; 00114 00115 StringRef Token, Remaining; 00116 if (isalpha(Expr[0])) 00117 std::tie(Token, Remaining) = parseSymbol(Expr); 00118 else if (isdigit(Expr[0])) 00119 std::tie(Token, Remaining) = parseNumberString(Expr); 00120 else { 00121 unsigned TokLen = 1; 00122 if (Expr.startswith("<<") || Expr.startswith(">>")) 00123 TokLen = 2; 00124 Token = Expr.substr(0, TokLen); 00125 } 00126 return Token; 00127 } 00128 00129 EvalResult unexpectedToken(StringRef TokenStart, StringRef SubExpr, 00130 StringRef ErrText) const { 00131 std::string ErrorMsg("Encountered unexpected token '"); 00132 ErrorMsg += getTokenForError(TokenStart); 00133 if (SubExpr != "") { 00134 ErrorMsg += "' while parsing subexpression '"; 00135 ErrorMsg += SubExpr; 00136 } 00137 ErrorMsg += "'"; 00138 if (ErrText != "") { 00139 ErrorMsg += " "; 00140 ErrorMsg += ErrText; 00141 } 00142 return EvalResult(std::move(ErrorMsg)); 00143 } 00144 00145 bool handleError(StringRef Expr, const EvalResult &R) const { 00146 assert(R.hasError() && "Not an error result."); 00147 Checker.ErrStream << "Error evaluating expression '" << Expr 00148 << "': " << R.getErrorMsg() << "\n"; 00149 return false; 00150 } 00151 00152 std::pair<BinOpToken, StringRef> parseBinOpToken(StringRef Expr) const { 00153 if (Expr.empty()) 00154 return std::make_pair(BinOpToken::Invalid, ""); 00155 00156 // Handle the two 2-character tokens. 00157 if (Expr.startswith("<<")) 00158 return std::make_pair(BinOpToken::ShiftLeft, Expr.substr(2).ltrim()); 00159 if (Expr.startswith(">>")) 00160 return std::make_pair(BinOpToken::ShiftRight, Expr.substr(2).ltrim()); 00161 00162 // Handle one-character tokens. 00163 BinOpToken Op; 00164 switch (Expr[0]) { 00165 default: 00166 return std::make_pair(BinOpToken::Invalid, Expr); 00167 case '+': 00168 Op = BinOpToken::Add; 00169 break; 00170 case '-': 00171 Op = BinOpToken::Sub; 00172 break; 00173 case '&': 00174 Op = BinOpToken::BitwiseAnd; 00175 break; 00176 case '|': 00177 Op = BinOpToken::BitwiseOr; 00178 break; 00179 } 00180 00181 return std::make_pair(Op, Expr.substr(1).ltrim()); 00182 } 00183 00184 EvalResult computeBinOpResult(BinOpToken Op, const EvalResult &LHSResult, 00185 const EvalResult &RHSResult) const { 00186 switch (Op) { 00187 default: 00188 llvm_unreachable("Tried to evaluate unrecognized operation."); 00189 case BinOpToken::Add: 00190 return EvalResult(LHSResult.getValue() + RHSResult.getValue()); 00191 case BinOpToken::Sub: 00192 return EvalResult(LHSResult.getValue() - RHSResult.getValue()); 00193 case BinOpToken::BitwiseAnd: 00194 return EvalResult(LHSResult.getValue() & RHSResult.getValue()); 00195 case BinOpToken::BitwiseOr: 00196 return EvalResult(LHSResult.getValue() | RHSResult.getValue()); 00197 case BinOpToken::ShiftLeft: 00198 return EvalResult(LHSResult.getValue() << RHSResult.getValue()); 00199 case BinOpToken::ShiftRight: 00200 return EvalResult(LHSResult.getValue() >> RHSResult.getValue()); 00201 } 00202 } 00203 00204 // Parse a symbol and return a (string, string) pair representing the symbol 00205 // name and expression remaining to be parsed. 00206 std::pair<StringRef, StringRef> parseSymbol(StringRef Expr) const { 00207 size_t FirstNonSymbol = Expr.find_first_not_of("0123456789" 00208 "abcdefghijklmnopqrstuvwxyz" 00209 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 00210 ":_.$"); 00211 return std::make_pair(Expr.substr(0, FirstNonSymbol), 00212 Expr.substr(FirstNonSymbol).ltrim()); 00213 } 00214 00215 // Evaluate a call to decode_operand. Decode the instruction operand at the 00216 // given symbol and get the value of the requested operand. 00217 // Returns an error if the instruction cannot be decoded, or the requested 00218 // operand is not an immediate. 00219 // On success, retuns a pair containing the value of the operand, plus 00220 // the expression remaining to be evaluated. 00221 std::pair<EvalResult, StringRef> evalDecodeOperand(StringRef Expr) const { 00222 if (!Expr.startswith("(")) 00223 return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), ""); 00224 StringRef RemainingExpr = Expr.substr(1).ltrim(); 00225 StringRef Symbol; 00226 std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr); 00227 00228 if (!Checker.isSymbolValid(Symbol)) 00229 return std::make_pair( 00230 EvalResult(("Cannot decode unknown symbol '" + Symbol + "'").str()), 00231 ""); 00232 00233 if (!RemainingExpr.startswith(",")) 00234 return std::make_pair( 00235 unexpectedToken(RemainingExpr, RemainingExpr, "expected ','"), ""); 00236 RemainingExpr = RemainingExpr.substr(1).ltrim(); 00237 00238 EvalResult OpIdxExpr; 00239 std::tie(OpIdxExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); 00240 if (OpIdxExpr.hasError()) 00241 return std::make_pair(OpIdxExpr, ""); 00242 00243 if (!RemainingExpr.startswith(")")) 00244 return std::make_pair( 00245 unexpectedToken(RemainingExpr, RemainingExpr, "expected ')'"), ""); 00246 RemainingExpr = RemainingExpr.substr(1).ltrim(); 00247 00248 MCInst Inst; 00249 uint64_t Size; 00250 if (!decodeInst(Symbol, Inst, Size)) 00251 return std::make_pair( 00252 EvalResult(("Couldn't decode instruction at '" + Symbol + "'").str()), 00253 ""); 00254 00255 unsigned OpIdx = OpIdxExpr.getValue(); 00256 if (OpIdx >= Inst.getNumOperands()) { 00257 std::string ErrMsg; 00258 raw_string_ostream ErrMsgStream(ErrMsg); 00259 ErrMsgStream << "Invalid operand index '" << format("%i", OpIdx) 00260 << "' for instruction '" << Symbol 00261 << "'. Instruction has only " 00262 << format("%i", Inst.getNumOperands()) 00263 << " operands.\nInstruction is:\n "; 00264 Inst.dump_pretty(ErrMsgStream, 00265 Checker.Disassembler->getContext().getAsmInfo(), 00266 Checker.InstPrinter); 00267 return std::make_pair(EvalResult(ErrMsgStream.str()), ""); 00268 } 00269 00270 const MCOperand &Op = Inst.getOperand(OpIdx); 00271 if (!Op.isImm()) { 00272 std::string ErrMsg; 00273 raw_string_ostream ErrMsgStream(ErrMsg); 00274 ErrMsgStream << "Operand '" << format("%i", OpIdx) << "' of instruction '" 00275 << Symbol << "' is not an immediate.\nInstruction is:\n "; 00276 Inst.dump_pretty(ErrMsgStream, 00277 Checker.Disassembler->getContext().getAsmInfo(), 00278 Checker.InstPrinter); 00279 00280 return std::make_pair(EvalResult(ErrMsgStream.str()), ""); 00281 } 00282 00283 return std::make_pair(EvalResult(Op.getImm()), RemainingExpr); 00284 } 00285 00286 // Evaluate a call to next_pc. 00287 // Decode the instruction at the given symbol and return the following program 00288 // counter. 00289 // Returns an error if the instruction cannot be decoded. 00290 // On success, returns a pair containing the next PC, plus of the 00291 // expression remaining to be evaluated. 00292 std::pair<EvalResult, StringRef> evalNextPC(StringRef Expr, 00293 ParseContext PCtx) const { 00294 if (!Expr.startswith("(")) 00295 return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), ""); 00296 StringRef RemainingExpr = Expr.substr(1).ltrim(); 00297 StringRef Symbol; 00298 std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr); 00299 00300 if (!Checker.isSymbolValid(Symbol)) 00301 return std::make_pair( 00302 EvalResult(("Cannot decode unknown symbol '" + Symbol + "'").str()), 00303 ""); 00304 00305 if (!RemainingExpr.startswith(")")) 00306 return std::make_pair( 00307 unexpectedToken(RemainingExpr, RemainingExpr, "expected ')'"), ""); 00308 RemainingExpr = RemainingExpr.substr(1).ltrim(); 00309 00310 MCInst Inst; 00311 uint64_t InstSize; 00312 if (!decodeInst(Symbol, Inst, InstSize)) 00313 return std::make_pair( 00314 EvalResult(("Couldn't decode instruction at '" + Symbol + "'").str()), 00315 ""); 00316 00317 uint64_t SymbolAddr = PCtx.IsInsideLoad 00318 ? Checker.getSymbolLinkerAddr(Symbol) 00319 : Checker.getSymbolRemoteAddr(Symbol); 00320 uint64_t NextPC = SymbolAddr + InstSize; 00321 00322 return std::make_pair(EvalResult(NextPC), RemainingExpr); 00323 } 00324 00325 // Evaluate a call to stub_addr. 00326 // Look up and return the address of the stub for the given 00327 // (<file name>, <section name>, <symbol name>) tuple. 00328 // On success, returns a pair containing the stub address, plus the expression 00329 // remaining to be evaluated. 00330 std::pair<EvalResult, StringRef> evalStubAddr(StringRef Expr, 00331 ParseContext PCtx) const { 00332 if (!Expr.startswith("(")) 00333 return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), ""); 00334 StringRef RemainingExpr = Expr.substr(1).ltrim(); 00335 00336 // Handle file-name specially, as it may contain characters that aren't 00337 // legal for symbols. 00338 StringRef FileName; 00339 size_t ComaIdx = RemainingExpr.find(','); 00340 FileName = RemainingExpr.substr(0, ComaIdx).rtrim(); 00341 RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim(); 00342 00343 if (!RemainingExpr.startswith(",")) 00344 return std::make_pair( 00345 unexpectedToken(RemainingExpr, Expr, "expected ','"), ""); 00346 RemainingExpr = RemainingExpr.substr(1).ltrim(); 00347 00348 StringRef SectionName; 00349 std::tie(SectionName, RemainingExpr) = parseSymbol(RemainingExpr); 00350 00351 if (!RemainingExpr.startswith(",")) 00352 return std::make_pair( 00353 unexpectedToken(RemainingExpr, Expr, "expected ','"), ""); 00354 RemainingExpr = RemainingExpr.substr(1).ltrim(); 00355 00356 StringRef Symbol; 00357 std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr); 00358 00359 if (!RemainingExpr.startswith(")")) 00360 return std::make_pair( 00361 unexpectedToken(RemainingExpr, Expr, "expected ')'"), ""); 00362 RemainingExpr = RemainingExpr.substr(1).ltrim(); 00363 00364 uint64_t StubAddr; 00365 std::string ErrorMsg = ""; 00366 std::tie(StubAddr, ErrorMsg) = Checker.getStubAddrFor( 00367 FileName, SectionName, Symbol, PCtx.IsInsideLoad); 00368 00369 if (ErrorMsg != "") 00370 return std::make_pair(EvalResult(ErrorMsg), ""); 00371 00372 return std::make_pair(EvalResult(StubAddr), RemainingExpr); 00373 } 00374 00375 std::pair<EvalResult, StringRef> evalSectionAddr(StringRef Expr, 00376 ParseContext PCtx) const { 00377 if (!Expr.startswith("(")) 00378 return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), ""); 00379 StringRef RemainingExpr = Expr.substr(1).ltrim(); 00380 00381 // Handle file-name specially, as it may contain characters that aren't 00382 // legal for symbols. 00383 StringRef FileName; 00384 size_t ComaIdx = RemainingExpr.find(','); 00385 FileName = RemainingExpr.substr(0, ComaIdx).rtrim(); 00386 RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim(); 00387 00388 if (!RemainingExpr.startswith(",")) 00389 return std::make_pair( 00390 unexpectedToken(RemainingExpr, Expr, "expected ','"), ""); 00391 RemainingExpr = RemainingExpr.substr(1).ltrim(); 00392 00393 StringRef SectionName; 00394 std::tie(SectionName, RemainingExpr) = parseSymbol(RemainingExpr); 00395 00396 if (!RemainingExpr.startswith(")")) 00397 return std::make_pair( 00398 unexpectedToken(RemainingExpr, Expr, "expected ')'"), ""); 00399 RemainingExpr = RemainingExpr.substr(1).ltrim(); 00400 00401 uint64_t StubAddr; 00402 std::string ErrorMsg = ""; 00403 std::tie(StubAddr, ErrorMsg) = Checker.getSectionAddr( 00404 FileName, SectionName, PCtx.IsInsideLoad); 00405 00406 if (ErrorMsg != "") 00407 return std::make_pair(EvalResult(ErrorMsg), ""); 00408 00409 return std::make_pair(EvalResult(StubAddr), RemainingExpr); 00410 } 00411 00412 // Evaluate an identiefer expr, which may be a symbol, or a call to 00413 // one of the builtin functions: get_insn_opcode or get_insn_length. 00414 // Return the result, plus the expression remaining to be parsed. 00415 std::pair<EvalResult, StringRef> evalIdentifierExpr(StringRef Expr, 00416 ParseContext PCtx) const { 00417 StringRef Symbol; 00418 StringRef RemainingExpr; 00419 std::tie(Symbol, RemainingExpr) = parseSymbol(Expr); 00420 00421 // Check for builtin function calls. 00422 if (Symbol == "decode_operand") 00423 return evalDecodeOperand(RemainingExpr); 00424 else if (Symbol == "next_pc") 00425 return evalNextPC(RemainingExpr, PCtx); 00426 else if (Symbol == "stub_addr") 00427 return evalStubAddr(RemainingExpr, PCtx); 00428 else if (Symbol == "section_addr") 00429 return evalSectionAddr(RemainingExpr, PCtx); 00430 00431 if (!Checker.isSymbolValid(Symbol)) { 00432 std::string ErrMsg("No known address for symbol '"); 00433 ErrMsg += Symbol; 00434 ErrMsg += "'"; 00435 if (Symbol.startswith("L")) 00436 ErrMsg += " (this appears to be an assembler local label - " 00437 " perhaps drop the 'L'?)"; 00438 00439 return std::make_pair(EvalResult(ErrMsg), ""); 00440 } 00441 00442 // The value for the symbol depends on the context we're evaluating in: 00443 // Inside a load this is the address in the linker's memory, outside a 00444 // load it's the address in the target processes memory. 00445 uint64_t Value = PCtx.IsInsideLoad ? Checker.getSymbolLinkerAddr(Symbol) 00446 : Checker.getSymbolRemoteAddr(Symbol); 00447 00448 // Looks like a plain symbol reference. 00449 return std::make_pair(EvalResult(Value), RemainingExpr); 00450 } 00451 00452 // Parse a number (hexadecimal or decimal) and return a (string, string) 00453 // pair representing the number and the expression remaining to be parsed. 00454 std::pair<StringRef, StringRef> parseNumberString(StringRef Expr) const { 00455 size_t FirstNonDigit = StringRef::npos; 00456 if (Expr.startswith("0x")) { 00457 FirstNonDigit = Expr.find_first_not_of("0123456789abcdefABCDEF", 2); 00458 if (FirstNonDigit == StringRef::npos) 00459 FirstNonDigit = Expr.size(); 00460 } else { 00461 FirstNonDigit = Expr.find_first_not_of("0123456789"); 00462 if (FirstNonDigit == StringRef::npos) 00463 FirstNonDigit = Expr.size(); 00464 } 00465 return std::make_pair(Expr.substr(0, FirstNonDigit), 00466 Expr.substr(FirstNonDigit)); 00467 } 00468 00469 // Evaluate a constant numeric expression (hexidecimal or decimal) and 00470 // return a pair containing the result, and the expression remaining to be 00471 // evaluated. 00472 std::pair<EvalResult, StringRef> evalNumberExpr(StringRef Expr) const { 00473 StringRef ValueStr; 00474 StringRef RemainingExpr; 00475 std::tie(ValueStr, RemainingExpr) = parseNumberString(Expr); 00476 00477 if (ValueStr.empty() || !isdigit(ValueStr[0])) 00478 return std::make_pair( 00479 unexpectedToken(RemainingExpr, RemainingExpr, "expected number"), ""); 00480 uint64_t Value; 00481 ValueStr.getAsInteger(0, Value); 00482 return std::make_pair(EvalResult(Value), RemainingExpr); 00483 } 00484 00485 // Evaluate an expression of the form "(<expr>)" and return a pair 00486 // containing the result of evaluating <expr>, plus the expression 00487 // remaining to be parsed. 00488 std::pair<EvalResult, StringRef> evalParensExpr(StringRef Expr, 00489 ParseContext PCtx) const { 00490 assert(Expr.startswith("(") && "Not a parenthesized expression"); 00491 EvalResult SubExprResult; 00492 StringRef RemainingExpr; 00493 std::tie(SubExprResult, RemainingExpr) = 00494 evalComplexExpr(evalSimpleExpr(Expr.substr(1).ltrim(), PCtx), PCtx); 00495 if (SubExprResult.hasError()) 00496 return std::make_pair(SubExprResult, ""); 00497 if (!RemainingExpr.startswith(")")) 00498 return std::make_pair( 00499 unexpectedToken(RemainingExpr, Expr, "expected ')'"), ""); 00500 RemainingExpr = RemainingExpr.substr(1).ltrim(); 00501 return std::make_pair(SubExprResult, RemainingExpr); 00502 } 00503 00504 // Evaluate an expression in one of the following forms: 00505 // *{<number>}<expr> 00506 // Return a pair containing the result, plus the expression remaining to be 00507 // parsed. 00508 std::pair<EvalResult, StringRef> evalLoadExpr(StringRef Expr) const { 00509 assert(Expr.startswith("*") && "Not a load expression"); 00510 StringRef RemainingExpr = Expr.substr(1).ltrim(); 00511 00512 // Parse read size. 00513 if (!RemainingExpr.startswith("{")) 00514 return std::make_pair(EvalResult("Expected '{' following '*'."), ""); 00515 RemainingExpr = RemainingExpr.substr(1).ltrim(); 00516 EvalResult ReadSizeExpr; 00517 std::tie(ReadSizeExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); 00518 if (ReadSizeExpr.hasError()) 00519 return std::make_pair(ReadSizeExpr, RemainingExpr); 00520 uint64_t ReadSize = ReadSizeExpr.getValue(); 00521 if (ReadSize < 1 || ReadSize > 8) 00522 return std::make_pair(EvalResult("Invalid size for dereference."), ""); 00523 if (!RemainingExpr.startswith("}")) 00524 return std::make_pair(EvalResult("Missing '}' for dereference."), ""); 00525 RemainingExpr = RemainingExpr.substr(1).ltrim(); 00526 00527 // Evaluate the expression representing the load address. 00528 ParseContext LoadCtx(true); 00529 EvalResult LoadAddrExprResult; 00530 std::tie(LoadAddrExprResult, RemainingExpr) = 00531 evalComplexExpr(evalSimpleExpr(RemainingExpr, LoadCtx), LoadCtx); 00532 00533 if (LoadAddrExprResult.hasError()) 00534 return std::make_pair(LoadAddrExprResult, ""); 00535 00536 uint64_t LoadAddr = LoadAddrExprResult.getValue(); 00537 00538 return std::make_pair( 00539 EvalResult(Checker.readMemoryAtAddr(LoadAddr, ReadSize)), 00540 RemainingExpr); 00541 } 00542 00543 // Evaluate a "simple" expression. This is any expression that _isn't_ an 00544 // un-parenthesized binary expression. 00545 // 00546 // "Simple" expressions can be optionally bit-sliced. See evalSlicedExpr. 00547 // 00548 // Returns a pair containing the result of the evaluation, plus the 00549 // expression remaining to be parsed. 00550 std::pair<EvalResult, StringRef> evalSimpleExpr(StringRef Expr, 00551 ParseContext PCtx) const { 00552 EvalResult SubExprResult; 00553 StringRef RemainingExpr; 00554 00555 if (Expr.empty()) 00556 return std::make_pair(EvalResult("Unexpected end of expression"), ""); 00557 00558 if (Expr[0] == '(') 00559 std::tie(SubExprResult, RemainingExpr) = evalParensExpr(Expr, PCtx); 00560 else if (Expr[0] == '*') 00561 std::tie(SubExprResult, RemainingExpr) = evalLoadExpr(Expr); 00562 else if (isalpha(Expr[0]) || Expr[0] == '_') 00563 std::tie(SubExprResult, RemainingExpr) = evalIdentifierExpr(Expr, PCtx); 00564 else if (isdigit(Expr[0])) 00565 std::tie(SubExprResult, RemainingExpr) = evalNumberExpr(Expr); 00566 else 00567 return std::make_pair( 00568 unexpectedToken(Expr, Expr, 00569 "expected '(', '*', identifier, or number"), ""); 00570 00571 if (SubExprResult.hasError()) 00572 return std::make_pair(SubExprResult, RemainingExpr); 00573 00574 // Evaluate bit-slice if present. 00575 if (RemainingExpr.startswith("[")) 00576 std::tie(SubExprResult, RemainingExpr) = 00577 evalSliceExpr(std::make_pair(SubExprResult, RemainingExpr)); 00578 00579 return std::make_pair(SubExprResult, RemainingExpr); 00580 } 00581 00582 // Evaluate a bit-slice of an expression. 00583 // A bit-slice has the form "<expr>[high:low]". The result of evaluating a 00584 // slice is the bits between high and low (inclusive) in the original 00585 // expression, right shifted so that the "low" bit is in position 0 in the 00586 // result. 00587 // Returns a pair containing the result of the slice operation, plus the 00588 // expression remaining to be parsed. 00589 std::pair<EvalResult, StringRef> 00590 evalSliceExpr(std::pair<EvalResult, StringRef> Ctx) const { 00591 EvalResult SubExprResult; 00592 StringRef RemainingExpr; 00593 std::tie(SubExprResult, RemainingExpr) = Ctx; 00594 00595 assert(RemainingExpr.startswith("[") && "Not a slice expr."); 00596 RemainingExpr = RemainingExpr.substr(1).ltrim(); 00597 00598 EvalResult HighBitExpr; 00599 std::tie(HighBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); 00600 00601 if (HighBitExpr.hasError()) 00602 return std::make_pair(HighBitExpr, RemainingExpr); 00603 00604 if (!RemainingExpr.startswith(":")) 00605 return std::make_pair( 00606 unexpectedToken(RemainingExpr, RemainingExpr, "expected ':'"), ""); 00607 RemainingExpr = RemainingExpr.substr(1).ltrim(); 00608 00609 EvalResult LowBitExpr; 00610 std::tie(LowBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); 00611 00612 if (LowBitExpr.hasError()) 00613 return std::make_pair(LowBitExpr, RemainingExpr); 00614 00615 if (!RemainingExpr.startswith("]")) 00616 return std::make_pair( 00617 unexpectedToken(RemainingExpr, RemainingExpr, "expected ']'"), ""); 00618 RemainingExpr = RemainingExpr.substr(1).ltrim(); 00619 00620 unsigned HighBit = HighBitExpr.getValue(); 00621 unsigned LowBit = LowBitExpr.getValue(); 00622 uint64_t Mask = ((uint64_t)1 << (HighBit - LowBit + 1)) - 1; 00623 uint64_t SlicedValue = (SubExprResult.getValue() >> LowBit) & Mask; 00624 return std::make_pair(EvalResult(SlicedValue), RemainingExpr); 00625 } 00626 00627 // Evaluate a "complex" expression. 00628 // Takes an already evaluated subexpression and checks for the presence of a 00629 // binary operator, computing the result of the binary operation if one is 00630 // found. Used to make arithmetic expressions left-associative. 00631 // Returns a pair containing the ultimate result of evaluating the 00632 // expression, plus the expression remaining to be evaluated. 00633 std::pair<EvalResult, StringRef> 00634 evalComplexExpr(std::pair<EvalResult, StringRef> LHSAndRemaining, 00635 ParseContext PCtx) const { 00636 EvalResult LHSResult; 00637 StringRef RemainingExpr; 00638 std::tie(LHSResult, RemainingExpr) = LHSAndRemaining; 00639 00640 // If there was an error, or there's nothing left to evaluate, return the 00641 // result. 00642 if (LHSResult.hasError() || RemainingExpr == "") 00643 return std::make_pair(LHSResult, RemainingExpr); 00644 00645 // Otherwise check if this is a binary expressioan. 00646 BinOpToken BinOp; 00647 std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr); 00648 00649 // If this isn't a recognized expression just return. 00650 if (BinOp == BinOpToken::Invalid) 00651 return std::make_pair(LHSResult, RemainingExpr); 00652 00653 // This is a recognized bin-op. Evaluate the RHS, then evaluate the binop. 00654 EvalResult RHSResult; 00655 std::tie(RHSResult, RemainingExpr) = evalSimpleExpr(RemainingExpr, PCtx); 00656 00657 // If there was an error evaluating the RHS, return it. 00658 if (RHSResult.hasError()) 00659 return std::make_pair(RHSResult, RemainingExpr); 00660 00661 // This is a binary expression - evaluate and try to continue as a 00662 // complex expr. 00663 EvalResult ThisResult(computeBinOpResult(BinOp, LHSResult, RHSResult)); 00664 00665 return evalComplexExpr(std::make_pair(ThisResult, RemainingExpr), PCtx); 00666 } 00667 00668 bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size) const { 00669 MCDisassembler *Dis = Checker.Disassembler; 00670 StringRef SectionMem = Checker.getSubsectionStartingAt(Symbol); 00671 StringRefMemoryObject SectionBytes(SectionMem, 0); 00672 00673 MCDisassembler::DecodeStatus S = 00674 Dis->getInstruction(Inst, Size, SectionBytes, 0, nulls(), nulls()); 00675 00676 return (S == MCDisassembler::Success); 00677 } 00678 }; 00679 } 00680 00681 RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl(RuntimeDyld &RTDyld, 00682 MCDisassembler *Disassembler, 00683 MCInstPrinter *InstPrinter, 00684 raw_ostream &ErrStream) 00685 : RTDyld(RTDyld), Disassembler(Disassembler), InstPrinter(InstPrinter), 00686 ErrStream(ErrStream) { 00687 RTDyld.Checker = this; 00688 } 00689 00690 bool RuntimeDyldCheckerImpl::check(StringRef CheckExpr) const { 00691 CheckExpr = CheckExpr.trim(); 00692 DEBUG(dbgs() << "RuntimeDyldChecker: Checking '" << CheckExpr << "'...\n"); 00693 RuntimeDyldCheckerExprEval P(*this, ErrStream); 00694 bool Result = P.evaluate(CheckExpr); 00695 (void)Result; 00696 DEBUG(dbgs() << "RuntimeDyldChecker: '" << CheckExpr << "' " 00697 << (Result ? "passed" : "FAILED") << ".\n"); 00698 return Result; 00699 } 00700 00701 bool RuntimeDyldCheckerImpl::checkAllRulesInBuffer(StringRef RulePrefix, 00702 MemoryBuffer *MemBuf) const { 00703 bool DidAllTestsPass = true; 00704 unsigned NumRules = 0; 00705 00706 const char *LineStart = MemBuf->getBufferStart(); 00707 00708 // Eat whitespace. 00709 while (LineStart != MemBuf->getBufferEnd() && std::isspace(*LineStart)) 00710 ++LineStart; 00711 00712 while (LineStart != MemBuf->getBufferEnd() && *LineStart != '\0') { 00713 const char *LineEnd = LineStart; 00714 while (LineEnd != MemBuf->getBufferEnd() && *LineEnd != '\r' && 00715 *LineEnd != '\n') 00716 ++LineEnd; 00717 00718 StringRef Line(LineStart, LineEnd - LineStart); 00719 if (Line.startswith(RulePrefix)) { 00720 DidAllTestsPass &= check(Line.substr(RulePrefix.size())); 00721 ++NumRules; 00722 } 00723 00724 // Eat whitespace. 00725 LineStart = LineEnd; 00726 while (LineStart != MemBuf->getBufferEnd() && std::isspace(*LineStart)) 00727 ++LineStart; 00728 } 00729 return DidAllTestsPass && (NumRules != 0); 00730 } 00731 00732 bool RuntimeDyldCheckerImpl::isSymbolValid(StringRef Symbol) const { 00733 return getRTDyld().getSymbolAddress(Symbol) != nullptr; 00734 } 00735 00736 uint64_t RuntimeDyldCheckerImpl::getSymbolLinkerAddr(StringRef Symbol) const { 00737 return static_cast<uint64_t>( 00738 reinterpret_cast<uintptr_t>(getRTDyld().getSymbolAddress(Symbol))); 00739 } 00740 00741 uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const { 00742 return getRTDyld().getAnySymbolRemoteAddress(Symbol); 00743 } 00744 00745 uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr, 00746 unsigned Size) const { 00747 uintptr_t PtrSizedAddr = static_cast<uintptr_t>(SrcAddr); 00748 assert(PtrSizedAddr == SrcAddr && "Linker memory pointer out-of-range."); 00749 uint8_t *Src = reinterpret_cast<uint8_t*>(PtrSizedAddr); 00750 return getRTDyld().readBytesUnaligned(Src, Size); 00751 } 00752 00753 00754 std::pair<const RuntimeDyldCheckerImpl::SectionAddressInfo*, std::string> 00755 RuntimeDyldCheckerImpl::findSectionAddrInfo(StringRef FileName, 00756 StringRef SectionName) const { 00757 00758 auto SectionMapItr = Stubs.find(FileName); 00759 if (SectionMapItr == Stubs.end()) { 00760 std::string ErrorMsg = "File '"; 00761 ErrorMsg += FileName; 00762 ErrorMsg += "' not found. "; 00763 if (Stubs.empty()) 00764 ErrorMsg += "No stubs registered."; 00765 else { 00766 ErrorMsg += "Available files are:"; 00767 for (const auto& StubEntry : Stubs) { 00768 ErrorMsg += " '"; 00769 ErrorMsg += StubEntry.first; 00770 ErrorMsg += "'"; 00771 } 00772 } 00773 ErrorMsg += "\n"; 00774 return std::make_pair(nullptr, ErrorMsg); 00775 } 00776 00777 auto SectionInfoItr = SectionMapItr->second.find(SectionName); 00778 if (SectionInfoItr == SectionMapItr->second.end()) 00779 return std::make_pair(nullptr, 00780 ("Section '" + SectionName + "' not found in file '" + 00781 FileName + "'\n").str()); 00782 00783 return std::make_pair(&SectionInfoItr->second, std::string("")); 00784 } 00785 00786 std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getSectionAddr( 00787 StringRef FileName, StringRef SectionName, bool IsInsideLoad) const { 00788 00789 const SectionAddressInfo *SectionInfo = nullptr; 00790 { 00791 std::string ErrorMsg; 00792 std::tie(SectionInfo, ErrorMsg) = 00793 findSectionAddrInfo(FileName, SectionName); 00794 if (ErrorMsg != "") 00795 return std::make_pair(0, ErrorMsg); 00796 } 00797 00798 unsigned SectionID = SectionInfo->SectionID; 00799 uint64_t Addr; 00800 if (IsInsideLoad) 00801 Addr = 00802 static_cast<uint64_t>( 00803 reinterpret_cast<uintptr_t>(getRTDyld().Sections[SectionID].Address)); 00804 else 00805 Addr = getRTDyld().Sections[SectionID].LoadAddress; 00806 00807 return std::make_pair(Addr, std::string("")); 00808 } 00809 00810 std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubAddrFor( 00811 StringRef FileName, StringRef SectionName, StringRef SymbolName, 00812 bool IsInsideLoad) const { 00813 00814 const SectionAddressInfo *SectionInfo = nullptr; 00815 { 00816 std::string ErrorMsg; 00817 std::tie(SectionInfo, ErrorMsg) = 00818 findSectionAddrInfo(FileName, SectionName); 00819 if (ErrorMsg != "") 00820 return std::make_pair(0, ErrorMsg); 00821 } 00822 00823 unsigned SectionID = SectionInfo->SectionID; 00824 const StubOffsetsMap &SymbolStubs = SectionInfo->StubOffsets; 00825 auto StubOffsetItr = SymbolStubs.find(SymbolName); 00826 if (StubOffsetItr == SymbolStubs.end()) 00827 return std::make_pair(0, 00828 ("Stub for symbol '" + SymbolName + "' not found. " 00829 "If '" + SymbolName + "' is an internal symbol this " 00830 "may indicate that the stub target offset is being " 00831 "computed incorrectly.\n").str()); 00832 00833 uint64_t StubOffset = StubOffsetItr->second; 00834 00835 uint64_t Addr; 00836 if (IsInsideLoad) { 00837 uintptr_t SectionBase = 00838 reinterpret_cast<uintptr_t>(getRTDyld().Sections[SectionID].Address); 00839 Addr = static_cast<uint64_t>(SectionBase) + StubOffset; 00840 } else { 00841 uint64_t SectionBase = getRTDyld().Sections[SectionID].LoadAddress; 00842 Addr = SectionBase + StubOffset; 00843 } 00844 00845 return std::make_pair(Addr, std::string("")); 00846 } 00847 00848 StringRef 00849 RuntimeDyldCheckerImpl::getSubsectionStartingAt(StringRef Name) const { 00850 RuntimeDyldImpl::SymbolTableMap::const_iterator pos = 00851 getRTDyld().GlobalSymbolTable.find(Name); 00852 if (pos == getRTDyld().GlobalSymbolTable.end()) 00853 return StringRef(); 00854 RuntimeDyldImpl::SymbolLoc Loc = pos->second; 00855 uint8_t *SectionAddr = getRTDyld().getSectionAddress(Loc.first); 00856 return StringRef(reinterpret_cast<const char *>(SectionAddr) + Loc.second, 00857 getRTDyld().Sections[Loc.first].Size - Loc.second); 00858 } 00859 00860 void RuntimeDyldCheckerImpl::registerSection( 00861 StringRef FilePath, unsigned SectionID) { 00862 StringRef FileName = sys::path::filename(FilePath); 00863 const SectionEntry &Section = getRTDyld().Sections[SectionID]; 00864 StringRef SectionName = Section.Name; 00865 00866 Stubs[FileName][SectionName].SectionID = SectionID; 00867 } 00868 00869 void RuntimeDyldCheckerImpl::registerStubMap( 00870 StringRef FilePath, unsigned SectionID, 00871 const RuntimeDyldImpl::StubMap &RTDyldStubs) { 00872 StringRef FileName = sys::path::filename(FilePath); 00873 const SectionEntry &Section = getRTDyld().Sections[SectionID]; 00874 StringRef SectionName = Section.Name; 00875 00876 Stubs[FileName][SectionName].SectionID = SectionID; 00877 00878 for (auto &StubMapEntry : RTDyldStubs) { 00879 std::string SymbolName = ""; 00880 00881 if (StubMapEntry.first.SymbolName) 00882 SymbolName = StubMapEntry.first.SymbolName; 00883 else { 00884 // If this is a (Section, Offset) pair, do a reverse lookup in the 00885 // global symbol table to find the name. 00886 for (auto &GSTEntry : getRTDyld().GlobalSymbolTable) { 00887 if (GSTEntry.second.first == StubMapEntry.first.SectionID && 00888 GSTEntry.second.second == 00889 static_cast<uint64_t>(StubMapEntry.first.Offset)) { 00890 SymbolName = GSTEntry.first(); 00891 break; 00892 } 00893 } 00894 } 00895 00896 if (SymbolName != "") 00897 Stubs[FileName][SectionName].StubOffsets[SymbolName] = 00898 StubMapEntry.second; 00899 } 00900 } 00901 00902 RuntimeDyldChecker::RuntimeDyldChecker(RuntimeDyld &RTDyld, 00903 MCDisassembler *Disassembler, 00904 MCInstPrinter *InstPrinter, 00905 raw_ostream &ErrStream) 00906 : Impl(make_unique<RuntimeDyldCheckerImpl>(RTDyld, Disassembler, 00907 InstPrinter, ErrStream)) {} 00908 00909 RuntimeDyldChecker::~RuntimeDyldChecker() {} 00910 00911 RuntimeDyld& RuntimeDyldChecker::getRTDyld() { 00912 return Impl->RTDyld; 00913 } 00914 00915 const RuntimeDyld& RuntimeDyldChecker::getRTDyld() const { 00916 return Impl->RTDyld; 00917 } 00918 00919 bool RuntimeDyldChecker::check(StringRef CheckExpr) const { 00920 return Impl->check(CheckExpr); 00921 } 00922 00923 bool RuntimeDyldChecker::checkAllRulesInBuffer(StringRef RulePrefix, 00924 MemoryBuffer *MemBuf) const { 00925 return Impl->checkAllRulesInBuffer(RulePrefix, MemBuf); 00926 } 00927 00928 std::pair<uint64_t, std::string> 00929 RuntimeDyldChecker::getSectionAddr(StringRef FileName, StringRef SectionName, 00930 bool LinkerAddress) { 00931 return Impl->getSectionAddr(FileName, SectionName, LinkerAddress); 00932 }