57 size_t EQIdx = Expr.
find(
'=');
59 ParseContext OutsideLoad(
false);
65 std::tie(LHSResult, RemainingExpr) =
66 evalComplexExpr(evalSimpleExpr(LHSExpr, OutsideLoad), OutsideLoad);
67 if (LHSResult.hasError())
68 return handleError(Expr, LHSResult);
69 if (RemainingExpr !=
"")
70 return handleError(Expr, unexpectedToken(RemainingExpr, LHSExpr,
""));
75 std::tie(RHSResult, RemainingExpr) =
76 evalComplexExpr(evalSimpleExpr(RHSExpr, OutsideLoad), OutsideLoad);
77 if (RHSResult.hasError())
78 return handleError(Expr, RHSResult);
79 if (RemainingExpr !=
"")
80 return handleError(Expr, unexpectedToken(RemainingExpr, RHSExpr,
""));
82 if (LHSResult.getValue() != RHSResult.getValue()) {
83 Checker.ErrStream <<
"Expression '" << Expr <<
"' is false: "
84 <<
format(
"0x%" PRIx64, LHSResult.getValue())
85 <<
" != " <<
format(
"0x%" PRIx64, RHSResult.getValue())
101 ParseContext(
bool IsInsideLoad) : IsInsideLoad(IsInsideLoad) {}
104 const RuntimeDyldCheckerImpl &Checker;
106 enum class BinOpToken :
unsigned {
118 EvalResult() : Value(0) {}
119 EvalResult(uint64_t Value) : Value(Value) {}
120 EvalResult(std::string ErrorMsg)
121 : Value(0), ErrorMsg(std::
move(ErrorMsg)) {}
122 uint64_t getValue()
const {
return Value; }
123 bool hasError()
const {
return ErrorMsg !=
""; }
124 const std::string &getErrorMsg()
const {
return ErrorMsg; }
128 std::string ErrorMsg;
131 StringRef getTokenForError(StringRef Expr)
const {
135 StringRef Token, Remaining;
136 if (isalpha(Expr[0]))
137 std::tie(Token, Remaining) = parseSymbol(Expr);
138 else if (isdigit(Expr[0]))
139 std::tie(Token, Remaining) = parseNumberString(Expr);
144 Token = Expr.
substr(0, TokLen);
149 EvalResult unexpectedToken(StringRef TokenStart, StringRef SubExpr,
150 StringRef ErrText)
const {
151 std::string ErrorMsg(
"Encountered unexpected token '");
152 ErrorMsg += getTokenForError(TokenStart);
154 ErrorMsg +=
"' while parsing subexpression '";
162 return EvalResult(std::move(ErrorMsg));
165 bool handleError(StringRef Expr,
const EvalResult &R)
const {
166 assert(
R.hasError() &&
"Not an error result.");
167 Checker.ErrStream <<
"Error evaluating expression '" << Expr
168 <<
"': " <<
R.getErrorMsg() <<
"\n";
172 std::pair<BinOpToken, StringRef> parseBinOpToken(StringRef Expr)
const {
174 return std::make_pair(BinOpToken::Invalid,
"");
178 return std::make_pair(BinOpToken::ShiftLeft, Expr.
substr(2).
ltrim());
180 return std::make_pair(BinOpToken::ShiftRight, Expr.
substr(2).
ltrim());
186 return std::make_pair(BinOpToken::Invalid, Expr);
188 Op = BinOpToken::Add;
191 Op = BinOpToken::Sub;
194 Op = BinOpToken::BitwiseAnd;
197 Op = BinOpToken::BitwiseOr;
204 EvalResult computeBinOpResult(BinOpToken
Op,
const EvalResult &LHSResult,
205 const EvalResult &RHSResult)
const {
209 case BinOpToken::Add:
210 return EvalResult(LHSResult.getValue() + RHSResult.getValue());
211 case BinOpToken::Sub:
212 return EvalResult(LHSResult.getValue() - RHSResult.getValue());
213 case BinOpToken::BitwiseAnd:
214 return EvalResult(LHSResult.getValue() & RHSResult.getValue());
215 case BinOpToken::BitwiseOr:
216 return EvalResult(LHSResult.getValue() | RHSResult.getValue());
217 case BinOpToken::ShiftLeft:
218 return EvalResult(LHSResult.getValue() << RHSResult.getValue());
219 case BinOpToken::ShiftRight:
220 return EvalResult(LHSResult.getValue() >> RHSResult.getValue());
226 std::pair<StringRef, StringRef> parseSymbol(StringRef Expr)
const {
228 "abcdefghijklmnopqrstuvwxyz"
229 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
231 return std::make_pair(Expr.
substr(0, FirstNonSymbol),
241 std::pair<EvalResult, StringRef> evalDecodeOperand(StringRef Expr)
const {
243 return std::make_pair(unexpectedToken(Expr, Expr,
"expected '('"),
"");
246 std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
248 if (!Checker.isSymbolValid(Symbol))
249 return std::make_pair(
250 EvalResult((
"Cannot decode unknown symbol '" + Symbol +
"'").str()),
256 std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr);
258 case BinOpToken::Add: {
260 std::tie(
Number, RemainingExpr) = evalNumberExpr(RemainingExpr);
264 case BinOpToken::Invalid:
267 return std::make_pair(
268 unexpectedToken(RemainingExpr, RemainingExpr,
269 "expected '+' for offset or ',' if no offset"),
274 return std::make_pair(
275 unexpectedToken(RemainingExpr, RemainingExpr,
"expected ','"),
"");
278 EvalResult OpIdxExpr;
279 std::tie(OpIdxExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
280 if (OpIdxExpr.hasError())
281 return std::make_pair(OpIdxExpr,
"");
284 return std::make_pair(
285 unexpectedToken(RemainingExpr, RemainingExpr,
"expected ')'"),
"");
291 return std::make_pair(
292 EvalResult((
"Couldn't decode instruction at '" + Symbol +
"'").str()),
295 unsigned OpIdx = OpIdxExpr.getValue();
297 auto printInst = [
this](StringRef
Symbol, MCInst Inst,
298 raw_string_ostream &ErrMsgStream) {
299 auto TT = Checker.getTripleForSymbol(Checker.getTargetFlag(Symbol));
300 auto TI = getTargetInfo(TT, Checker.getCPU(), Checker.getFeatures());
301 if (
auto E = TI.takeError()) {
302 errs() <<
"Error obtaining instruction printer: "
306 Inst.dump_pretty(ErrMsgStream, TI->InstPrinter.get());
312 raw_string_ostream ErrMsgStream(ErrMsg);
313 ErrMsgStream <<
"Invalid operand index '" <<
format(
"%i",
OpIdx)
314 <<
"' for instruction '" <<
Symbol
315 <<
"'. Instruction has only "
316 <<
format(
"%i", Inst.getNumOperands())
317 <<
" operands.\nInstruction is:\n ";
319 printInst(Symbol, Inst, ErrMsgStream);
320 return {EvalResult(std::move(ErrMsg)),
""};
323 const MCOperand &
Op = Inst.getOperand(
OpIdx);
326 raw_string_ostream ErrMsgStream(ErrMsg);
327 ErrMsgStream <<
"Operand '" <<
format(
"%i",
OpIdx) <<
"' of instruction '"
328 <<
Symbol <<
"' is not an immediate.\nInstruction is:\n ";
330 printInst(Symbol, Inst, ErrMsgStream);
331 return {EvalResult(std::move(ErrMsg)),
""};
334 return std::make_pair(EvalResult(
Op.getImm()), RemainingExpr);
343 std::pair<EvalResult, StringRef> evalNextPC(StringRef Expr,
344 ParseContext PCtx)
const {
346 return std::make_pair(unexpectedToken(Expr, Expr,
"expected '('"),
"");
349 std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
351 if (!Checker.isSymbolValid(Symbol))
352 return std::make_pair(
353 EvalResult((
"Cannot decode unknown symbol '" + Symbol +
"'").str()),
357 return std::make_pair(
358 unexpectedToken(RemainingExpr, RemainingExpr,
"expected ')'"),
"");
363 if (!decodeInst(Symbol, Inst, InstSize, 0))
364 return std::make_pair(
365 EvalResult((
"Couldn't decode instruction at '" + Symbol +
"'").str()),
368 uint64_t SymbolAddr = PCtx.IsInsideLoad
369 ? Checker.getSymbolLocalAddr(Symbol)
370 : Checker.getSymbolRemoteAddr(Symbol);
374 auto TT = Checker.getTripleForSymbol(Checker.getTargetFlag(Symbol));
377 uint64_t NextPC = SymbolAddr + InstSize + PCOffset;
379 return std::make_pair(EvalResult(NextPC), RemainingExpr);
387 std::pair<EvalResult, StringRef>
388 evalStubOrGOTAddr(StringRef Expr, ParseContext PCtx,
bool IsStubAddr)
const {
390 return std::make_pair(unexpectedToken(Expr, Expr,
"expected '('"),
"");
395 StringRef StubContainerName;
396 size_t ComaIdx = RemainingExpr.
find(
',');
397 StubContainerName = RemainingExpr.
substr(0, ComaIdx).
rtrim();
398 RemainingExpr = RemainingExpr.
substr(ComaIdx).
ltrim();
401 return std::make_pair(
402 unexpectedToken(RemainingExpr, Expr,
"expected ','"),
"");
406 std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
409 StringRef KindNameFilter;
412 size_t ClosingBracket = RemainingExpr.
find(
")");
413 KindNameFilter = RemainingExpr.
substr(0, ClosingBracket);
414 RemainingExpr = RemainingExpr.
substr(ClosingBracket);
418 return std::make_pair(
419 unexpectedToken(RemainingExpr, Expr,
"expected ')'"),
"");
423 std::string ErrorMsg;
424 std::tie(StubAddr, ErrorMsg) =
425 Checker.getStubOrGOTAddrFor(StubContainerName, Symbol, KindNameFilter,
426 PCtx.IsInsideLoad, IsStubAddr);
429 return std::make_pair(EvalResult(ErrorMsg),
"");
431 return std::make_pair(EvalResult(StubAddr), RemainingExpr);
434 std::pair<EvalResult, StringRef> evalSectionAddr(StringRef Expr,
435 ParseContext PCtx)
const {
437 return std::make_pair(unexpectedToken(Expr, Expr,
"expected '('"),
"");
443 size_t ComaIdx = RemainingExpr.
find(
',');
444 FileName = RemainingExpr.
substr(0, ComaIdx).
rtrim();
445 RemainingExpr = RemainingExpr.
substr(ComaIdx).
ltrim();
448 return std::make_pair(
449 unexpectedToken(RemainingExpr, Expr,
"expected ','"),
"");
453 size_t CloseParensIdx = RemainingExpr.
find(
')');
455 RemainingExpr = RemainingExpr.
substr(CloseParensIdx).
ltrim();
458 return std::make_pair(
459 unexpectedToken(RemainingExpr, Expr,
"expected ')'"),
"");
463 std::string ErrorMsg;
464 std::tie(StubAddr, ErrorMsg) = Checker.getSectionAddr(
465 FileName, SectionName, PCtx.IsInsideLoad);
468 return std::make_pair(EvalResult(ErrorMsg),
"");
470 return std::make_pair(EvalResult(StubAddr), RemainingExpr);
476 std::pair<EvalResult, StringRef> evalIdentifierExpr(StringRef Expr,
477 ParseContext PCtx)
const {
479 StringRef RemainingExpr;
480 std::tie(Symbol, RemainingExpr) = parseSymbol(Expr);
483 if (Symbol ==
"decode_operand")
484 return evalDecodeOperand(RemainingExpr);
485 else if (Symbol ==
"next_pc")
486 return evalNextPC(RemainingExpr, PCtx);
487 else if (Symbol ==
"stub_addr")
488 return evalStubOrGOTAddr(RemainingExpr, PCtx,
true);
489 else if (Symbol ==
"got_addr")
490 return evalStubOrGOTAddr(RemainingExpr, PCtx,
false);
491 else if (Symbol ==
"section_addr")
492 return evalSectionAddr(RemainingExpr, PCtx);
494 if (!Checker.isSymbolValid(Symbol)) {
495 std::string ErrMsg(
"No known address for symbol '");
498 if (
Symbol.starts_with(
"L"))
499 ErrMsg +=
" (this appears to be an assembler local label - "
500 " perhaps drop the 'L'?)";
502 return std::make_pair(EvalResult(ErrMsg),
"");
508 uint64_t
Value = PCtx.IsInsideLoad ? Checker.getSymbolLocalAddr(Symbol)
509 : Checker.getSymbolRemoteAddr(Symbol);
512 return std::make_pair(EvalResult(
Value), RemainingExpr);
517 std::pair<StringRef, StringRef> parseNumberString(StringRef Expr)
const {
522 FirstNonDigit = Expr.
size();
526 FirstNonDigit = Expr.
size();
528 return std::make_pair(Expr.
substr(0, FirstNonDigit),
529 Expr.
substr(FirstNonDigit));
535 std::pair<EvalResult, StringRef> evalNumberExpr(StringRef Expr)
const {
537 StringRef RemainingExpr;
538 std::tie(ValueStr, RemainingExpr) = parseNumberString(Expr);
540 if (ValueStr.
empty() || !isdigit(ValueStr[0]))
541 return std::make_pair(
542 unexpectedToken(RemainingExpr, RemainingExpr,
"expected number"),
"");
545 return std::make_pair(EvalResult(
Value), RemainingExpr);
551 std::pair<EvalResult, StringRef> evalParensExpr(StringRef Expr,
552 ParseContext PCtx)
const {
554 EvalResult SubExprResult;
555 StringRef RemainingExpr;
556 std::tie(SubExprResult, RemainingExpr) =
557 evalComplexExpr(evalSimpleExpr(Expr.
substr(1).
ltrim(), PCtx), PCtx);
558 if (SubExprResult.hasError())
559 return std::make_pair(SubExprResult,
"");
561 return std::make_pair(
562 unexpectedToken(RemainingExpr, Expr,
"expected ')'"),
"");
564 return std::make_pair(SubExprResult, RemainingExpr);
571 std::pair<EvalResult, StringRef> evalLoadExpr(StringRef Expr)
const {
577 return std::make_pair(EvalResult(
"Expected '{' following '*'."),
"");
579 EvalResult ReadSizeExpr;
580 std::tie(ReadSizeExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
581 if (ReadSizeExpr.hasError())
582 return std::make_pair(ReadSizeExpr, RemainingExpr);
583 uint64_t ReadSize = ReadSizeExpr.getValue();
584 if (ReadSize < 1 || ReadSize > 8)
585 return std::make_pair(EvalResult(
"Invalid size for dereference."),
"");
587 return std::make_pair(EvalResult(
"Missing '}' for dereference."),
"");
591 ParseContext LoadCtx(
true);
592 EvalResult LoadAddrExprResult;
593 std::tie(LoadAddrExprResult, RemainingExpr) =
594 evalComplexExpr(evalSimpleExpr(RemainingExpr, LoadCtx), LoadCtx);
596 if (LoadAddrExprResult.hasError())
597 return std::make_pair(LoadAddrExprResult,
"");
599 uint64_t LoadAddr = LoadAddrExprResult.getValue();
604 return std::make_pair(0, RemainingExpr);
606 return std::make_pair(
607 EvalResult(Checker.readMemoryAtAddr(LoadAddr, ReadSize)),
618 std::pair<EvalResult, StringRef> evalSimpleExpr(StringRef Expr,
619 ParseContext PCtx)
const {
620 EvalResult SubExprResult;
621 StringRef RemainingExpr;
624 return std::make_pair(EvalResult(
"Unexpected end of expression"),
"");
627 std::tie(SubExprResult, RemainingExpr) = evalParensExpr(Expr, PCtx);
628 else if (Expr[0] ==
'*')
629 std::tie(SubExprResult, RemainingExpr) = evalLoadExpr(Expr);
630 else if (isalpha(Expr[0]) || Expr[0] ==
'_')
631 std::tie(SubExprResult, RemainingExpr) = evalIdentifierExpr(Expr, PCtx);
632 else if (isdigit(Expr[0]))
633 std::tie(SubExprResult, RemainingExpr) = evalNumberExpr(Expr);
635 return std::make_pair(
636 unexpectedToken(Expr, Expr,
637 "expected '(', '*', identifier, or number"),
"");
639 if (SubExprResult.hasError())
640 return std::make_pair(SubExprResult, RemainingExpr);
644 std::tie(SubExprResult, RemainingExpr) =
645 evalSliceExpr(std::make_pair(SubExprResult, RemainingExpr));
647 return std::make_pair(SubExprResult, RemainingExpr);
657 std::pair<EvalResult, StringRef>
658 evalSliceExpr(
const std::pair<EvalResult, StringRef> &Ctx)
const {
659 EvalResult SubExprResult;
660 StringRef RemainingExpr;
661 std::tie(SubExprResult, RemainingExpr) = Ctx;
666 EvalResult HighBitExpr;
667 std::tie(HighBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
669 if (HighBitExpr.hasError())
670 return std::make_pair(HighBitExpr, RemainingExpr);
673 return std::make_pair(
674 unexpectedToken(RemainingExpr, RemainingExpr,
"expected ':'"),
"");
677 EvalResult LowBitExpr;
678 std::tie(LowBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
680 if (LowBitExpr.hasError())
681 return std::make_pair(LowBitExpr, RemainingExpr);
684 return std::make_pair(
685 unexpectedToken(RemainingExpr, RemainingExpr,
"expected ']'"),
"");
688 unsigned HighBit = HighBitExpr.getValue();
689 unsigned LowBit = LowBitExpr.getValue();
690 uint64_t
Mask = ((uint64_t)1 << (HighBit - LowBit + 1)) - 1;
691 uint64_t SlicedValue = (SubExprResult.getValue() >> LowBit) &
Mask;
692 return std::make_pair(EvalResult(SlicedValue), RemainingExpr);
701 std::pair<EvalResult, StringRef>
702 evalComplexExpr(
const std::pair<EvalResult, StringRef> &LHSAndRemaining,
703 ParseContext PCtx)
const {
704 EvalResult LHSResult;
705 StringRef RemainingExpr;
706 std::tie(LHSResult, RemainingExpr) = LHSAndRemaining;
710 if (LHSResult.hasError() || RemainingExpr ==
"")
711 return std::make_pair(LHSResult, RemainingExpr);
715 std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr);
718 if (BinOp == BinOpToken::Invalid)
719 return std::make_pair(LHSResult, RemainingExpr);
722 EvalResult RHSResult;
723 std::tie(RHSResult, RemainingExpr) = evalSimpleExpr(RemainingExpr, PCtx);
726 if (RHSResult.hasError())
727 return std::make_pair(RHSResult, RemainingExpr);
731 EvalResult ThisResult(computeBinOpResult(BinOp, LHSResult, RHSResult));
733 return evalComplexExpr(std::make_pair(ThisResult, RemainingExpr), PCtx);
736 bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &
Size,
738 auto TT = Checker.getTripleForSymbol(Checker.getTargetFlag(Symbol));
739 auto TI = getTargetInfo(TT, Checker.getCPU(), Checker.getFeatures());
741 if (
auto E = TI.takeError()) {
742 errs() <<
"Error obtaining disassembler: " <<
toString(std::move(
E))
747 StringRef SymbolMem = Checker.getSymbolContent(Symbol);
752 TI->Disassembler->getInstruction(Inst,
Size, SymbolBytes, 0,
nulls());
757 Expected<TargetInfo> getTargetInfo(
const Triple &TT,
const StringRef &CPU,
758 const SubtargetFeatures &TF)
const {
759 std::string ErrorStr;
766 std::unique_ptr<MCSubtargetInfo> STI(
780 MCTargetOptions MCOptions;
781 std::unique_ptr<MCAsmInfo> MAI(
788 auto Ctx = std::make_unique<MCContext>(Triple(
TT.str()), MAI.get(),
789 MRI.get(), STI.get());
791 std::unique_ptr<MCDisassembler> Disassembler(
804 std::unique_ptr<MCInstPrinter> InstPrinter(
808 "Unable to create instruction printer for" +
TT.str(),
811 return TargetInfo({TheTarget, std::move(STI), std::move(
MRI),
812 std::move(MAI), std::move(Ctx), std::move(Disassembler),
813 std::move(MII), std::move(InstPrinter)});