1 //===---- RuntimeDyldChecker.h - RuntimeDyld tester framework -----*- C++ -*-=//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
10 #define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
12 #include "llvm/ADT/DenseMap.h"
13 #include "llvm/ADT/Optional.h"
14 #include "llvm/ExecutionEngine/JITSymbol.h"
15 #include "llvm/Support/Endian.h"
29 class RuntimeDyldCheckerImpl
;
32 /// RuntimeDyld invariant checker for verifying that RuntimeDyld has
33 /// correctly applied relocations.
35 /// The RuntimeDyldChecker class evaluates expressions against an attached
36 /// RuntimeDyld instance to verify that relocations have been applied
39 /// The expression language supports basic pointer arithmetic and bit-masking,
40 /// and has limited disassembler integration for accessing instruction
41 /// operands and the next PC (program counter) address for each instruction.
43 /// The language syntax is:
45 /// check = expr '=' expr
47 /// expr = binary_expr
50 /// sliceable_expr = '*{' number '}' load_addr_expr [slice]
51 /// | '(' expr ')' [slice]
52 /// | ident_expr [slice]
55 /// slice = '[' high-bit-index ':' low-bit-index ']'
57 /// load_addr_expr = symbol
58 /// | '(' symbol '+' number ')'
59 /// | '(' symbol '-' number ')'
61 /// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')'
62 /// | 'next_pc' '(' symbol ')'
63 /// | 'stub_addr' '(' stub-container-name ',' symbol ')'
64 /// | 'got_addr' '(' stub-container-name ',' symbol ')'
67 /// binary_expr = expr '+' expr
74 class RuntimeDyldChecker
{
76 class MemoryRegionInfo
{
78 MemoryRegionInfo() = default;
80 /// Constructor for symbols/sections with content.
81 MemoryRegionInfo(StringRef Content
, JITTargetAddress TargetAddress
)
82 : ContentPtr(Content
.data()), Size(Content
.size()),
83 TargetAddress(TargetAddress
) {}
85 /// Constructor for zero-fill symbols/sections.
86 MemoryRegionInfo(uint64_t Size
, JITTargetAddress TargetAddress
)
87 : Size(Size
), TargetAddress(TargetAddress
) {}
89 /// Returns true if this is a zero-fill symbol/section.
90 bool isZeroFill() const {
91 assert(Size
&& "setContent/setZeroFill must be called first");
95 /// Set the content for this memory region.
96 void setContent(StringRef Content
) {
97 assert(!ContentPtr
&& !Size
&& "Content/zero-fill already set");
98 ContentPtr
= Content
.data();
99 Size
= Content
.size();
102 /// Set a zero-fill length for this memory region.
103 void setZeroFill(uint64_t Size
) {
104 assert(!ContentPtr
&& !this->Size
&& "Content/zero-fill already set");
108 /// Returns the content for this section if there is any.
109 StringRef
getContent() const {
110 assert(!isZeroFill() && "Can't get content for a zero-fill section");
111 return StringRef(ContentPtr
, static_cast<size_t>(Size
));
114 /// Returns the zero-fill length for this section.
115 uint64_t getZeroFillLength() const {
116 assert(isZeroFill() && "Can't get zero-fill length for content section");
120 /// Set the target address for this region.
121 void setTargetAddress(JITTargetAddress TargetAddress
) {
122 assert(!this->TargetAddress
&& "TargetAddress already set");
123 this->TargetAddress
= TargetAddress
;
126 /// Return the target address for this region.
127 JITTargetAddress
getTargetAddress() const { return TargetAddress
; }
130 const char *ContentPtr
= 0;
132 JITTargetAddress TargetAddress
= 0;
135 using IsSymbolValidFunction
= std::function
<bool(StringRef Symbol
)>;
136 using GetSymbolInfoFunction
=
137 std::function
<Expected
<MemoryRegionInfo
>(StringRef SymbolName
)>;
138 using GetSectionInfoFunction
= std::function
<Expected
<MemoryRegionInfo
>(
139 StringRef FileName
, StringRef SectionName
)>;
140 using GetStubInfoFunction
= std::function
<Expected
<MemoryRegionInfo
>(
141 StringRef StubContainer
, StringRef TargetName
)>;
142 using GetGOTInfoFunction
= std::function
<Expected
<MemoryRegionInfo
>(
143 StringRef GOTContainer
, StringRef TargetName
)>;
145 RuntimeDyldChecker(IsSymbolValidFunction IsSymbolValid
,
146 GetSymbolInfoFunction GetSymbolInfo
,
147 GetSectionInfoFunction GetSectionInfo
,
148 GetStubInfoFunction GetStubInfo
,
149 GetGOTInfoFunction GetGOTInfo
,
150 support::endianness Endianness
,
151 MCDisassembler
*Disassembler
, MCInstPrinter
*InstPrinter
,
152 raw_ostream
&ErrStream
);
153 ~RuntimeDyldChecker();
155 /// Check a single expression against the attached RuntimeDyld
157 bool check(StringRef CheckExpr
) const;
159 /// Scan the given memory buffer for lines beginning with the string
160 /// in RulePrefix. The remainder of the line is passed to the check
161 /// method to be evaluated as an expression.
162 bool checkAllRulesInBuffer(StringRef RulePrefix
, MemoryBuffer
*MemBuf
) const;
164 /// Returns the address of the requested section (or an error message
165 /// in the second element of the pair if the address cannot be found).
167 /// if 'LocalAddress' is true, this returns the address of the section
168 /// within the linker's memory. If 'LocalAddress' is false it returns the
169 /// address within the target process (i.e. the load address).
170 std::pair
<uint64_t, std::string
> getSectionAddr(StringRef FileName
,
171 StringRef SectionName
,
174 /// If there is a section at the given local address, return its load
175 /// address, otherwise return none.
176 Optional
<uint64_t> getSectionLoadAddress(void *LocalAddress
) const;
179 std::unique_ptr
<RuntimeDyldCheckerImpl
> Impl
;
182 } // end namespace llvm