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/ADT/DenseMap.h" 13#include "llvm/ADT/Optional.h" 14#include "llvm/ExecutionEngine/JITSymbol.h" 15#include "llvm/Support/Endian.h" 16 17#include <cstdint> 18#include <memory> 19#include <string> 20#include <utility> 21 22namespace llvm { 23 24class StringRef; 25class MCDisassembler; 26class MemoryBuffer; 27class MCInstPrinter; 28class RuntimeDyld; 29class RuntimeDyldCheckerImpl; 30class raw_ostream; 31 32/// RuntimeDyld invariant checker for verifying that RuntimeDyld has 33/// correctly applied relocations. 34/// 35/// The RuntimeDyldChecker class evaluates expressions against an attached 36/// RuntimeDyld instance to verify that relocations have been applied 37/// correctly. 38/// 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. 42/// 43/// The language syntax is: 44/// 45/// check = expr '=' expr 46/// 47/// expr = binary_expr 48/// | sliceable_expr 49/// 50/// sliceable_expr = '*{' number '}' load_addr_expr [slice] 51/// | '(' expr ')' [slice] 52/// | ident_expr [slice] 53/// | number [slice] 54/// 55/// slice = '[' high-bit-index ':' low-bit-index ']' 56/// 57/// load_addr_expr = symbol 58/// | '(' symbol '+' number ')' 59/// | '(' symbol '-' number ')' 60/// 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 ')' 65/// | symbol 66/// 67/// binary_expr = expr '+' expr 68/// | expr '-' expr 69/// | expr '&' expr 70/// | expr '|' expr 71/// | expr '<<' expr 72/// | expr '>>' expr 73/// 74class RuntimeDyldChecker { 75public: 76 class MemoryRegionInfo { 77 public: 78 MemoryRegionInfo() = default; 79 80 /// Constructor for symbols/sections with content. 81 MemoryRegionInfo(StringRef Content, JITTargetAddress TargetAddress) 82 : ContentPtr(Content.data()), Size(Content.size()), 83 TargetAddress(TargetAddress) {} 84 85 /// Constructor for zero-fill symbols/sections. 86 MemoryRegionInfo(uint64_t Size, JITTargetAddress TargetAddress) 87 : Size(Size), TargetAddress(TargetAddress) {} 88 89 /// Returns true if this is a zero-fill symbol/section. 90 bool isZeroFill() const { 91 assert(Size && "setContent/setZeroFill must be called first"); 92 return !ContentPtr; 93 } 94 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(); 100 } 101 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"); 105 this->Size = Size; 106 } 107 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)); 112 } 113 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"); 117 return Size; 118 } 119 120 /// Set the target address for this region. 121 void setTargetAddress(JITTargetAddress TargetAddress) { 122 assert(!this->TargetAddress && "TargetAddress already set"); 123 this->TargetAddress = TargetAddress; 124 } 125 126 /// Return the target address for this region. 127 JITTargetAddress getTargetAddress() const { return TargetAddress; } 128 129 private: 130 const char *ContentPtr = 0; 131 uint64_t Size = 0; 132 JITTargetAddress TargetAddress = 0; 133 }; 134 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)>; 144 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(); 154 155 /// Check a single expression against the attached RuntimeDyld 156 /// instance. 157 bool check(StringRef CheckExpr) const; 158 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; 163 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). 166 /// 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, 172 bool LocalAddress); 173 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; 177 178private: 179 std::unique_ptr<RuntimeDyldCheckerImpl> Impl; 180}; 181 182} // end namespace llvm 183 184#endif 185