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