1 //===--- RuntimeDyldChecker.cpp - RuntimeDyld tester framework --*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/ExecutionEngine/RuntimeDyldChecker.h" 11 #include "llvm/MC/MCContext.h" 12 #include "llvm/MC/MCDisassembler.h" 13 #include "llvm/MC/MCInst.h" 14 #include "llvm/Support/StringRefMemoryObject.h" 15 #include "RuntimeDyldImpl.h" 16 #include <cctype> 17 #include <memory> 18 19 #define DEBUG_TYPE "rtdyld" 20 21 using namespace llvm; 22 23 namespace llvm { 24 25 // Helper class that implements the language evaluated by RuntimeDyldChecker. 26 class RuntimeDyldCheckerExprEval { 27 public: 28 29 RuntimeDyldCheckerExprEval(const RuntimeDyldChecker &Checker, 30 llvm::raw_ostream &ErrStream) 31 : Checker(Checker), ErrStream(ErrStream) {} 32 33 bool evaluate(StringRef Expr) const { 34 // Expect equality expression of the form 'LHS = RHS'. 35 Expr = Expr.trim(); 36 size_t EQIdx = Expr.find('='); 37 38 // Evaluate LHS. 39 StringRef LHSExpr = Expr.substr(0, EQIdx).rtrim(); 40 StringRef RemainingExpr; 41 EvalResult LHSResult; 42 std::tie(LHSResult, RemainingExpr) = 43 evalComplexExpr(evalSimpleExpr(LHSExpr)); 44 if (LHSResult.hasError()) 45 return handleError(Expr, LHSResult); 46 if (RemainingExpr != "") 47 return handleError(Expr, unexpectedToken(RemainingExpr, LHSExpr, "")); 48 49 // Evaluate RHS. 50 StringRef RHSExpr = Expr.substr(EQIdx + 1).ltrim(); 51 EvalResult RHSResult; 52 std::tie(RHSResult, RemainingExpr) = 53 evalComplexExpr(evalSimpleExpr(RHSExpr)); 54 if (RHSResult.hasError()) 55 return handleError(Expr, RHSResult); 56 if (RemainingExpr != "") 57 return handleError(Expr, unexpectedToken(RemainingExpr, RHSExpr, "")); 58 59 if (LHSResult.getValue() != RHSResult.getValue()) { 60 ErrStream << "Expression '" << Expr << "' is false: " 61 << format("0x%lx", LHSResult.getValue()) << " != " 62 << format("0x%lx", RHSResult.getValue()) << "\n"; 63 return false; 64 } 65 return true; 66 } 67 68 private: 69 const RuntimeDyldChecker &Checker; 70 llvm::raw_ostream &ErrStream; 71 72 enum class BinOpToken : unsigned { Invalid, Add, Sub, BitwiseAnd, 73 BitwiseOr, ShiftLeft, ShiftRight }; 74 75 class EvalResult { 76 public: 77 EvalResult() 78 : Value(0), ErrorMsg("") {} 79 EvalResult(uint64_t Value) 80 : Value(Value), ErrorMsg("") {} 81 EvalResult(std::string ErrorMsg) 82 : Value(0), ErrorMsg(ErrorMsg) {} 83 uint64_t getValue() const { return Value; } 84 bool hasError() const { return ErrorMsg != ""; } 85 const std::string& getErrorMsg() const { return ErrorMsg; } 86 private: 87 uint64_t Value; 88 std::string ErrorMsg; 89 }; 90 91 StringRef getTokenForError(StringRef Expr) const { 92 if (Expr.empty()) 93 return ""; 94 95 StringRef Token, Remaining; 96 if (isalpha(Expr[0])) 97 std::tie(Token, Remaining) = parseSymbol(Expr); 98 else if (isdigit(Expr[0])) 99 std::tie(Token, Remaining) = parseNumberString(Expr); 100 else { 101 unsigned TokLen = 1; 102 if (Expr.startswith("<<") || Expr.startswith(">>")) 103 TokLen = 2; 104 Token = Expr.substr(0, TokLen); 105 } 106 return Token; 107 } 108 109 EvalResult unexpectedToken(StringRef TokenStart, 110 StringRef SubExpr, 111 StringRef ErrText) const { 112 std::string ErrorMsg("Encountered unexpected token '"); 113 ErrorMsg += getTokenForError(TokenStart); 114 if (SubExpr != "") { 115 ErrorMsg += "' while parsing subexpression '"; 116 ErrorMsg += SubExpr; 117 } 118 ErrorMsg += "'"; 119 if (ErrText != "") { 120 ErrorMsg += " "; 121 ErrorMsg += ErrText; 122 } 123 return EvalResult(std::move(ErrorMsg)); 124 } 125 126 bool handleError(StringRef Expr, const EvalResult &R) const { 127 assert(R.hasError() && "Not an error result."); 128 ErrStream << "Error evaluating expression '" << Expr << "': " 129 << R.getErrorMsg() << "\n"; 130 return false; 131 } 132 133 std::pair<BinOpToken, StringRef> parseBinOpToken(StringRef Expr) const { 134 if (Expr.empty()) 135 return std::make_pair(BinOpToken::Invalid, ""); 136 137 // Handle the two 2-character tokens. 138 if (Expr.startswith("<<")) 139 return std::make_pair(BinOpToken::ShiftLeft, 140 Expr.substr(2).ltrim()); 141 if (Expr.startswith(">>")) 142 return std::make_pair(BinOpToken::ShiftRight, 143 Expr.substr(2).ltrim()); 144 145 // Handle one-character tokens. 146 BinOpToken Op; 147 switch (Expr[0]) { 148 default: return std::make_pair(BinOpToken::Invalid, Expr); 149 case '+': Op = BinOpToken::Add; break; 150 case '-': Op = BinOpToken::Sub; break; 151 case '&': Op = BinOpToken::BitwiseAnd; break; 152 case '|': Op = BinOpToken::BitwiseOr; break; 153 } 154 155 return std::make_pair(Op, Expr.substr(1).ltrim()); 156 } 157 158 EvalResult computeBinOpResult(BinOpToken Op, const EvalResult &LHSResult, 159 const EvalResult &RHSResult) const { 160 switch (Op) { 161 default: llvm_unreachable("Tried to evaluate unrecognized operation."); 162 case BinOpToken::Add: 163 return EvalResult(LHSResult.getValue() + RHSResult.getValue()); 164 case BinOpToken::Sub: 165 return EvalResult(LHSResult.getValue() - RHSResult.getValue()); 166 case BinOpToken::BitwiseAnd: 167 return EvalResult(LHSResult.getValue() & RHSResult.getValue()); 168 case BinOpToken::BitwiseOr: 169 return EvalResult(LHSResult.getValue() | RHSResult.getValue()); 170 case BinOpToken::ShiftLeft: 171 return EvalResult(LHSResult.getValue() << RHSResult.getValue()); 172 case BinOpToken::ShiftRight: 173 return EvalResult(LHSResult.getValue() >> RHSResult.getValue()); 174 } 175 } 176 177 // Parse a symbol and return a (string, string) pair representing the symbol 178 // name and expression remaining to be parsed. 179 std::pair<StringRef, StringRef> parseSymbol(StringRef Expr) const { 180 size_t FirstNonSymbol = 181 Expr.find_first_not_of("0123456789" 182 "abcdefghijklmnopqrstuvwxyz" 183 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 184 ":_"); 185 return std::make_pair(Expr.substr(0, FirstNonSymbol), 186 Expr.substr(FirstNonSymbol).ltrim()); 187 } 188 189 // Evaluate a call to decode_operand. Decode the instruction operand at the 190 // given symbol and get the value of the requested operand. 191 // Returns an error if the instruction cannot be decoded, or the requested 192 // operand is not an immediate. 193 // On success, retuns a pair containing the value of the operand, plus 194 // the expression remaining to be evaluated. 195 std::pair<EvalResult, StringRef> evalDecodeOperand(StringRef Expr) const { 196 if (!Expr.startswith("(")) 197 return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), ""); 198 StringRef RemainingExpr = Expr.substr(1).ltrim(); 199 StringRef Symbol; 200 std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr); 201 202 if (!Checker.checkSymbolIsValidForLoad(Symbol)) 203 return std::make_pair(EvalResult(("Cannot decode unknown symbol '" + 204 Symbol + "'").str()), 205 ""); 206 207 if (!RemainingExpr.startswith(",")) 208 return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr, 209 "expected ','"), 210 ""); 211 RemainingExpr = RemainingExpr.substr(1).ltrim(); 212 213 EvalResult OpIdxExpr; 214 std::tie(OpIdxExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); 215 if (OpIdxExpr.hasError()) 216 return std::make_pair(OpIdxExpr, ""); 217 218 if (!RemainingExpr.startswith(")")) 219 return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr, 220 "expected ')'"), 221 ""); 222 RemainingExpr = RemainingExpr.substr(1).ltrim(); 223 224 MCInst Inst; 225 uint64_t Size; 226 if (!decodeInst(Symbol, Inst, Size)) 227 return std::make_pair(EvalResult(("Couldn't decode instruction at '" + 228 Symbol + "'").str()), 229 ""); 230 231 unsigned OpIdx = OpIdxExpr.getValue(); 232 if (OpIdx >= Inst.getNumOperands()) { 233 std::string ErrMsg; 234 raw_string_ostream ErrMsgStream(ErrMsg); 235 ErrMsgStream << "Invalid operand index '" << format("%i", OpIdx) 236 << " for instruction '" << Symbol 237 << ". Instruction has only " 238 << format("%i", Inst.getNumOperands()) << " operands."; 239 return std::make_pair(EvalResult(ErrMsgStream.str()), ""); 240 } 241 242 const MCOperand &Op = Inst.getOperand(OpIdx); 243 if (!Op.isImm()) { 244 std::string ErrMsg; 245 raw_string_ostream ErrMsgStream(ErrMsg); 246 ErrMsgStream << "Operand '" << format("%i", OpIdx) 247 << "' of instruction '" << Symbol 248 << "' is not an immediate.\nInstruction is:\n "; 249 Inst.dump_pretty(ErrMsgStream, 250 Checker.Disassembler->getContext().getAsmInfo(), 251 Checker.InstPrinter); 252 253 return std::make_pair(EvalResult(ErrMsgStream.str()), ""); 254 } 255 256 return std::make_pair(EvalResult(Op.getImm()), RemainingExpr); 257 } 258 259 // Evaluate a call to next_pc. Decode the instruction at the given 260 // symbol and return the following program counter.. 261 // Returns an error if the instruction cannot be decoded. 262 // On success, returns a pair containing the next PC, plus the length of the 263 // expression remaining to be evaluated. 264 std::pair<EvalResult, StringRef> evalNextPC(StringRef Expr) const { 265 if (!Expr.startswith("(")) 266 return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), ""); 267 StringRef RemainingExpr = Expr.substr(1).ltrim(); 268 StringRef Symbol; 269 std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr); 270 271 if (!Checker.checkSymbolIsValidForLoad(Symbol)) 272 return std::make_pair(EvalResult(("Cannot decode unknown symbol '" 273 + Symbol + "'").str()), 274 ""); 275 276 if (!RemainingExpr.startswith(")")) 277 return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr, 278 "expected ')'"), 279 ""); 280 RemainingExpr = RemainingExpr.substr(1).ltrim(); 281 282 MCInst Inst; 283 uint64_t Size; 284 if (!decodeInst(Symbol, Inst, Size)) 285 return std::make_pair(EvalResult(("Couldn't decode instruction at '" + 286 Symbol + "'").str()), 287 ""); 288 uint64_t NextPC = Checker.getSymbolAddress(Symbol) + Size; 289 290 return std::make_pair(EvalResult(NextPC), RemainingExpr); 291 } 292 293 // Evaluate an identiefer expr, which may be a symbol, or a call to 294 // one of the builtin functions: get_insn_opcode or get_insn_length. 295 // Return the result, plus the expression remaining to be parsed. 296 std::pair<EvalResult, StringRef> evalIdentifierExpr(StringRef Expr) const { 297 StringRef Symbol; 298 StringRef RemainingExpr; 299 std::tie(Symbol, RemainingExpr) = parseSymbol(Expr); 300 301 // Check for builtin function calls. 302 if (Symbol == "decode_operand") 303 return evalDecodeOperand(RemainingExpr); 304 else if (Symbol == "next_pc") 305 return evalNextPC(RemainingExpr); 306 307 // Looks like a plain symbol reference. 308 return std::make_pair(EvalResult(Checker.getSymbolAddress(Symbol)), 309 RemainingExpr); 310 } 311 312 // Parse a number (hexadecimal or decimal) and return a (string, string) 313 // pair representing the number and the expression remaining to be parsed. 314 std::pair<StringRef, StringRef> parseNumberString(StringRef Expr) const { 315 size_t FirstNonDigit = StringRef::npos; 316 if (Expr.startswith("0x")) { 317 FirstNonDigit = Expr.find_first_not_of("0123456789abcdefABCDEF", 2); 318 if (FirstNonDigit == StringRef::npos) 319 FirstNonDigit = Expr.size(); 320 } else { 321 FirstNonDigit = Expr.find_first_not_of("0123456789"); 322 if (FirstNonDigit == StringRef::npos) 323 FirstNonDigit = Expr.size(); 324 } 325 return std::make_pair(Expr.substr(0, FirstNonDigit), 326 Expr.substr(FirstNonDigit)); 327 } 328 329 // Evaluate a constant numeric expression (hexidecimal or decimal) and 330 // return a pair containing the result, and the expression remaining to be 331 // evaluated. 332 std::pair<EvalResult, StringRef> evalNumberExpr(StringRef Expr) const { 333 StringRef ValueStr; 334 StringRef RemainingExpr; 335 std::tie(ValueStr, RemainingExpr) = parseNumberString(Expr); 336 337 if (ValueStr.empty() || !isdigit(ValueStr[0])) 338 return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr, 339 "expected number"), 340 ""); 341 uint64_t Value; 342 ValueStr.getAsInteger(0, Value); 343 return std::make_pair(EvalResult(Value), RemainingExpr); 344 } 345 346 // Evaluate an expression of the form "(<expr>)" and return a pair 347 // containing the result of evaluating <expr>, plus the expression 348 // remaining to be parsed. 349 std::pair<EvalResult, StringRef> evalParensExpr(StringRef Expr) const { 350 assert(Expr.startswith("(") && "Not a parenthesized expression"); 351 EvalResult SubExprResult; 352 StringRef RemainingExpr; 353 std::tie(SubExprResult, RemainingExpr) = 354 evalComplexExpr(evalSimpleExpr(Expr.substr(1).ltrim())); 355 if (SubExprResult.hasError()) 356 return std::make_pair(SubExprResult, ""); 357 if (!RemainingExpr.startswith(")")) 358 return std::make_pair(unexpectedToken(RemainingExpr, Expr, 359 "expected ')'"), 360 ""); 361 RemainingExpr = RemainingExpr.substr(1).ltrim(); 362 return std::make_pair(SubExprResult, RemainingExpr); 363 } 364 365 // Evaluate an expression in one of the following forms: 366 // *{<number>}<symbol> 367 // *{<number>}(<symbol> + <number>) 368 // *{<number>}(<symbol> - <number>) 369 // Return a pair containing the result, plus the expression remaining to be 370 // parsed. 371 std::pair<EvalResult, StringRef> evalLoadExpr(StringRef Expr) const { 372 assert(Expr.startswith("*") && "Not a load expression"); 373 StringRef RemainingExpr = Expr.substr(1).ltrim(); 374 // Parse read size. 375 if (!RemainingExpr.startswith("{")) 376 return std::make_pair(EvalResult("Expected '{' following '*'."), ""); 377 RemainingExpr = RemainingExpr.substr(1).ltrim(); 378 EvalResult ReadSizeExpr; 379 std::tie(ReadSizeExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); 380 if (ReadSizeExpr.hasError()) 381 return std::make_pair(ReadSizeExpr, RemainingExpr); 382 uint64_t ReadSize = ReadSizeExpr.getValue(); 383 if (ReadSize < 1 || ReadSize > 8) 384 return std::make_pair(EvalResult("Invalid size for dereference."), ""); 385 if (!RemainingExpr.startswith("}")) 386 return std::make_pair(EvalResult("Missing '}' for dereference."), ""); 387 RemainingExpr = RemainingExpr.substr(1).ltrim(); 388 389 // Check for '(symbol +/- constant)' form. 390 bool SymbolPlusConstant = false; 391 if (RemainingExpr.startswith("(")) { 392 SymbolPlusConstant = true; 393 RemainingExpr = RemainingExpr.substr(1).ltrim(); 394 } 395 396 // Read symbol. 397 StringRef Symbol; 398 std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr); 399 400 if (!Checker.checkSymbolIsValidForLoad(Symbol)) 401 return std::make_pair(EvalResult(("Cannot dereference unknown symbol '" 402 + Symbol + "'").str()), 403 ""); 404 405 // Set up defaut offset. 406 int64_t Offset = 0; 407 408 // Handle "+/- constant)" portion if necessary. 409 if (SymbolPlusConstant) { 410 char OpChar = RemainingExpr[0]; 411 if (OpChar != '+' && OpChar != '-') 412 return std::make_pair(EvalResult("Invalid operator in load address."), 413 ""); 414 RemainingExpr = RemainingExpr.substr(1).ltrim(); 415 416 EvalResult OffsetExpr; 417 std::tie(OffsetExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); 418 419 Offset = (OpChar == '+') ? 420 OffsetExpr.getValue() : -1 * OffsetExpr.getValue(); 421 422 if (!RemainingExpr.startswith(")")) 423 return std::make_pair(EvalResult("Missing ')' in load address."), 424 ""); 425 426 RemainingExpr = RemainingExpr.substr(1).ltrim(); 427 } 428 429 return std::make_pair( 430 EvalResult(Checker.readMemoryAtSymbol(Symbol, Offset, ReadSize)), 431 RemainingExpr); 432 } 433 434 // Evaluate a "simple" expression. This is any expression that _isn't_ an 435 // un-parenthesized binary expression. 436 // 437 // "Simple" expressions can be optionally bit-sliced. See evalSlicedExpr. 438 // 439 // Returns a pair containing the result of the evaluation, plus the 440 // expression remaining to be parsed. 441 std::pair<EvalResult, StringRef> evalSimpleExpr(StringRef Expr) const { 442 EvalResult SubExprResult; 443 StringRef RemainingExpr; 444 445 if (Expr.empty()) 446 return std::make_pair(EvalResult("Unexpected end of expression"), ""); 447 448 if (Expr[0] == '(') 449 std::tie(SubExprResult, RemainingExpr) = evalParensExpr(Expr); 450 else if (Expr[0] == '*') 451 std::tie(SubExprResult, RemainingExpr) = evalLoadExpr(Expr); 452 else if (isalpha(Expr[0])) 453 std::tie(SubExprResult, RemainingExpr) = evalIdentifierExpr(Expr); 454 else if (isdigit(Expr[0])) 455 std::tie(SubExprResult, RemainingExpr) = evalNumberExpr(Expr); 456 457 if (SubExprResult.hasError()) 458 return std::make_pair(SubExprResult, RemainingExpr); 459 460 // Evaluate bit-slice if present. 461 if (RemainingExpr.startswith("[")) 462 std::tie(SubExprResult, RemainingExpr) = 463 evalSliceExpr(std::make_pair(SubExprResult, RemainingExpr)); 464 465 return std::make_pair(SubExprResult, RemainingExpr); 466 } 467 468 // Evaluate a bit-slice of an expression. 469 // A bit-slice has the form "<expr>[high:low]". The result of evaluating a 470 // slice is the bits between high and low (inclusive) in the original 471 // expression, right shifted so that the "low" bit is in position 0 in the 472 // result. 473 // Returns a pair containing the result of the slice operation, plus the 474 // expression remaining to be parsed. 475 std::pair<EvalResult, StringRef> evalSliceExpr( 476 std::pair<EvalResult, StringRef> Ctx) const{ 477 EvalResult SubExprResult; 478 StringRef RemainingExpr; 479 std::tie(SubExprResult, RemainingExpr) = Ctx; 480 481 assert(RemainingExpr.startswith("[") && "Not a slice expr."); 482 RemainingExpr = RemainingExpr.substr(1).ltrim(); 483 484 EvalResult HighBitExpr; 485 std::tie(HighBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); 486 487 if (HighBitExpr.hasError()) 488 return std::make_pair(HighBitExpr, RemainingExpr); 489 490 if (!RemainingExpr.startswith(":")) 491 return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr, 492 "expected ':'"), 493 ""); 494 RemainingExpr = RemainingExpr.substr(1).ltrim(); 495 496 EvalResult LowBitExpr; 497 std::tie(LowBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); 498 499 if (LowBitExpr.hasError()) 500 return std::make_pair(LowBitExpr, RemainingExpr); 501 502 if (!RemainingExpr.startswith("]")) 503 return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr, 504 "expected ']'"), 505 ""); 506 RemainingExpr = RemainingExpr.substr(1).ltrim(); 507 508 unsigned HighBit = HighBitExpr.getValue(); 509 unsigned LowBit = LowBitExpr.getValue(); 510 uint64_t Mask = ((uint64_t)1 << (HighBit - LowBit + 1)) - 1; 511 uint64_t SlicedValue = (SubExprResult.getValue() >> LowBit) & Mask; 512 return std::make_pair(EvalResult(SlicedValue), RemainingExpr); 513 } 514 515 // Evaluate a "complex" expression. 516 // Takes an already evaluated subexpression and checks for the presence of a 517 // binary operator, computing the result of the binary operation if one is 518 // found. Used to make arithmetic expressions left-associative. 519 // Returns a pair containing the ultimate result of evaluating the 520 // expression, plus the expression remaining to be evaluated. 521 std::pair<EvalResult, StringRef> evalComplexExpr( 522 std::pair<EvalResult, StringRef> Ctx) const { 523 EvalResult LHSResult; 524 StringRef RemainingExpr; 525 std::tie(LHSResult, RemainingExpr) = Ctx; 526 527 // If there was an error, or there's nothing left to evaluate, return the 528 // result. 529 if (LHSResult.hasError() || RemainingExpr == "") 530 return std::make_pair(LHSResult, RemainingExpr); 531 532 // Otherwise check if this is a binary expressioan. 533 BinOpToken BinOp; 534 std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr); 535 536 // If this isn't a recognized expression just return. 537 if (BinOp == BinOpToken::Invalid) 538 return std::make_pair(LHSResult, RemainingExpr); 539 540 // This is a recognized bin-op. Evaluate the RHS, then evaluate the binop. 541 EvalResult RHSResult; 542 std::tie(RHSResult, RemainingExpr) = evalSimpleExpr(RemainingExpr); 543 544 // If there was an error evaluating the RHS, return it. 545 if (RHSResult.hasError()) 546 return std::make_pair(RHSResult, RemainingExpr); 547 548 // This is a binary expression - evaluate and try to continue as a 549 // complex expr. 550 EvalResult ThisResult(computeBinOpResult(BinOp, LHSResult, RHSResult)); 551 552 return evalComplexExpr(std::make_pair(ThisResult, RemainingExpr)); 553 } 554 555 bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size) const { 556 MCDisassembler *Dis = Checker.Disassembler; 557 StringRef SectionMem = Checker.getSubsectionStartingAt(Symbol); 558 StringRefMemoryObject SectionBytes(SectionMem, 0); 559 560 MCDisassembler::DecodeStatus S = 561 Dis->getInstruction(Inst, Size, SectionBytes, 0, nulls(), nulls()); 562 563 return (S == MCDisassembler::Success); 564 } 565 566 }; 567 568 } 569 570 bool RuntimeDyldChecker::check(StringRef CheckExpr) const { 571 CheckExpr = CheckExpr.trim(); 572 DEBUG(llvm::dbgs() << "RuntimeDyldChecker: Checking '" << CheckExpr 573 << "'...\n"); 574 RuntimeDyldCheckerExprEval P(*this, ErrStream); 575 bool Result = P.evaluate(CheckExpr); 576 (void)Result; 577 DEBUG(llvm::dbgs() << "RuntimeDyldChecker: '" << CheckExpr << "' " 578 << (Result ? "passed" : "FAILED") << ".\n"); 579 return Result; 580 } 581 582 bool RuntimeDyldChecker::checkAllRulesInBuffer(StringRef RulePrefix, 583 MemoryBuffer* MemBuf) const { 584 bool DidAllTestsPass = true; 585 unsigned NumRules = 0; 586 587 const char *LineStart = MemBuf->getBufferStart(); 588 589 // Eat whitespace. 590 while (LineStart != MemBuf->getBufferEnd() && 591 std::isspace(*LineStart)) 592 ++LineStart; 593 594 while (LineStart != MemBuf->getBufferEnd() && *LineStart != '\0') { 595 const char *LineEnd = LineStart; 596 while (LineEnd != MemBuf->getBufferEnd() && 597 *LineEnd != '\r' && *LineEnd != '\n') 598 ++LineEnd; 599 600 StringRef Line(LineStart, LineEnd - LineStart); 601 if (Line.startswith(RulePrefix)) { 602 DidAllTestsPass &= check(Line.substr(RulePrefix.size())); 603 ++NumRules; 604 } 605 606 // Eat whitespace. 607 LineStart = LineEnd; 608 while (LineStart != MemBuf->getBufferEnd() && 609 std::isspace(*LineStart)) 610 ++LineStart; 611 } 612 return DidAllTestsPass && (NumRules != 0); 613 } 614 615 bool RuntimeDyldChecker::checkSymbolIsValidForLoad(StringRef Symbol) const { 616 return RTDyld.getSymbolAddress(Symbol) != nullptr; 617 } 618 619 uint64_t RuntimeDyldChecker::getSymbolAddress(StringRef Symbol) const { 620 return RTDyld.getAnySymbolRemoteAddress(Symbol); 621 } 622 623 uint64_t RuntimeDyldChecker::readMemoryAtSymbol(StringRef Symbol, 624 int64_t Offset, 625 unsigned Size) const { 626 uint8_t *Src = RTDyld.getSymbolAddress(Symbol); 627 uint64_t Result = 0; 628 memcpy(&Result, Src + Offset, Size); 629 return Result; 630 } 631 632 StringRef RuntimeDyldChecker::getSubsectionStartingAt(StringRef Name) const { 633 RuntimeDyldImpl::SymbolTableMap::const_iterator pos = 634 RTDyld.GlobalSymbolTable.find(Name); 635 if (pos == RTDyld.GlobalSymbolTable.end()) 636 return StringRef(); 637 RuntimeDyldImpl::SymbolLoc Loc = pos->second; 638 uint8_t *SectionAddr = RTDyld.getSectionAddress(Loc.first); 639 return StringRef(reinterpret_cast<const char*>(SectionAddr) + Loc.second, 640 RTDyld.Sections[Loc.first].Size - Loc.second); 641 } 642