LLVM 18.0.0git
RuntimeDyldChecker.cpp
Go to the documentation of this file.
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
11#include "llvm/ADT/STLExtras.h"
13#include "llvm/MC/MCAsmInfo.h"
14#include "llvm/MC/MCContext.h"
16#include "llvm/MC/MCInst.h"
18#include "llvm/MC/MCInstrInfo.h"
23#include "llvm/Support/Endian.h"
26#include "llvm/Support/Path.h"
27#include <cctype>
28#include <memory>
29#include <utility>
30
31#define DEBUG_TYPE "rtdyld"
32
33using namespace llvm;
34
35namespace {
36struct TargetInfo {
37 const Target *TheTarget;
38 std::unique_ptr<MCSubtargetInfo> STI;
39 std::unique_ptr<MCRegisterInfo> MRI;
40 std::unique_ptr<MCAsmInfo> MAI;
41 std::unique_ptr<MCContext> Ctx;
42 std::unique_ptr<MCDisassembler> Disassembler;
43 std::unique_ptr<MCInstrInfo> MII;
44 std::unique_ptr<MCInstPrinter> InstPrinter;
45};
46} // anonymous namespace
47
48namespace llvm {
49
50// Helper class that implements the language evaluated by RuntimeDyldChecker.
52public:
54 raw_ostream &ErrStream)
55 : Checker(Checker) {}
56
57 bool evaluate(StringRef Expr) const {
58 // Expect equality expression of the form 'LHS = RHS'.
59 Expr = Expr.trim();
60 size_t EQIdx = Expr.find('=');
61
62 ParseContext OutsideLoad(false);
63
64 // Evaluate LHS.
65 StringRef LHSExpr = Expr.substr(0, EQIdx).rtrim();
66 StringRef RemainingExpr;
67 EvalResult LHSResult;
68 std::tie(LHSResult, RemainingExpr) =
69 evalComplexExpr(evalSimpleExpr(LHSExpr, OutsideLoad), OutsideLoad);
70 if (LHSResult.hasError())
71 return handleError(Expr, LHSResult);
72 if (RemainingExpr != "")
73 return handleError(Expr, unexpectedToken(RemainingExpr, LHSExpr, ""));
74
75 // Evaluate RHS.
76 StringRef RHSExpr = Expr.substr(EQIdx + 1).ltrim();
77 EvalResult RHSResult;
78 std::tie(RHSResult, RemainingExpr) =
79 evalComplexExpr(evalSimpleExpr(RHSExpr, OutsideLoad), OutsideLoad);
80 if (RHSResult.hasError())
81 return handleError(Expr, RHSResult);
82 if (RemainingExpr != "")
83 return handleError(Expr, unexpectedToken(RemainingExpr, RHSExpr, ""));
84
85 if (LHSResult.getValue() != RHSResult.getValue()) {
86 Checker.ErrStream << "Expression '" << Expr << "' is false: "
87 << format("0x%" PRIx64, LHSResult.getValue())
88 << " != " << format("0x%" PRIx64, RHSResult.getValue())
89 << "\n";
90 return false;
91 }
92 return true;
93 }
94
95private:
96 // RuntimeDyldCheckerExprEval requires some context when parsing exprs. In
97 // particular, it needs to know whether a symbol is being evaluated in the
98 // context of a load, in which case we want the linker's local address for
99 // the symbol, or outside of a load, in which case we want the symbol's
100 // address in the remote target.
101
102 struct ParseContext {
103 bool IsInsideLoad;
104 ParseContext(bool IsInsideLoad) : IsInsideLoad(IsInsideLoad) {}
105 };
106
107 const RuntimeDyldCheckerImpl &Checker;
108
109 enum class BinOpToken : unsigned {
110 Invalid,
111 Add,
112 Sub,
114 BitwiseOr,
115 ShiftLeft,
116 ShiftRight
117 };
118
119 class EvalResult {
120 public:
121 EvalResult() : Value(0) {}
122 EvalResult(uint64_t Value) : Value(Value) {}
123 EvalResult(std::string ErrorMsg)
124 : Value(0), ErrorMsg(std::move(ErrorMsg)) {}
125 uint64_t getValue() const { return Value; }
126 bool hasError() const { return ErrorMsg != ""; }
127 const std::string &getErrorMsg() const { return ErrorMsg; }
128
129 private:
131 std::string ErrorMsg;
132 };
133
134 StringRef getTokenForError(StringRef Expr) const {
135 if (Expr.empty())
136 return "";
137
138 StringRef Token, Remaining;
139 if (isalpha(Expr[0]))
140 std::tie(Token, Remaining) = parseSymbol(Expr);
141 else if (isdigit(Expr[0]))
142 std::tie(Token, Remaining) = parseNumberString(Expr);
143 else {
144 unsigned TokLen = 1;
145 if (Expr.startswith("<<") || Expr.startswith(">>"))
146 TokLen = 2;
147 Token = Expr.substr(0, TokLen);
148 }
149 return Token;
150 }
151
152 EvalResult unexpectedToken(StringRef TokenStart, StringRef SubExpr,
153 StringRef ErrText) const {
154 std::string ErrorMsg("Encountered unexpected token '");
155 ErrorMsg += getTokenForError(TokenStart);
156 if (SubExpr != "") {
157 ErrorMsg += "' while parsing subexpression '";
158 ErrorMsg += SubExpr;
159 }
160 ErrorMsg += "'";
161 if (ErrText != "") {
162 ErrorMsg += " ";
163 ErrorMsg += ErrText;
164 }
165 return EvalResult(std::move(ErrorMsg));
166 }
167
168 bool handleError(StringRef Expr, const EvalResult &R) const {
169 assert(R.hasError() && "Not an error result.");
170 Checker.ErrStream << "Error evaluating expression '" << Expr
171 << "': " << R.getErrorMsg() << "\n";
172 return false;
173 }
174
175 std::pair<BinOpToken, StringRef> parseBinOpToken(StringRef Expr) const {
176 if (Expr.empty())
177 return std::make_pair(BinOpToken::Invalid, "");
178
179 // Handle the two 2-character tokens.
180 if (Expr.startswith("<<"))
181 return std::make_pair(BinOpToken::ShiftLeft, Expr.substr(2).ltrim());
182 if (Expr.startswith(">>"))
183 return std::make_pair(BinOpToken::ShiftRight, Expr.substr(2).ltrim());
184
185 // Handle one-character tokens.
186 BinOpToken Op;
187 switch (Expr[0]) {
188 default:
189 return std::make_pair(BinOpToken::Invalid, Expr);
190 case '+':
191 Op = BinOpToken::Add;
192 break;
193 case '-':
194 Op = BinOpToken::Sub;
195 break;
196 case '&':
197 Op = BinOpToken::BitwiseAnd;
198 break;
199 case '|':
200 Op = BinOpToken::BitwiseOr;
201 break;
202 }
203
204 return std::make_pair(Op, Expr.substr(1).ltrim());
205 }
206
207 EvalResult computeBinOpResult(BinOpToken Op, const EvalResult &LHSResult,
208 const EvalResult &RHSResult) const {
209 switch (Op) {
210 default:
211 llvm_unreachable("Tried to evaluate unrecognized operation.");
212 case BinOpToken::Add:
213 return EvalResult(LHSResult.getValue() + RHSResult.getValue());
214 case BinOpToken::Sub:
215 return EvalResult(LHSResult.getValue() - RHSResult.getValue());
216 case BinOpToken::BitwiseAnd:
217 return EvalResult(LHSResult.getValue() & RHSResult.getValue());
218 case BinOpToken::BitwiseOr:
219 return EvalResult(LHSResult.getValue() | RHSResult.getValue());
220 case BinOpToken::ShiftLeft:
221 return EvalResult(LHSResult.getValue() << RHSResult.getValue());
222 case BinOpToken::ShiftRight:
223 return EvalResult(LHSResult.getValue() >> RHSResult.getValue());
224 }
225 }
226
227 // Parse a symbol and return a (string, string) pair representing the symbol
228 // name and expression remaining to be parsed.
229 std::pair<StringRef, StringRef> parseSymbol(StringRef Expr) const {
230 size_t FirstNonSymbol = Expr.find_first_not_of("0123456789"
231 "abcdefghijklmnopqrstuvwxyz"
232 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
233 ":_.$");
234 return std::make_pair(Expr.substr(0, FirstNonSymbol),
235 Expr.substr(FirstNonSymbol).ltrim());
236 }
237
238 // Evaluate a call to decode_operand. Decode the instruction operand at the
239 // given symbol and get the value of the requested operand.
240 // Returns an error if the instruction cannot be decoded, or the requested
241 // operand is not an immediate.
242 // On success, returns a pair containing the value of the operand, plus
243 // the expression remaining to be evaluated.
244 std::pair<EvalResult, StringRef> evalDecodeOperand(StringRef Expr) const {
245 if (!Expr.startswith("("))
246 return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");
247 StringRef RemainingExpr = Expr.substr(1).ltrim();
249 std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
250
251 if (!Checker.isSymbolValid(Symbol))
252 return std::make_pair(
253 EvalResult(("Cannot decode unknown symbol '" + Symbol + "'").str()),
254 "");
255
256 // if there is an offset number expr
257 int64_t Offset = 0;
258 BinOpToken BinOp;
259 std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr);
260 switch (BinOp) {
261 case BinOpToken::Add: {
262 EvalResult Number;
263 std::tie(Number, RemainingExpr) = evalNumberExpr(RemainingExpr);
264 Offset = Number.getValue();
265 break;
266 }
267 case BinOpToken::Invalid:
268 break;
269 default:
270 return std::make_pair(
271 unexpectedToken(RemainingExpr, RemainingExpr,
272 "expected '+' for offset or ',' if no offset"),
273 "");
274 }
275
276 if (!RemainingExpr.startswith(","))
277 return std::make_pair(
278 unexpectedToken(RemainingExpr, RemainingExpr, "expected ','"), "");
279 RemainingExpr = RemainingExpr.substr(1).ltrim();
280
281 EvalResult OpIdxExpr;
282 std::tie(OpIdxExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
283 if (OpIdxExpr.hasError())
284 return std::make_pair(OpIdxExpr, "");
285
286 if (!RemainingExpr.startswith(")"))
287 return std::make_pair(
288 unexpectedToken(RemainingExpr, RemainingExpr, "expected ')'"), "");
289 RemainingExpr = RemainingExpr.substr(1).ltrim();
290
291 MCInst Inst;
293 if (!decodeInst(Symbol, Inst, Size, Offset))
294 return std::make_pair(
295 EvalResult(("Couldn't decode instruction at '" + Symbol + "'").str()),
296 "");
297
298 unsigned OpIdx = OpIdxExpr.getValue();
299
300 auto printInst = [this](StringRef Symbol, MCInst Inst,
301 raw_string_ostream &ErrMsgStream) {
302 auto TT = Checker.getTripleForSymbol(Checker.getTargetFlag(Symbol));
303 auto TI = getTargetInfo(TT, Checker.getCPU(), Checker.getFeatures());
304 if (auto E = TI.takeError()) {
305 errs() << "Error obtaining instruction printer: "
306 << toString(std::move(E)) << "\n";
307 return std::make_pair(EvalResult(ErrMsgStream.str()), "");
308 }
309 Inst.dump_pretty(ErrMsgStream, TI->InstPrinter.get());
310 return std::make_pair(EvalResult(ErrMsgStream.str()), "");
311 };
312
313 if (OpIdx >= Inst.getNumOperands()) {
314 std::string ErrMsg;
315 raw_string_ostream ErrMsgStream(ErrMsg);
316 ErrMsgStream << "Invalid operand index '" << format("%i", OpIdx)
317 << "' for instruction '" << Symbol
318 << "'. Instruction has only "
319 << format("%i", Inst.getNumOperands())
320 << " operands.\nInstruction is:\n ";
321
322 return printInst(Symbol, Inst, ErrMsgStream);
323 }
324
325 const MCOperand &Op = Inst.getOperand(OpIdx);
326 if (!Op.isImm()) {
327 std::string ErrMsg;
328 raw_string_ostream ErrMsgStream(ErrMsg);
329 ErrMsgStream << "Operand '" << format("%i", OpIdx) << "' of instruction '"
330 << Symbol << "' is not an immediate.\nInstruction is:\n ";
331
332 return printInst(Symbol, Inst, ErrMsgStream);
333 }
334
335 return std::make_pair(EvalResult(Op.getImm()), RemainingExpr);
336 }
337
338 // Evaluate a call to next_pc.
339 // Decode the instruction at the given symbol and return the following program
340 // counter.
341 // Returns an error if the instruction cannot be decoded.
342 // On success, returns a pair containing the next PC, plus of the
343 // expression remaining to be evaluated.
344 std::pair<EvalResult, StringRef> evalNextPC(StringRef Expr,
345 ParseContext PCtx) const {
346 if (!Expr.startswith("("))
347 return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");
348 StringRef RemainingExpr = Expr.substr(1).ltrim();
350 std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
351
352 if (!Checker.isSymbolValid(Symbol))
353 return std::make_pair(
354 EvalResult(("Cannot decode unknown symbol '" + Symbol + "'").str()),
355 "");
356
357 if (!RemainingExpr.startswith(")"))
358 return std::make_pair(
359 unexpectedToken(RemainingExpr, RemainingExpr, "expected ')'"), "");
360 RemainingExpr = RemainingExpr.substr(1).ltrim();
361
362 MCInst Inst;
363 uint64_t InstSize;
364 if (!decodeInst(Symbol, Inst, InstSize, 0))
365 return std::make_pair(
366 EvalResult(("Couldn't decode instruction at '" + Symbol + "'").str()),
367 "");
368
369 uint64_t SymbolAddr = PCtx.IsInsideLoad
370 ? Checker.getSymbolLocalAddr(Symbol)
371 : Checker.getSymbolRemoteAddr(Symbol);
372 uint64_t NextPC = SymbolAddr + InstSize;
373
374 return std::make_pair(EvalResult(NextPC), RemainingExpr);
375 }
376
377 // Evaluate a call to stub_addr/got_addr.
378 // Look up and return the address of the stub for the given
379 // (<file name>, <section name>, <symbol name>) tuple.
380 // On success, returns a pair containing the stub address, plus the expression
381 // remaining to be evaluated.
382 std::pair<EvalResult, StringRef>
383 evalStubOrGOTAddr(StringRef Expr, ParseContext PCtx, bool IsStubAddr) const {
384 if (!Expr.startswith("("))
385 return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");
386 StringRef RemainingExpr = Expr.substr(1).ltrim();
387
388 // Handle file-name specially, as it may contain characters that aren't
389 // legal for symbols.
390 StringRef StubContainerName;
391 size_t ComaIdx = RemainingExpr.find(',');
392 StubContainerName = RemainingExpr.substr(0, ComaIdx).rtrim();
393 RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim();
394
395 if (!RemainingExpr.startswith(","))
396 return std::make_pair(
397 unexpectedToken(RemainingExpr, Expr, "expected ','"), "");
398 RemainingExpr = RemainingExpr.substr(1).ltrim();
399
401 std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
402
403 if (!RemainingExpr.startswith(")"))
404 return std::make_pair(
405 unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");
406 RemainingExpr = RemainingExpr.substr(1).ltrim();
407
408 uint64_t StubAddr;
409 std::string ErrorMsg;
410 std::tie(StubAddr, ErrorMsg) = Checker.getStubOrGOTAddrFor(
411 StubContainerName, Symbol, PCtx.IsInsideLoad, IsStubAddr);
412
413 if (ErrorMsg != "")
414 return std::make_pair(EvalResult(ErrorMsg), "");
415
416 return std::make_pair(EvalResult(StubAddr), RemainingExpr);
417 }
418
419 std::pair<EvalResult, StringRef> evalSectionAddr(StringRef Expr,
420 ParseContext PCtx) const {
421 if (!Expr.startswith("("))
422 return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), "");
423 StringRef RemainingExpr = Expr.substr(1).ltrim();
424
425 // Handle file-name specially, as it may contain characters that aren't
426 // legal for symbols.
427 StringRef FileName;
428 size_t ComaIdx = RemainingExpr.find(',');
429 FileName = RemainingExpr.substr(0, ComaIdx).rtrim();
430 RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim();
431
432 if (!RemainingExpr.startswith(","))
433 return std::make_pair(
434 unexpectedToken(RemainingExpr, Expr, "expected ','"), "");
435 RemainingExpr = RemainingExpr.substr(1).ltrim();
436
438 size_t CloseParensIdx = RemainingExpr.find(')');
439 SectionName = RemainingExpr.substr(0, CloseParensIdx).rtrim();
440 RemainingExpr = RemainingExpr.substr(CloseParensIdx).ltrim();
441
442 if (!RemainingExpr.startswith(")"))
443 return std::make_pair(
444 unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");
445 RemainingExpr = RemainingExpr.substr(1).ltrim();
446
447 uint64_t StubAddr;
448 std::string ErrorMsg;
449 std::tie(StubAddr, ErrorMsg) = Checker.getSectionAddr(
450 FileName, SectionName, PCtx.IsInsideLoad);
451
452 if (ErrorMsg != "")
453 return std::make_pair(EvalResult(ErrorMsg), "");
454
455 return std::make_pair(EvalResult(StubAddr), RemainingExpr);
456 }
457
458 // Evaluate an identifier expr, which may be a symbol, or a call to
459 // one of the builtin functions: get_insn_opcode or get_insn_length.
460 // Return the result, plus the expression remaining to be parsed.
461 std::pair<EvalResult, StringRef> evalIdentifierExpr(StringRef Expr,
462 ParseContext PCtx) const {
464 StringRef RemainingExpr;
465 std::tie(Symbol, RemainingExpr) = parseSymbol(Expr);
466
467 // Check for builtin function calls.
468 if (Symbol == "decode_operand")
469 return evalDecodeOperand(RemainingExpr);
470 else if (Symbol == "next_pc")
471 return evalNextPC(RemainingExpr, PCtx);
472 else if (Symbol == "stub_addr")
473 return evalStubOrGOTAddr(RemainingExpr, PCtx, true);
474 else if (Symbol == "got_addr")
475 return evalStubOrGOTAddr(RemainingExpr, PCtx, false);
476 else if (Symbol == "section_addr")
477 return evalSectionAddr(RemainingExpr, PCtx);
478
479 if (!Checker.isSymbolValid(Symbol)) {
480 std::string ErrMsg("No known address for symbol '");
481 ErrMsg += Symbol;
482 ErrMsg += "'";
483 if (Symbol.startswith("L"))
484 ErrMsg += " (this appears to be an assembler local label - "
485 " perhaps drop the 'L'?)";
486
487 return std::make_pair(EvalResult(ErrMsg), "");
488 }
489
490 // The value for the symbol depends on the context we're evaluating in:
491 // Inside a load this is the address in the linker's memory, outside a
492 // load it's the address in the target processes memory.
493 uint64_t Value = PCtx.IsInsideLoad ? Checker.getSymbolLocalAddr(Symbol)
494 : Checker.getSymbolRemoteAddr(Symbol);
495
496 // Looks like a plain symbol reference.
497 return std::make_pair(EvalResult(Value), RemainingExpr);
498 }
499
500 // Parse a number (hexadecimal or decimal) and return a (string, string)
501 // pair representing the number and the expression remaining to be parsed.
502 std::pair<StringRef, StringRef> parseNumberString(StringRef Expr) const {
503 size_t FirstNonDigit = StringRef::npos;
504 if (Expr.startswith("0x")) {
505 FirstNonDigit = Expr.find_first_not_of("0123456789abcdefABCDEF", 2);
506 if (FirstNonDigit == StringRef::npos)
507 FirstNonDigit = Expr.size();
508 } else {
509 FirstNonDigit = Expr.find_first_not_of("0123456789");
510 if (FirstNonDigit == StringRef::npos)
511 FirstNonDigit = Expr.size();
512 }
513 return std::make_pair(Expr.substr(0, FirstNonDigit),
514 Expr.substr(FirstNonDigit));
515 }
516
517 // Evaluate a constant numeric expression (hexadecimal or decimal) and
518 // return a pair containing the result, and the expression remaining to be
519 // evaluated.
520 std::pair<EvalResult, StringRef> evalNumberExpr(StringRef Expr) const {
521 StringRef ValueStr;
522 StringRef RemainingExpr;
523 std::tie(ValueStr, RemainingExpr) = parseNumberString(Expr);
524
525 if (ValueStr.empty() || !isdigit(ValueStr[0]))
526 return std::make_pair(
527 unexpectedToken(RemainingExpr, RemainingExpr, "expected number"), "");
529 ValueStr.getAsInteger(0, Value);
530 return std::make_pair(EvalResult(Value), RemainingExpr);
531 }
532
533 // Evaluate an expression of the form "(<expr>)" and return a pair
534 // containing the result of evaluating <expr>, plus the expression
535 // remaining to be parsed.
536 std::pair<EvalResult, StringRef> evalParensExpr(StringRef Expr,
537 ParseContext PCtx) const {
538 assert(Expr.startswith("(") && "Not a parenthesized expression");
539 EvalResult SubExprResult;
540 StringRef RemainingExpr;
541 std::tie(SubExprResult, RemainingExpr) =
542 evalComplexExpr(evalSimpleExpr(Expr.substr(1).ltrim(), PCtx), PCtx);
543 if (SubExprResult.hasError())
544 return std::make_pair(SubExprResult, "");
545 if (!RemainingExpr.startswith(")"))
546 return std::make_pair(
547 unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");
548 RemainingExpr = RemainingExpr.substr(1).ltrim();
549 return std::make_pair(SubExprResult, RemainingExpr);
550 }
551
552 // Evaluate an expression in one of the following forms:
553 // *{<number>}<expr>
554 // Return a pair containing the result, plus the expression remaining to be
555 // parsed.
556 std::pair<EvalResult, StringRef> evalLoadExpr(StringRef Expr) const {
557 assert(Expr.startswith("*") && "Not a load expression");
558 StringRef RemainingExpr = Expr.substr(1).ltrim();
559
560 // Parse read size.
561 if (!RemainingExpr.startswith("{"))
562 return std::make_pair(EvalResult("Expected '{' following '*'."), "");
563 RemainingExpr = RemainingExpr.substr(1).ltrim();
564 EvalResult ReadSizeExpr;
565 std::tie(ReadSizeExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
566 if (ReadSizeExpr.hasError())
567 return std::make_pair(ReadSizeExpr, RemainingExpr);
568 uint64_t ReadSize = ReadSizeExpr.getValue();
569 if (ReadSize < 1 || ReadSize > 8)
570 return std::make_pair(EvalResult("Invalid size for dereference."), "");
571 if (!RemainingExpr.startswith("}"))
572 return std::make_pair(EvalResult("Missing '}' for dereference."), "");
573 RemainingExpr = RemainingExpr.substr(1).ltrim();
574
575 // Evaluate the expression representing the load address.
576 ParseContext LoadCtx(true);
577 EvalResult LoadAddrExprResult;
578 std::tie(LoadAddrExprResult, RemainingExpr) =
579 evalComplexExpr(evalSimpleExpr(RemainingExpr, LoadCtx), LoadCtx);
580
581 if (LoadAddrExprResult.hasError())
582 return std::make_pair(LoadAddrExprResult, "");
583
584 uint64_t LoadAddr = LoadAddrExprResult.getValue();
585
586 // If there is no error but the content pointer is null then this is a
587 // zero-fill symbol/section.
588 if (LoadAddr == 0)
589 return std::make_pair(0, RemainingExpr);
590
591 return std::make_pair(
592 EvalResult(Checker.readMemoryAtAddr(LoadAddr, ReadSize)),
593 RemainingExpr);
594 }
595
596 // Evaluate a "simple" expression. This is any expression that _isn't_ an
597 // un-parenthesized binary expression.
598 //
599 // "Simple" expressions can be optionally bit-sliced. See evalSlicedExpr.
600 //
601 // Returns a pair containing the result of the evaluation, plus the
602 // expression remaining to be parsed.
603 std::pair<EvalResult, StringRef> evalSimpleExpr(StringRef Expr,
604 ParseContext PCtx) const {
605 EvalResult SubExprResult;
606 StringRef RemainingExpr;
607
608 if (Expr.empty())
609 return std::make_pair(EvalResult("Unexpected end of expression"), "");
610
611 if (Expr[0] == '(')
612 std::tie(SubExprResult, RemainingExpr) = evalParensExpr(Expr, PCtx);
613 else if (Expr[0] == '*')
614 std::tie(SubExprResult, RemainingExpr) = evalLoadExpr(Expr);
615 else if (isalpha(Expr[0]) || Expr[0] == '_')
616 std::tie(SubExprResult, RemainingExpr) = evalIdentifierExpr(Expr, PCtx);
617 else if (isdigit(Expr[0]))
618 std::tie(SubExprResult, RemainingExpr) = evalNumberExpr(Expr);
619 else
620 return std::make_pair(
621 unexpectedToken(Expr, Expr,
622 "expected '(', '*', identifier, or number"), "");
623
624 if (SubExprResult.hasError())
625 return std::make_pair(SubExprResult, RemainingExpr);
626
627 // Evaluate bit-slice if present.
628 if (RemainingExpr.startswith("["))
629 std::tie(SubExprResult, RemainingExpr) =
630 evalSliceExpr(std::make_pair(SubExprResult, RemainingExpr));
631
632 return std::make_pair(SubExprResult, RemainingExpr);
633 }
634
635 // Evaluate a bit-slice of an expression.
636 // A bit-slice has the form "<expr>[high:low]". The result of evaluating a
637 // slice is the bits between high and low (inclusive) in the original
638 // expression, right shifted so that the "low" bit is in position 0 in the
639 // result.
640 // Returns a pair containing the result of the slice operation, plus the
641 // expression remaining to be parsed.
642 std::pair<EvalResult, StringRef>
643 evalSliceExpr(const std::pair<EvalResult, StringRef> &Ctx) const {
644 EvalResult SubExprResult;
645 StringRef RemainingExpr;
646 std::tie(SubExprResult, RemainingExpr) = Ctx;
647
648 assert(RemainingExpr.startswith("[") && "Not a slice expr.");
649 RemainingExpr = RemainingExpr.substr(1).ltrim();
650
651 EvalResult HighBitExpr;
652 std::tie(HighBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
653
654 if (HighBitExpr.hasError())
655 return std::make_pair(HighBitExpr, RemainingExpr);
656
657 if (!RemainingExpr.startswith(":"))
658 return std::make_pair(
659 unexpectedToken(RemainingExpr, RemainingExpr, "expected ':'"), "");
660 RemainingExpr = RemainingExpr.substr(1).ltrim();
661
662 EvalResult LowBitExpr;
663 std::tie(LowBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr);
664
665 if (LowBitExpr.hasError())
666 return std::make_pair(LowBitExpr, RemainingExpr);
667
668 if (!RemainingExpr.startswith("]"))
669 return std::make_pair(
670 unexpectedToken(RemainingExpr, RemainingExpr, "expected ']'"), "");
671 RemainingExpr = RemainingExpr.substr(1).ltrim();
672
673 unsigned HighBit = HighBitExpr.getValue();
674 unsigned LowBit = LowBitExpr.getValue();
675 uint64_t Mask = ((uint64_t)1 << (HighBit - LowBit + 1)) - 1;
676 uint64_t SlicedValue = (SubExprResult.getValue() >> LowBit) & Mask;
677 return std::make_pair(EvalResult(SlicedValue), RemainingExpr);
678 }
679
680 // Evaluate a "complex" expression.
681 // Takes an already evaluated subexpression and checks for the presence of a
682 // binary operator, computing the result of the binary operation if one is
683 // found. Used to make arithmetic expressions left-associative.
684 // Returns a pair containing the ultimate result of evaluating the
685 // expression, plus the expression remaining to be evaluated.
686 std::pair<EvalResult, StringRef>
687 evalComplexExpr(const std::pair<EvalResult, StringRef> &LHSAndRemaining,
688 ParseContext PCtx) const {
689 EvalResult LHSResult;
690 StringRef RemainingExpr;
691 std::tie(LHSResult, RemainingExpr) = LHSAndRemaining;
692
693 // If there was an error, or there's nothing left to evaluate, return the
694 // result.
695 if (LHSResult.hasError() || RemainingExpr == "")
696 return std::make_pair(LHSResult, RemainingExpr);
697
698 // Otherwise check if this is a binary expression.
699 BinOpToken BinOp;
700 std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr);
701
702 // If this isn't a recognized expression just return.
703 if (BinOp == BinOpToken::Invalid)
704 return std::make_pair(LHSResult, RemainingExpr);
705
706 // This is a recognized bin-op. Evaluate the RHS, then evaluate the binop.
707 EvalResult RHSResult;
708 std::tie(RHSResult, RemainingExpr) = evalSimpleExpr(RemainingExpr, PCtx);
709
710 // If there was an error evaluating the RHS, return it.
711 if (RHSResult.hasError())
712 return std::make_pair(RHSResult, RemainingExpr);
713
714 // This is a binary expression - evaluate and try to continue as a
715 // complex expr.
716 EvalResult ThisResult(computeBinOpResult(BinOp, LHSResult, RHSResult));
717
718 return evalComplexExpr(std::make_pair(ThisResult, RemainingExpr), PCtx);
719 }
720
721 bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size,
722 int64_t Offset) const {
723 auto TT = Checker.getTripleForSymbol(Checker.getTargetFlag(Symbol));
724 auto TI = getTargetInfo(TT, Checker.getCPU(), Checker.getFeatures());
725
726 if (auto E = TI.takeError()) {
727 errs() << "Error obtaining disassembler: " << toString(std::move(E))
728 << "\n";
729 return false;
730 }
731
732 StringRef SymbolMem = Checker.getSymbolContent(Symbol);
733 ArrayRef<uint8_t> SymbolBytes(SymbolMem.bytes_begin() + Offset,
734 SymbolMem.size() - Offset);
735
737 TI->Disassembler->getInstruction(Inst, Size, SymbolBytes, 0, nulls());
738
739 return (S == MCDisassembler::Success);
740 }
741
742 Expected<TargetInfo> getTargetInfo(const Triple &TT, const StringRef &CPU,
743 const SubtargetFeatures &TF) const {
744
745 auto TripleName = TT.str();
746 std::string ErrorStr;
747 const Target *TheTarget =
748 TargetRegistry::lookupTarget(TripleName, ErrorStr);
749 if (!TheTarget)
750 return make_error<StringError>("Error accessing target '" + TripleName +
751 "': " + ErrorStr,
753
754 std::unique_ptr<MCSubtargetInfo> STI(
755 TheTarget->createMCSubtargetInfo(TripleName, CPU, TF.getString()));
756 if (!STI)
757 return make_error<StringError>("Unable to create subtarget for " +
758 TripleName,
760
761 std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
762 if (!MRI)
763 return make_error<StringError>("Unable to create target register info "
764 "for " +
765 TripleName,
767
768 MCTargetOptions MCOptions;
769 std::unique_ptr<MCAsmInfo> MAI(
770 TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
771 if (!MAI)
772 return make_error<StringError>("Unable to create target asm info " +
773 TripleName,
775
776 auto Ctx = std::make_unique<MCContext>(Triple(TripleName), MAI.get(),
777 MRI.get(), STI.get());
778
779 std::unique_ptr<MCDisassembler> Disassembler(
780 TheTarget->createMCDisassembler(*STI, *Ctx));
781 if (!Disassembler)
782 return make_error<StringError>("Unable to create disassembler for " +
783 TripleName,
785
786 std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
787 if (!MII)
788 return make_error<StringError>("Unable to create instruction info for" +
789 TripleName,
791
792 std::unique_ptr<MCInstPrinter> InstPrinter(TheTarget->createMCInstPrinter(
793 Triple(TripleName), 0, *MAI, *MII, *MRI));
794 if (!InstPrinter)
795 return make_error<StringError>(
796 "Unable to create instruction printer for" + TripleName,
798
799 return TargetInfo({TheTarget, std::move(STI), std::move(MRI),
800 std::move(MAI), std::move(Ctx), std::move(Disassembler),
801 std::move(MII), std::move(InstPrinter)});
802 }
803};
804} // namespace llvm
805
807 IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
808 GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,
809 GetGOTInfoFunction GetGOTInfo, llvm::endianness Endianness, Triple TT,
810 StringRef CPU, SubtargetFeatures TF, raw_ostream &ErrStream)
811 : IsSymbolValid(std::move(IsSymbolValid)),
812 GetSymbolInfo(std::move(GetSymbolInfo)),
813 GetSectionInfo(std::move(GetSectionInfo)),
814 GetStubInfo(std::move(GetStubInfo)), GetGOTInfo(std::move(GetGOTInfo)),
815 Endianness(Endianness), TT(std::move(TT)), CPU(std::move(CPU)),
816 TF(std::move(TF)), ErrStream(ErrStream) {}
817
819 CheckExpr = CheckExpr.trim();
820 LLVM_DEBUG(dbgs() << "RuntimeDyldChecker: Checking '" << CheckExpr
821 << "'...\n");
822 RuntimeDyldCheckerExprEval P(*this, ErrStream);
823 bool Result = P.evaluate(CheckExpr);
824 (void)Result;
825 LLVM_DEBUG(dbgs() << "RuntimeDyldChecker: '" << CheckExpr << "' "
826 << (Result ? "passed" : "FAILED") << ".\n");
827 return Result;
828}
829
831 MemoryBuffer *MemBuf) const {
832 bool DidAllTestsPass = true;
833 unsigned NumRules = 0;
834
835 std::string CheckExpr;
836 const char *LineStart = MemBuf->getBufferStart();
837
838 // Eat whitespace.
839 while (LineStart != MemBuf->getBufferEnd() && isSpace(*LineStart))
840 ++LineStart;
841
842 while (LineStart != MemBuf->getBufferEnd() && *LineStart != '\0') {
843 const char *LineEnd = LineStart;
844 while (LineEnd != MemBuf->getBufferEnd() && *LineEnd != '\r' &&
845 *LineEnd != '\n')
846 ++LineEnd;
847
848 StringRef Line(LineStart, LineEnd - LineStart);
849 if (Line.startswith(RulePrefix))
850 CheckExpr += Line.substr(RulePrefix.size()).str();
851
852 // If there's a check expr string...
853 if (!CheckExpr.empty()) {
854 // ... and it's complete then run it, otherwise remove the trailer '\'.
855 if (CheckExpr.back() != '\\') {
856 DidAllTestsPass &= check(CheckExpr);
857 CheckExpr.clear();
858 ++NumRules;
859 } else
860 CheckExpr.pop_back();
861 }
862
863 // Eat whitespace.
864 LineStart = LineEnd;
865 while (LineStart != MemBuf->getBufferEnd() && isSpace(*LineStart))
866 ++LineStart;
867 }
868 return DidAllTestsPass && (NumRules != 0);
869}
870
871bool RuntimeDyldCheckerImpl::isSymbolValid(StringRef Symbol) const {
872 return IsSymbolValid(Symbol);
873}
874
875uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const {
876 auto SymInfo = GetSymbolInfo(Symbol);
877 if (!SymInfo) {
878 logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
879 return 0;
880 }
881
882 if (SymInfo->isZeroFill())
883 return 0;
884
885 return static_cast<uint64_t>(
886 reinterpret_cast<uintptr_t>(SymInfo->getContent().data()));
887}
888
889uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const {
890 auto SymInfo = GetSymbolInfo(Symbol);
891 if (!SymInfo) {
892 logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
893 return 0;
894 }
895
896 return SymInfo->getTargetAddress();
897}
898
899uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr,
900 unsigned Size) const {
901 uintptr_t PtrSizedAddr = static_cast<uintptr_t>(SrcAddr);
902 assert(PtrSizedAddr == SrcAddr && "Linker memory pointer out-of-range.");
903 void *Ptr = reinterpret_cast<void*>(PtrSizedAddr);
904
905 switch (Size) {
906 case 1:
907 return support::endian::read<uint8_t>(Ptr, Endianness);
908 case 2:
909 return support::endian::read<uint16_t>(Ptr, Endianness);
910 case 4:
911 return support::endian::read<uint32_t>(Ptr, Endianness);
912 case 8:
913 return support::endian::read<uint64_t>(Ptr, Endianness);
914 }
915 llvm_unreachable("Unsupported read size");
916}
917
918StringRef RuntimeDyldCheckerImpl::getSymbolContent(StringRef Symbol) const {
919 auto SymInfo = GetSymbolInfo(Symbol);
920 if (!SymInfo) {
921 logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
922 return StringRef();
923 }
924 return {SymInfo->getContent().data(), SymInfo->getContent().size()};
925}
926
927TargetFlagsType RuntimeDyldCheckerImpl::getTargetFlag(StringRef Symbol) const {
928 auto SymInfo = GetSymbolInfo(Symbol);
929 if (!SymInfo) {
930 logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
931 return TargetFlagsType{};
932 }
933 return SymInfo->getTargetFlags();
934}
935
936Triple
937RuntimeDyldCheckerImpl::getTripleForSymbol(TargetFlagsType Flag) const {
938 Triple TheTriple = TT;
939
940 switch (TT.getArch()) {
942 if (~Flag & 0x1)
943 return TT;
944 TheTriple.setArchName((Twine("thumb") + TT.getArchName().substr(3)).str());
945 return TheTriple;
947 if (Flag & 0x1)
948 return TT;
949 TheTriple.setArchName((Twine("arm") + TT.getArchName().substr(5)).str());
950 return TheTriple;
951
952 default:
953 return TT;
954 }
955}
956
957std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getSectionAddr(
958 StringRef FileName, StringRef SectionName, bool IsInsideLoad) const {
959
960 auto SecInfo = GetSectionInfo(FileName, SectionName);
961 if (!SecInfo) {
962 std::string ErrMsg;
963 {
964 raw_string_ostream ErrMsgStream(ErrMsg);
965 logAllUnhandledErrors(SecInfo.takeError(), ErrMsgStream,
966 "RTDyldChecker: ");
967 }
968 return std::make_pair(0, std::move(ErrMsg));
969 }
970
971 // If this address is being looked up in "load" mode, return the content
972 // pointer, otherwise return the target address.
973
974 uint64_t Addr = 0;
975
976 if (IsInsideLoad) {
977 if (SecInfo->isZeroFill())
978 Addr = 0;
979 else
980 Addr = pointerToJITTargetAddress(SecInfo->getContent().data());
981 } else
982 Addr = SecInfo->getTargetAddress();
983
984 return std::make_pair(Addr, "");
985}
986
987std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubOrGOTAddrFor(
988 StringRef StubContainerName, StringRef SymbolName, bool IsInsideLoad,
989 bool IsStubAddr) const {
990
991 auto StubInfo = IsStubAddr ? GetStubInfo(StubContainerName, SymbolName)
992 : GetGOTInfo(StubContainerName, SymbolName);
993
994 if (!StubInfo) {
995 std::string ErrMsg;
996 {
997 raw_string_ostream ErrMsgStream(ErrMsg);
998 logAllUnhandledErrors(StubInfo.takeError(), ErrMsgStream,
999 "RTDyldChecker: ");
1000 }
1001 return std::make_pair((uint64_t)0, std::move(ErrMsg));
1002 }
1003
1004 uint64_t Addr = 0;
1005
1006 if (IsInsideLoad) {
1007 if (StubInfo->isZeroFill())
1008 return std::make_pair((uint64_t)0, "Detected zero-filled stub/GOT entry");
1009 Addr = pointerToJITTargetAddress(StubInfo->getContent().data());
1010 } else
1011 Addr = StubInfo->getTargetAddress();
1012
1013 return std::make_pair(Addr, "");
1014}
1015
1017 IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
1018 GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,
1019 GetGOTInfoFunction GetGOTInfo, llvm::endianness Endianness, Triple TT,
1020 StringRef CPU, SubtargetFeatures TF, raw_ostream &ErrStream)
1021 : Impl(::std::make_unique<RuntimeDyldCheckerImpl>(
1022 std::move(IsSymbolValid), std::move(GetSymbolInfo),
1023 std::move(GetSectionInfo), std::move(GetStubInfo),
1024 std::move(GetGOTInfo), Endianness, std::move(TT), std::move(CPU),
1025 std::move(TF), ErrStream)) {}
1026
1028
1030 return Impl->check(CheckExpr);
1031}
1032
1034 MemoryBuffer *MemBuf) const {
1035 return Impl->checkAllRulesInBuffer(RulePrefix, MemBuf);
1036}
1037
1038std::pair<uint64_t, std::string>
1040 bool LocalAddress) {
1041 return Impl->getSectionAddr(FileName, SectionName, LocalAddress);
1042}
unsigned const MachineRegisterInfo * MRI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DEBUG(X)
Definition: Debug.h:101
uint64_t Addr
uint64_t Size
#define check(cond)
#define P(N)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
This file contains some functions that are useful when dealing with strings.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
This class represents an Operation in the Expression.
Tagged union holding either a T or a Error.
Definition: Error.h:474
DecodeStatus
Ternary decode status.
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:51
const char * getBufferEnd() const
Definition: MemoryBuffer.h:67
const char * getBufferStart() const
Definition: MemoryBuffer.h:66
bool evaluate(StringRef Expr) const
RuntimeDyldCheckerExprEval(const RuntimeDyldCheckerImpl &Checker, raw_ostream &ErrStream)
bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const
bool check(StringRef CheckExpr) const
RuntimeDyldCheckerImpl(IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo, GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo, GetGOTInfoFunction GetGOTInfo, llvm::endianness Endianness, Triple TT, StringRef CPU, SubtargetFeatures TF, llvm::raw_ostream &ErrStream)
std::pair< uint64_t, std::string > getSectionAddr(StringRef FileName, StringRef SectionName, bool LocalAddress)
Returns the address of the requested section (or an error message in the second element of the pair i...
bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const
Scan the given memory buffer for lines beginning with the string in RulePrefix.
std::function< Expected< MemoryRegionInfo >(StringRef StubContainer, StringRef TargetName)> GetStubInfoFunction
bool check(StringRef CheckExpr) const
Check a single expression against the attached RuntimeDyld instance.
std::function< bool(StringRef Symbol)> IsSymbolValidFunction
RuntimeDyldChecker(IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo, GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo, GetGOTInfoFunction GetGOTInfo, llvm::endianness Endianness, Triple TT, StringRef CPU, SubtargetFeatures TF, raw_ostream &ErrStream)
std::function< Expected< MemoryRegionInfo >(StringRef FileName, StringRef SectionName)> GetSectionInfoFunction
std::function< Expected< MemoryRegionInfo >(StringRef GOTContainer, StringRef TargetName)> GetGOTInfoFunction
std::function< Expected< MemoryRegionInfo >(StringRef SymbolName)> GetSymbolInfoFunction
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:474
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:575
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
Definition: StringRef.h:795
bool startswith(StringRef Prefix) const
Definition: StringRef.h:261
StringRef rtrim(char Char) const
Return string with consecutive Char characters starting from the right removed.
Definition: StringRef.h:807
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:301
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
Definition: StringRef.h:819
static constexpr size_t npos
Definition: StringRef.h:52
const unsigned char * bytes_begin() const
Definition: StringRef.h:115
size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
Definition: StringRef.cpp:251
Manages the enabling and disabling of subtarget specific features.
std::string getString() const
Returns features as a string.
Target - Wrapper for Target specific information.
MCSubtargetInfo * createMCSubtargetInfo(StringRef TheTriple, StringRef CPU, StringRef Features) const
createMCSubtargetInfo - Create a MCSubtargetInfo implementation.
MCRegisterInfo * createMCRegInfo(StringRef TT) const
createMCRegInfo - Create a MCRegisterInfo implementation.
MCDisassembler * createMCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) const
MCAsmInfo * createMCAsmInfo(const MCRegisterInfo &MRI, StringRef TheTriple, const MCTargetOptions &Options) const
createMCAsmInfo - Create a MCAsmInfo implementation for the specified target triple.
MCInstPrinter * createMCInstPrinter(const Triple &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI) const
MCInstrInfo * createMCInstrInfo() const
createMCInstrInfo - Create a MCInstrInfo implementation.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
void setArchName(StringRef Str)
Set the architecture (first) component of the triple by name.
Definition: Triple.cpp:1362
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
LLVM Value Representation.
Definition: Value.h:74
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:642
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:121
@ Invalid
Invalid file type.
Definition: InterfaceFile.h:55
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
Definition: Error.cpp:65
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:90
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
uint8_t TargetFlagsType
Holds target-specific properties for a symbol.
raw_ostream & nulls()
This returns a reference to a raw_ostream which simply discards output.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1853
JITTargetAddress pointerToJITTargetAddress(T *Ptr)
Convert a pointer to a JITTargetAddress.
Definition: JITSymbol.h:69
endianness
Definition: bit.h:70
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
SymInfo contains information about symbol: it's address and section index which is -1LL for absolute ...
static const Target * lookupTarget(StringRef Triple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.