Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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/ExecutionEngine/JITSymbol.h"
14
#include "llvm/Support/Endian.h"
15
#include <optional>
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 = nullptr;
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
  std::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