1274955Ssvnmir//===---- RuntimeDyldChecker.h - RuntimeDyld tester framework -----*- C++ -*-=//
2274955Ssvnmir//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6274955Ssvnmir//
7274955Ssvnmir//===----------------------------------------------------------------------===//
8274955Ssvnmir
9280031Sdim#ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
10280031Sdim#define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
11274955Ssvnmir
12353358Sdim#include "llvm/ADT/DenseMap.h"
13321369Sdim#include "llvm/ADT/Optional.h"
14353358Sdim#include "llvm/ExecutionEngine/JITSymbol.h"
15353358Sdim#include "llvm/Support/Endian.h"
16321369Sdim
17309124Sdim#include <cstdint>
18309124Sdim#include <memory>
19309124Sdim#include <string>
20309124Sdim#include <utility>
21274955Ssvnmir
22274955Ssvnmirnamespace llvm {
23274955Ssvnmir
24309124Sdimclass StringRef;
25274955Ssvnmirclass MCDisassembler;
26280031Sdimclass MemoryBuffer;
27274955Ssvnmirclass MCInstPrinter;
28280031Sdimclass RuntimeDyld;
29280031Sdimclass RuntimeDyldCheckerImpl;
30280031Sdimclass raw_ostream;
31274955Ssvnmir
32341825Sdim/// RuntimeDyld invariant checker for verifying that RuntimeDyld has
33274955Ssvnmir///        correctly applied relocations.
34274955Ssvnmir///
35274955Ssvnmir/// The RuntimeDyldChecker class evaluates expressions against an attached
36274955Ssvnmir/// RuntimeDyld instance to verify that relocations have been applied
37274955Ssvnmir/// correctly.
38274955Ssvnmir///
39274955Ssvnmir/// The expression language supports basic pointer arithmetic and bit-masking,
40274955Ssvnmir/// and has limited disassembler integration for accessing instruction
41274955Ssvnmir/// operands and the next PC (program counter) address for each instruction.
42274955Ssvnmir///
43274955Ssvnmir/// The language syntax is:
44274955Ssvnmir///
45274955Ssvnmir/// check = expr '=' expr
46274955Ssvnmir///
47274955Ssvnmir/// expr = binary_expr
48274955Ssvnmir///      | sliceable_expr
49274955Ssvnmir///
50274955Ssvnmir/// sliceable_expr = '*{' number '}' load_addr_expr [slice]
51274955Ssvnmir///                | '(' expr ')' [slice]
52274955Ssvnmir///                | ident_expr [slice]
53274955Ssvnmir///                | number [slice]
54274955Ssvnmir///
55274955Ssvnmir/// slice = '[' high-bit-index ':' low-bit-index ']'
56274955Ssvnmir///
57274955Ssvnmir/// load_addr_expr = symbol
58274955Ssvnmir///                | '(' symbol '+' number ')'
59274955Ssvnmir///                | '(' symbol '-' number ')'
60274955Ssvnmir///
61274955Ssvnmir/// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')'
62274955Ssvnmir///            | 'next_pc'        '(' symbol ')'
63353358Sdim///            | 'stub_addr' '(' stub-container-name ',' symbol ')'
64353358Sdim///            | 'got_addr' '(' stub-container-name ',' symbol ')'
65274955Ssvnmir///            | symbol
66274955Ssvnmir///
67274955Ssvnmir/// binary_expr = expr '+' expr
68274955Ssvnmir///             | expr '-' expr
69274955Ssvnmir///             | expr '&' expr
70274955Ssvnmir///             | expr '|' expr
71274955Ssvnmir///             | expr '<<' expr
72274955Ssvnmir///             | expr '>>' expr
73274955Ssvnmir///
74274955Ssvnmirclass RuntimeDyldChecker {
75274955Ssvnmirpublic:
76353358Sdim  class MemoryRegionInfo {
77353358Sdim  public:
78353358Sdim    MemoryRegionInfo() = default;
79274955Ssvnmir
80353358Sdim    /// Constructor for symbols/sections with content.
81353358Sdim    MemoryRegionInfo(StringRef Content, JITTargetAddress TargetAddress)
82353358Sdim        : ContentPtr(Content.data()), Size(Content.size()),
83353358Sdim          TargetAddress(TargetAddress) {}
84280031Sdim
85353358Sdim    /// Constructor for zero-fill symbols/sections.
86353358Sdim    MemoryRegionInfo(uint64_t Size, JITTargetAddress TargetAddress)
87353358Sdim        : Size(Size), TargetAddress(TargetAddress) {}
88280031Sdim
89353358Sdim    /// Returns true if this is a zero-fill symbol/section.
90353358Sdim    bool isZeroFill() const {
91353358Sdim      assert(Size && "setContent/setZeroFill must be called first");
92353358Sdim      return !ContentPtr;
93353358Sdim    }
94353358Sdim
95353358Sdim    /// Set the content for this memory region.
96353358Sdim    void setContent(StringRef Content) {
97353358Sdim      assert(!ContentPtr && !Size && "Content/zero-fill already set");
98353358Sdim      ContentPtr = Content.data();
99353358Sdim      Size = Content.size();
100353358Sdim    }
101353358Sdim
102353358Sdim    /// Set a zero-fill length for this memory region.
103353358Sdim    void setZeroFill(uint64_t Size) {
104353358Sdim      assert(!ContentPtr && !this->Size && "Content/zero-fill already set");
105353358Sdim      this->Size = Size;
106353358Sdim    }
107353358Sdim
108353358Sdim    /// Returns the content for this section if there is any.
109353358Sdim    StringRef getContent() const {
110353358Sdim      assert(!isZeroFill() && "Can't get content for a zero-fill section");
111353358Sdim      return StringRef(ContentPtr, static_cast<size_t>(Size));
112353358Sdim    }
113353358Sdim
114353358Sdim    /// Returns the zero-fill length for this section.
115353358Sdim    uint64_t getZeroFillLength() const {
116353358Sdim      assert(isZeroFill() && "Can't get zero-fill length for content section");
117353358Sdim      return Size;
118353358Sdim    }
119353358Sdim
120353358Sdim    /// Set the target address for this region.
121353358Sdim    void setTargetAddress(JITTargetAddress TargetAddress) {
122353358Sdim      assert(!this->TargetAddress && "TargetAddress already set");
123353358Sdim      this->TargetAddress = TargetAddress;
124353358Sdim    }
125353358Sdim
126353358Sdim    /// Return the target address for this region.
127353358Sdim    JITTargetAddress getTargetAddress() const { return TargetAddress; }
128353358Sdim
129353358Sdim  private:
130353358Sdim    const char *ContentPtr = 0;
131353358Sdim    uint64_t Size = 0;
132353358Sdim    JITTargetAddress TargetAddress = 0;
133353358Sdim  };
134353358Sdim
135353358Sdim  using IsSymbolValidFunction = std::function<bool(StringRef Symbol)>;
136353358Sdim  using GetSymbolInfoFunction =
137353358Sdim      std::function<Expected<MemoryRegionInfo>(StringRef SymbolName)>;
138353358Sdim  using GetSectionInfoFunction = std::function<Expected<MemoryRegionInfo>(
139353358Sdim      StringRef FileName, StringRef SectionName)>;
140353358Sdim  using GetStubInfoFunction = std::function<Expected<MemoryRegionInfo>(
141353358Sdim      StringRef StubContainer, StringRef TargetName)>;
142353358Sdim  using GetGOTInfoFunction = std::function<Expected<MemoryRegionInfo>(
143353358Sdim      StringRef GOTContainer, StringRef TargetName)>;
144353358Sdim
145353358Sdim  RuntimeDyldChecker(IsSymbolValidFunction IsSymbolValid,
146353358Sdim                     GetSymbolInfoFunction GetSymbolInfo,
147353358Sdim                     GetSectionInfoFunction GetSectionInfo,
148353358Sdim                     GetStubInfoFunction GetStubInfo,
149353358Sdim                     GetGOTInfoFunction GetGOTInfo,
150353358Sdim                     support::endianness Endianness,
151353358Sdim                     MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
152353358Sdim                     raw_ostream &ErrStream);
153353358Sdim  ~RuntimeDyldChecker();
154353358Sdim
155341825Sdim  /// Check a single expression against the attached RuntimeDyld
156274955Ssvnmir  ///        instance.
157274955Ssvnmir  bool check(StringRef CheckExpr) const;
158274955Ssvnmir
159341825Sdim  /// Scan the given memory buffer for lines beginning with the string
160274955Ssvnmir  ///        in RulePrefix. The remainder of the line is passed to the check
161274955Ssvnmir  ///        method to be evaluated as an expression.
162274955Ssvnmir  bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
163274955Ssvnmir
164341825Sdim  /// Returns the address of the requested section (or an error message
165280031Sdim  ///        in the second element of the pair if the address cannot be found).
166280031Sdim  ///
167288943Sdim  /// if 'LocalAddress' is true, this returns the address of the section
168288943Sdim  /// within the linker's memory. If 'LocalAddress' is false it returns the
169280031Sdim  /// address within the target process (i.e. the load address).
170280031Sdim  std::pair<uint64_t, std::string> getSectionAddr(StringRef FileName,
171280031Sdim                                                  StringRef SectionName,
172288943Sdim                                                  bool LocalAddress);
173280031Sdim
174341825Sdim  /// If there is a section at the given local address, return its load
175353358Sdim  /// address, otherwise return none.
176321369Sdim  Optional<uint64_t> getSectionLoadAddress(void *LocalAddress) const;
177321369Sdim
178274955Ssvnmirprivate:
179280031Sdim  std::unique_ptr<RuntimeDyldCheckerImpl> Impl;
180274955Ssvnmir};
181274955Ssvnmir
182274955Ssvnmir} // end namespace llvm
183274955Ssvnmir
184280031Sdim#endif
185