reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
//===---- RuntimeDyldChecker.h - RuntimeDyld tester framework -----*- C++ -*-=//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
#define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/Support/Endian.h"

#include <cstdint>
#include <memory>
#include <string>
#include <utility>

namespace llvm {

class StringRef;
class MCDisassembler;
class MemoryBuffer;
class MCInstPrinter;
class RuntimeDyld;
class RuntimeDyldCheckerImpl;
class raw_ostream;

/// RuntimeDyld invariant checker for verifying that RuntimeDyld has
///        correctly applied relocations.
///
/// The RuntimeDyldChecker class evaluates expressions against an attached
/// RuntimeDyld instance to verify that relocations have been applied
/// correctly.
///
/// The expression language supports basic pointer arithmetic and bit-masking,
/// and has limited disassembler integration for accessing instruction
/// operands and the next PC (program counter) address for each instruction.
///
/// The language syntax is:
///
/// check = expr '=' expr
///
/// expr = binary_expr
///      | sliceable_expr
///
/// sliceable_expr = '*{' number '}' load_addr_expr [slice]
///                | '(' expr ')' [slice]
///                | ident_expr [slice]
///                | number [slice]
///
/// slice = '[' high-bit-index ':' low-bit-index ']'
///
/// load_addr_expr = symbol
///                | '(' symbol '+' number ')'
///                | '(' symbol '-' number ')'
///
/// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')'
///            | 'next_pc'        '(' symbol ')'
///            | 'stub_addr' '(' stub-container-name ',' symbol ')'
///            | 'got_addr' '(' stub-container-name ',' symbol ')'
///            | symbol
///
/// binary_expr = expr '+' expr
///             | expr '-' expr
///             | expr '&' expr
///             | expr '|' expr
///             | expr '<<' expr
///             | expr '>>' expr
///
class RuntimeDyldChecker {
public:
  class MemoryRegionInfo {
  public:
    MemoryRegionInfo() = default;

    /// Constructor for symbols/sections with content.
    MemoryRegionInfo(StringRef Content, JITTargetAddress TargetAddress)
        : ContentPtr(Content.data()), Size(Content.size()),
          TargetAddress(TargetAddress) {}

    /// Constructor for zero-fill symbols/sections.
    MemoryRegionInfo(uint64_t Size, JITTargetAddress TargetAddress)
        : Size(Size), TargetAddress(TargetAddress) {}

    /// Returns true if this is a zero-fill symbol/section.
    bool isZeroFill() const {
      assert(Size && "setContent/setZeroFill must be called first");
      return !ContentPtr;
    }

    /// Set the content for this memory region.
    void setContent(StringRef Content) {
      assert(!ContentPtr && !Size && "Content/zero-fill already set");
      ContentPtr = Content.data();
      Size = Content.size();
    }

    /// Set a zero-fill length for this memory region.
    void setZeroFill(uint64_t Size) {
      assert(!ContentPtr && !this->Size && "Content/zero-fill already set");
      this->Size = Size;
    }

    /// Returns the content for this section if there is any.
    StringRef getContent() const {
      assert(!isZeroFill() && "Can't get content for a zero-fill section");
      return StringRef(ContentPtr, static_cast<size_t>(Size));
    }

    /// Returns the zero-fill length for this section.
    uint64_t getZeroFillLength() const {
      assert(isZeroFill() && "Can't get zero-fill length for content section");
      return Size;
    }

    /// Set the target address for this region.
    void setTargetAddress(JITTargetAddress TargetAddress) {
      assert(!this->TargetAddress && "TargetAddress already set");
      this->TargetAddress = TargetAddress;
    }

    /// Return the target address for this region.
    JITTargetAddress getTargetAddress() const { return TargetAddress; }

  private:
    const char *ContentPtr = 0;
    uint64_t Size = 0;
    JITTargetAddress TargetAddress = 0;
  };

  using IsSymbolValidFunction = std::function<bool(StringRef Symbol)>;
  using GetSymbolInfoFunction =
      std::function<Expected<MemoryRegionInfo>(StringRef SymbolName)>;
  using GetSectionInfoFunction = std::function<Expected<MemoryRegionInfo>(
      StringRef FileName, StringRef SectionName)>;
  using GetStubInfoFunction = std::function<Expected<MemoryRegionInfo>(
      StringRef StubContainer, StringRef TargetName)>;
  using GetGOTInfoFunction = std::function<Expected<MemoryRegionInfo>(
      StringRef GOTContainer, StringRef TargetName)>;

  RuntimeDyldChecker(IsSymbolValidFunction IsSymbolValid,
                     GetSymbolInfoFunction GetSymbolInfo,
                     GetSectionInfoFunction GetSectionInfo,
                     GetStubInfoFunction GetStubInfo,
                     GetGOTInfoFunction GetGOTInfo,
                     support::endianness Endianness,
                     MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
                     raw_ostream &ErrStream);
  ~RuntimeDyldChecker();

  /// Check a single expression against the attached RuntimeDyld
  ///        instance.
  bool check(StringRef CheckExpr) const;

  /// Scan the given memory buffer for lines beginning with the string
  ///        in RulePrefix. The remainder of the line is passed to the check
  ///        method to be evaluated as an expression.
  bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;

  /// Returns the address of the requested section (or an error message
  ///        in the second element of the pair if the address cannot be found).
  ///
  /// if 'LocalAddress' is true, this returns the address of the section
  /// within the linker's memory. If 'LocalAddress' is false it returns the
  /// address within the target process (i.e. the load address).
  std::pair<uint64_t, std::string> getSectionAddr(StringRef FileName,
                                                  StringRef SectionName,
                                                  bool LocalAddress);

  /// If there is a section at the given local address, return its load
  /// address, otherwise return none.
  Optional<uint64_t> getSectionLoadAddress(void *LocalAddress) const;

private:
  std::unique_ptr<RuntimeDyldCheckerImpl> Impl;
};

} // end namespace llvm

#endif