RuntimeDyldChecker.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===---- RuntimeDyldChecker.h - RuntimeDyld tester framework -----*- C++ -*-=//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
  14. #define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
  15. #include "llvm/ADT/DenseMap.h"
  16. #include "llvm/ADT/Optional.h"
  17. #include "llvm/ExecutionEngine/JITSymbol.h"
  18. #include "llvm/Support/Endian.h"
  19. #include <cstdint>
  20. #include <memory>
  21. #include <string>
  22. #include <utility>
  23. namespace llvm {
  24. class StringRef;
  25. class MCDisassembler;
  26. class MemoryBuffer;
  27. class MCInstPrinter;
  28. class RuntimeDyld;
  29. class RuntimeDyldCheckerImpl;
  30. class raw_ostream;
  31. /// RuntimeDyld invariant checker for verifying that RuntimeDyld has
  32. /// correctly applied relocations.
  33. ///
  34. /// The RuntimeDyldChecker class evaluates expressions against an attached
  35. /// RuntimeDyld instance to verify that relocations have been applied
  36. /// correctly.
  37. ///
  38. /// The expression language supports basic pointer arithmetic and bit-masking,
  39. /// and has limited disassembler integration for accessing instruction
  40. /// operands and the next PC (program counter) address for each instruction.
  41. ///
  42. /// The language syntax is:
  43. ///
  44. /// check = expr '=' expr
  45. ///
  46. /// expr = binary_expr
  47. /// | sliceable_expr
  48. ///
  49. /// sliceable_expr = '*{' number '}' load_addr_expr [slice]
  50. /// | '(' expr ')' [slice]
  51. /// | ident_expr [slice]
  52. /// | number [slice]
  53. ///
  54. /// slice = '[' high-bit-index ':' low-bit-index ']'
  55. ///
  56. /// load_addr_expr = symbol
  57. /// | '(' symbol '+' number ')'
  58. /// | '(' symbol '-' number ')'
  59. ///
  60. /// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')'
  61. /// | 'next_pc' '(' symbol ')'
  62. /// | 'stub_addr' '(' stub-container-name ',' symbol ')'
  63. /// | 'got_addr' '(' stub-container-name ',' symbol ')'
  64. /// | symbol
  65. ///
  66. /// binary_expr = expr '+' expr
  67. /// | expr '-' expr
  68. /// | expr '&' expr
  69. /// | expr '|' expr
  70. /// | expr '<<' expr
  71. /// | expr '>>' expr
  72. ///
  73. class RuntimeDyldChecker {
  74. public:
  75. class MemoryRegionInfo {
  76. public:
  77. MemoryRegionInfo() = default;
  78. /// Constructor for symbols/sections with content.
  79. MemoryRegionInfo(ArrayRef<char> Content, JITTargetAddress TargetAddress)
  80. : ContentPtr(Content.data()), Size(Content.size()),
  81. TargetAddress(TargetAddress) {}
  82. /// Constructor for zero-fill symbols/sections.
  83. MemoryRegionInfo(uint64_t Size, JITTargetAddress TargetAddress)
  84. : Size(Size), TargetAddress(TargetAddress) {}
  85. /// Returns true if this is a zero-fill symbol/section.
  86. bool isZeroFill() const {
  87. assert(Size && "setContent/setZeroFill must be called first");
  88. return !ContentPtr;
  89. }
  90. /// Set the content for this memory region.
  91. void setContent(ArrayRef<char> Content) {
  92. assert(!ContentPtr && !Size && "Content/zero-fill already set");
  93. ContentPtr = Content.data();
  94. Size = Content.size();
  95. }
  96. /// Set a zero-fill length for this memory region.
  97. void setZeroFill(uint64_t Size) {
  98. assert(!ContentPtr && !this->Size && "Content/zero-fill already set");
  99. this->Size = Size;
  100. }
  101. /// Returns the content for this section if there is any.
  102. ArrayRef<char> getContent() const {
  103. assert(!isZeroFill() && "Can't get content for a zero-fill section");
  104. return {ContentPtr, static_cast<size_t>(Size)};
  105. }
  106. /// Returns the zero-fill length for this section.
  107. uint64_t getZeroFillLength() const {
  108. assert(isZeroFill() && "Can't get zero-fill length for content section");
  109. return Size;
  110. }
  111. /// Set the target address for this region.
  112. void setTargetAddress(JITTargetAddress TargetAddress) {
  113. assert(!this->TargetAddress && "TargetAddress already set");
  114. this->TargetAddress = TargetAddress;
  115. }
  116. /// Return the target address for this region.
  117. JITTargetAddress getTargetAddress() const { return TargetAddress; }
  118. private:
  119. const char *ContentPtr = nullptr;
  120. uint64_t Size = 0;
  121. JITTargetAddress TargetAddress = 0;
  122. };
  123. using IsSymbolValidFunction = std::function<bool(StringRef Symbol)>;
  124. using GetSymbolInfoFunction =
  125. std::function<Expected<MemoryRegionInfo>(StringRef SymbolName)>;
  126. using GetSectionInfoFunction = std::function<Expected<MemoryRegionInfo>(
  127. StringRef FileName, StringRef SectionName)>;
  128. using GetStubInfoFunction = std::function<Expected<MemoryRegionInfo>(
  129. StringRef StubContainer, StringRef TargetName)>;
  130. using GetGOTInfoFunction = std::function<Expected<MemoryRegionInfo>(
  131. StringRef GOTContainer, StringRef TargetName)>;
  132. RuntimeDyldChecker(IsSymbolValidFunction IsSymbolValid,
  133. GetSymbolInfoFunction GetSymbolInfo,
  134. GetSectionInfoFunction GetSectionInfo,
  135. GetStubInfoFunction GetStubInfo,
  136. GetGOTInfoFunction GetGOTInfo,
  137. support::endianness Endianness,
  138. MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
  139. raw_ostream &ErrStream);
  140. ~RuntimeDyldChecker();
  141. /// Check a single expression against the attached RuntimeDyld
  142. /// instance.
  143. bool check(StringRef CheckExpr) const;
  144. /// Scan the given memory buffer for lines beginning with the string
  145. /// in RulePrefix. The remainder of the line is passed to the check
  146. /// method to be evaluated as an expression.
  147. bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
  148. /// Returns the address of the requested section (or an error message
  149. /// in the second element of the pair if the address cannot be found).
  150. ///
  151. /// if 'LocalAddress' is true, this returns the address of the section
  152. /// within the linker's memory. If 'LocalAddress' is false it returns the
  153. /// address within the target process (i.e. the load address).
  154. std::pair<uint64_t, std::string> getSectionAddr(StringRef FileName,
  155. StringRef SectionName,
  156. bool LocalAddress);
  157. /// If there is a section at the given local address, return its load
  158. /// address, otherwise return none.
  159. Optional<uint64_t> getSectionLoadAddress(void *LocalAddress) const;
  160. private:
  161. std::unique_ptr<RuntimeDyldCheckerImpl> Impl;
  162. };
  163. } // end namespace llvm
  164. #endif
  165. #ifdef __GNUC__
  166. #pragma GCC diagnostic pop
  167. #endif