Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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
  185.