xref: /llvm-project/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h (revision 2ccf7ed277df28651b94bbee9fccefdf22fb074f)
1 //===---- RuntimeDyldChecker.h - 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 #ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
10 #define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
11 
12 #include "llvm/ExecutionEngine/JITSymbol.h"
13 #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
14 #include "llvm/Support/Endian.h"
15 #include "llvm/TargetParser/SubtargetFeature.h"
16 #include "llvm/TargetParser/Triple.h"
17 #include <optional>
18 
19 #include <cstdint>
20 #include <memory>
21 #include <string>
22 #include <utility>
23 
24 namespace llvm {
25 
26 class StringRef;
27 class MCDisassembler;
28 class MemoryBuffer;
29 class MCInstPrinter;
30 class RuntimeDyld;
31 class RuntimeDyldCheckerImpl;
32 class raw_ostream;
33 
34 /// Holds target-specific properties for a symbol.
35 using TargetFlagsType = uint8_t;
36 
37 /// RuntimeDyld invariant checker for verifying that RuntimeDyld has
38 ///        correctly applied relocations.
39 ///
40 /// The RuntimeDyldChecker class evaluates expressions against an attached
41 /// RuntimeDyld instance to verify that relocations have been applied
42 /// correctly.
43 ///
44 /// The expression language supports basic pointer arithmetic and bit-masking,
45 /// and has limited disassembler integration for accessing instruction
46 /// operands and the next PC (program counter) address for each instruction.
47 ///
48 /// The language syntax is:
49 ///
50 /// check = expr '=' expr
51 ///
52 /// expr = binary_expr
53 ///      | sliceable_expr
54 ///
55 /// sliceable_expr = '*{' number '}' load_addr_expr [slice]
56 ///                | '(' expr ')' [slice]
57 ///                | ident_expr [slice]
58 ///                | number [slice]
59 ///
60 /// slice = '[' high-bit-index ':' low-bit-index ']'
61 ///
62 /// load_addr_expr = symbol
63 ///                | '(' symbol '+' number ')'
64 ///                | '(' symbol '-' number ')'
65 ///
66 /// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')'
67 ///            | 'next_pc'        '(' symbol ')'
68 ///            | 'stub_addr' '(' stub-container-name ',' symbol ')'
69 ///            | 'got_addr' '(' stub-container-name ',' symbol ')'
70 ///            | 'section_addr' '(' stub-container-name ',' symbol ')'
71 ///            | symbol
72 ///
73 /// binary_expr = expr '+' expr
74 ///             | expr '-' expr
75 ///             | expr '&' expr
76 ///             | expr '|' expr
77 ///             | expr '<<' expr
78 ///             | expr '>>' expr
79 ///
80 class RuntimeDyldChecker {
81 public:
82   class MemoryRegionInfo {
83   public:
84     MemoryRegionInfo() = default;
85 
86     /// Constructor for symbols/sections with content and TargetFlag.
87     MemoryRegionInfo(ArrayRef<char> Content, JITTargetAddress TargetAddress,
88                      TargetFlagsType TargetFlags)
89         : ContentPtr(Content.data()), Size(Content.size()),
90           TargetAddress(TargetAddress), TargetFlags(TargetFlags) {}
91 
92     /// Constructor for zero-fill symbols/sections.
93     MemoryRegionInfo(uint64_t Size, JITTargetAddress TargetAddress)
94         : Size(Size), TargetAddress(TargetAddress) {}
95 
96     /// Returns true if this is a zero-fill symbol/section.
97     bool isZeroFill() const {
98       assert(Size && "setContent/setZeroFill must be called first");
99       return !ContentPtr;
100     }
101 
102     /// Set the content for this memory region.
103     void setContent(ArrayRef<char> Content) {
104       assert(!ContentPtr && !Size && "Content/zero-fill already set");
105       ContentPtr = Content.data();
106       Size = Content.size();
107     }
108 
109     /// Set a zero-fill length for this memory region.
110     void setZeroFill(uint64_t Size) {
111       assert(!ContentPtr && !this->Size && "Content/zero-fill already set");
112       this->Size = Size;
113     }
114 
115     /// Returns the content for this section if there is any.
116     ArrayRef<char> getContent() const {
117       assert(!isZeroFill() && "Can't get content for a zero-fill section");
118       return {ContentPtr, static_cast<size_t>(Size)};
119     }
120 
121     /// Returns the zero-fill length for this section.
122     uint64_t getZeroFillLength() const {
123       assert(isZeroFill() && "Can't get zero-fill length for content section");
124       return Size;
125     }
126 
127     /// Set the target address for this region.
128     void setTargetAddress(JITTargetAddress TargetAddress) {
129       assert(!this->TargetAddress && "TargetAddress already set");
130       this->TargetAddress = TargetAddress;
131     }
132 
133     /// Return the target address for this region.
134     JITTargetAddress getTargetAddress() const { return TargetAddress; }
135 
136     /// Get the target flags for this Symbol.
137     TargetFlagsType getTargetFlags() const { return TargetFlags; }
138 
139     /// Set the target flags for this Symbol.
140     void setTargetFlags(TargetFlagsType Flags) {
141       assert(Flags <= 1 && "Add more bits to store more than one flag");
142       TargetFlags = Flags;
143     }
144 
145   private:
146     const char *ContentPtr = nullptr;
147     uint64_t Size = 0;
148     JITTargetAddress TargetAddress = 0;
149     TargetFlagsType TargetFlags = 0;
150   };
151 
152   using IsSymbolValidFunction = std::function<bool(StringRef Symbol)>;
153   using GetSymbolInfoFunction =
154       std::function<Expected<MemoryRegionInfo>(StringRef SymbolName)>;
155   using GetSectionInfoFunction = std::function<Expected<MemoryRegionInfo>(
156       StringRef FileName, StringRef SectionName)>;
157   using GetStubInfoFunction = std::function<Expected<MemoryRegionInfo>(
158       StringRef StubContainer, StringRef TargetName, StringRef StubKindFilter)>;
159   using GetGOTInfoFunction = std::function<Expected<MemoryRegionInfo>(
160       StringRef GOTContainer, StringRef TargetName)>;
161 
162   RuntimeDyldChecker(IsSymbolValidFunction IsSymbolValid,
163                      GetSymbolInfoFunction GetSymbolInfo,
164                      GetSectionInfoFunction GetSectionInfo,
165                      GetStubInfoFunction GetStubInfo,
166                      GetGOTInfoFunction GetGOTInfo, llvm::endianness Endianness,
167                      Triple TT, StringRef CPU, SubtargetFeatures TF,
168                      raw_ostream &ErrStream);
169   ~RuntimeDyldChecker();
170 
171   /// Check a single expression against the attached RuntimeDyld
172   ///        instance.
173   bool check(StringRef CheckExpr) const;
174 
175   /// Scan the given memory buffer for lines beginning with the string
176   ///        in RulePrefix. The remainder of the line is passed to the check
177   ///        method to be evaluated as an expression.
178   bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
179 
180   /// Returns the address of the requested section (or an error message
181   ///        in the second element of the pair if the address cannot be found).
182   ///
183   /// if 'LocalAddress' is true, this returns the address of the section
184   /// within the linker's memory. If 'LocalAddress' is false it returns the
185   /// address within the target process (i.e. the load address).
186   std::pair<uint64_t, std::string> getSectionAddr(StringRef FileName,
187                                                   StringRef SectionName,
188                                                   bool LocalAddress);
189 
190   /// If there is a section at the given local address, return its load
191   /// address, otherwise return std::nullopt.
192   std::optional<uint64_t> getSectionLoadAddress(void *LocalAddress) const;
193 
194 private:
195   std::unique_ptr<RuntimeDyldCheckerImpl> Impl;
196 };
197 
198 } // end namespace llvm
199 
200 #endif
201