Home | History | Annotate | Line # | Download | only in ExecutionEngine
      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 
     22 namespace llvm {
     23 
     24 class StringRef;
     25 class MCDisassembler;
     26 class MemoryBuffer;
     27 class MCInstPrinter;
     28 class RuntimeDyld;
     29 class RuntimeDyldCheckerImpl;
     30 class 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 ///
     74 class RuntimeDyldChecker {
     75 public:
     76   class MemoryRegionInfo {
     77   public:
     78     MemoryRegionInfo() = default;
     79 
     80     /// Constructor for symbols/sections with content.
     81     MemoryRegionInfo(ArrayRef<char> 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(ArrayRef<char> 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     ArrayRef<char> getContent() const {
    110       assert(!isZeroFill() && "Can't get content for a zero-fill section");
    111       return {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 
    178 private:
    179   std::unique_ptr<RuntimeDyldCheckerImpl> Impl;
    180 };
    181 
    182 } // end namespace llvm
    183 
    184 #endif
    185