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