1274955Ssvnmir//===---- RuntimeDyldChecker.h - RuntimeDyld tester framework -----*- C++ -*-=// 2274955Ssvnmir// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6274955Ssvnmir// 7274955Ssvnmir//===----------------------------------------------------------------------===// 8274955Ssvnmir 9280031Sdim#ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H 10280031Sdim#define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H 11274955Ssvnmir 12353358Sdim#include "llvm/ADT/DenseMap.h" 13321369Sdim#include "llvm/ADT/Optional.h" 14353358Sdim#include "llvm/ExecutionEngine/JITSymbol.h" 15353358Sdim#include "llvm/Support/Endian.h" 16321369Sdim 17309124Sdim#include <cstdint> 18309124Sdim#include <memory> 19309124Sdim#include <string> 20309124Sdim#include <utility> 21274955Ssvnmir 22274955Ssvnmirnamespace llvm { 23274955Ssvnmir 24309124Sdimclass StringRef; 25274955Ssvnmirclass MCDisassembler; 26280031Sdimclass MemoryBuffer; 27274955Ssvnmirclass MCInstPrinter; 28280031Sdimclass RuntimeDyld; 29280031Sdimclass RuntimeDyldCheckerImpl; 30280031Sdimclass raw_ostream; 31274955Ssvnmir 32341825Sdim/// RuntimeDyld invariant checker for verifying that RuntimeDyld has 33274955Ssvnmir/// correctly applied relocations. 34274955Ssvnmir/// 35274955Ssvnmir/// The RuntimeDyldChecker class evaluates expressions against an attached 36274955Ssvnmir/// RuntimeDyld instance to verify that relocations have been applied 37274955Ssvnmir/// correctly. 38274955Ssvnmir/// 39274955Ssvnmir/// The expression language supports basic pointer arithmetic and bit-masking, 40274955Ssvnmir/// and has limited disassembler integration for accessing instruction 41274955Ssvnmir/// operands and the next PC (program counter) address for each instruction. 42274955Ssvnmir/// 43274955Ssvnmir/// The language syntax is: 44274955Ssvnmir/// 45274955Ssvnmir/// check = expr '=' expr 46274955Ssvnmir/// 47274955Ssvnmir/// expr = binary_expr 48274955Ssvnmir/// | sliceable_expr 49274955Ssvnmir/// 50274955Ssvnmir/// sliceable_expr = '*{' number '}' load_addr_expr [slice] 51274955Ssvnmir/// | '(' expr ')' [slice] 52274955Ssvnmir/// | ident_expr [slice] 53274955Ssvnmir/// | number [slice] 54274955Ssvnmir/// 55274955Ssvnmir/// slice = '[' high-bit-index ':' low-bit-index ']' 56274955Ssvnmir/// 57274955Ssvnmir/// load_addr_expr = symbol 58274955Ssvnmir/// | '(' symbol '+' number ')' 59274955Ssvnmir/// | '(' symbol '-' number ')' 60274955Ssvnmir/// 61274955Ssvnmir/// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')' 62274955Ssvnmir/// | 'next_pc' '(' symbol ')' 63353358Sdim/// | 'stub_addr' '(' stub-container-name ',' symbol ')' 64353358Sdim/// | 'got_addr' '(' stub-container-name ',' symbol ')' 65274955Ssvnmir/// | symbol 66274955Ssvnmir/// 67274955Ssvnmir/// binary_expr = expr '+' expr 68274955Ssvnmir/// | expr '-' expr 69274955Ssvnmir/// | expr '&' expr 70274955Ssvnmir/// | expr '|' expr 71274955Ssvnmir/// | expr '<<' expr 72274955Ssvnmir/// | expr '>>' expr 73274955Ssvnmir/// 74274955Ssvnmirclass RuntimeDyldChecker { 75274955Ssvnmirpublic: 76353358Sdim class MemoryRegionInfo { 77353358Sdim public: 78353358Sdim MemoryRegionInfo() = default; 79274955Ssvnmir 80353358Sdim /// Constructor for symbols/sections with content. 81353358Sdim MemoryRegionInfo(StringRef Content, JITTargetAddress TargetAddress) 82353358Sdim : ContentPtr(Content.data()), Size(Content.size()), 83353358Sdim TargetAddress(TargetAddress) {} 84280031Sdim 85353358Sdim /// Constructor for zero-fill symbols/sections. 86353358Sdim MemoryRegionInfo(uint64_t Size, JITTargetAddress TargetAddress) 87353358Sdim : Size(Size), TargetAddress(TargetAddress) {} 88280031Sdim 89353358Sdim /// Returns true if this is a zero-fill symbol/section. 90353358Sdim bool isZeroFill() const { 91353358Sdim assert(Size && "setContent/setZeroFill must be called first"); 92353358Sdim return !ContentPtr; 93353358Sdim } 94353358Sdim 95353358Sdim /// Set the content for this memory region. 96353358Sdim void setContent(StringRef Content) { 97353358Sdim assert(!ContentPtr && !Size && "Content/zero-fill already set"); 98353358Sdim ContentPtr = Content.data(); 99353358Sdim Size = Content.size(); 100353358Sdim } 101353358Sdim 102353358Sdim /// Set a zero-fill length for this memory region. 103353358Sdim void setZeroFill(uint64_t Size) { 104353358Sdim assert(!ContentPtr && !this->Size && "Content/zero-fill already set"); 105353358Sdim this->Size = Size; 106353358Sdim } 107353358Sdim 108353358Sdim /// Returns the content for this section if there is any. 109353358Sdim StringRef getContent() const { 110353358Sdim assert(!isZeroFill() && "Can't get content for a zero-fill section"); 111353358Sdim return StringRef(ContentPtr, static_cast<size_t>(Size)); 112353358Sdim } 113353358Sdim 114353358Sdim /// Returns the zero-fill length for this section. 115353358Sdim uint64_t getZeroFillLength() const { 116353358Sdim assert(isZeroFill() && "Can't get zero-fill length for content section"); 117353358Sdim return Size; 118353358Sdim } 119353358Sdim 120353358Sdim /// Set the target address for this region. 121353358Sdim void setTargetAddress(JITTargetAddress TargetAddress) { 122353358Sdim assert(!this->TargetAddress && "TargetAddress already set"); 123353358Sdim this->TargetAddress = TargetAddress; 124353358Sdim } 125353358Sdim 126353358Sdim /// Return the target address for this region. 127353358Sdim JITTargetAddress getTargetAddress() const { return TargetAddress; } 128353358Sdim 129353358Sdim private: 130353358Sdim const char *ContentPtr = 0; 131353358Sdim uint64_t Size = 0; 132353358Sdim JITTargetAddress TargetAddress = 0; 133353358Sdim }; 134353358Sdim 135353358Sdim using IsSymbolValidFunction = std::function<bool(StringRef Symbol)>; 136353358Sdim using GetSymbolInfoFunction = 137353358Sdim std::function<Expected<MemoryRegionInfo>(StringRef SymbolName)>; 138353358Sdim using GetSectionInfoFunction = std::function<Expected<MemoryRegionInfo>( 139353358Sdim StringRef FileName, StringRef SectionName)>; 140353358Sdim using GetStubInfoFunction = std::function<Expected<MemoryRegionInfo>( 141353358Sdim StringRef StubContainer, StringRef TargetName)>; 142353358Sdim using GetGOTInfoFunction = std::function<Expected<MemoryRegionInfo>( 143353358Sdim StringRef GOTContainer, StringRef TargetName)>; 144353358Sdim 145353358Sdim RuntimeDyldChecker(IsSymbolValidFunction IsSymbolValid, 146353358Sdim GetSymbolInfoFunction GetSymbolInfo, 147353358Sdim GetSectionInfoFunction GetSectionInfo, 148353358Sdim GetStubInfoFunction GetStubInfo, 149353358Sdim GetGOTInfoFunction GetGOTInfo, 150353358Sdim support::endianness Endianness, 151353358Sdim MCDisassembler *Disassembler, MCInstPrinter *InstPrinter, 152353358Sdim raw_ostream &ErrStream); 153353358Sdim ~RuntimeDyldChecker(); 154353358Sdim 155341825Sdim /// Check a single expression against the attached RuntimeDyld 156274955Ssvnmir /// instance. 157274955Ssvnmir bool check(StringRef CheckExpr) const; 158274955Ssvnmir 159341825Sdim /// Scan the given memory buffer for lines beginning with the string 160274955Ssvnmir /// in RulePrefix. The remainder of the line is passed to the check 161274955Ssvnmir /// method to be evaluated as an expression. 162274955Ssvnmir bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const; 163274955Ssvnmir 164341825Sdim /// Returns the address of the requested section (or an error message 165280031Sdim /// in the second element of the pair if the address cannot be found). 166280031Sdim /// 167288943Sdim /// if 'LocalAddress' is true, this returns the address of the section 168288943Sdim /// within the linker's memory. If 'LocalAddress' is false it returns the 169280031Sdim /// address within the target process (i.e. the load address). 170280031Sdim std::pair<uint64_t, std::string> getSectionAddr(StringRef FileName, 171280031Sdim StringRef SectionName, 172288943Sdim bool LocalAddress); 173280031Sdim 174341825Sdim /// If there is a section at the given local address, return its load 175353358Sdim /// address, otherwise return none. 176321369Sdim Optional<uint64_t> getSectionLoadAddress(void *LocalAddress) const; 177321369Sdim 178274955Ssvnmirprivate: 179280031Sdim std::unique_ptr<RuntimeDyldCheckerImpl> Impl; 180274955Ssvnmir}; 181274955Ssvnmir 182274955Ssvnmir} // end namespace llvm 183274955Ssvnmir 184280031Sdim#endif 185