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