Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:55

0001 //===---- RuntimeDyldChecker.h - RuntimeDyld tester framework -----*- C++ -*-=//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
0010 #define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
0011 
0012 #include "llvm/ExecutionEngine/JITSymbol.h"
0013 #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
0014 #include "llvm/Support/Endian.h"
0015 #include "llvm/TargetParser/SubtargetFeature.h"
0016 #include "llvm/TargetParser/Triple.h"
0017 #include <optional>
0018 
0019 #include <cstdint>
0020 #include <memory>
0021 #include <string>
0022 #include <utility>
0023 
0024 namespace llvm {
0025 
0026 class StringRef;
0027 class MCDisassembler;
0028 class MemoryBuffer;
0029 class MCInstPrinter;
0030 class RuntimeDyld;
0031 class RuntimeDyldCheckerImpl;
0032 class raw_ostream;
0033 
0034 /// Holds target-specific properties for a symbol.
0035 using TargetFlagsType = uint8_t;
0036 
0037 /// RuntimeDyld invariant checker for verifying that RuntimeDyld has
0038 ///        correctly applied relocations.
0039 ///
0040 /// The RuntimeDyldChecker class evaluates expressions against an attached
0041 /// RuntimeDyld instance to verify that relocations have been applied
0042 /// correctly.
0043 ///
0044 /// The expression language supports basic pointer arithmetic and bit-masking,
0045 /// and has limited disassembler integration for accessing instruction
0046 /// operands and the next PC (program counter) address for each instruction.
0047 ///
0048 /// The language syntax is:
0049 ///
0050 /// check = expr '=' expr
0051 ///
0052 /// expr = binary_expr
0053 ///      | sliceable_expr
0054 ///
0055 /// sliceable_expr = '*{' number '}' load_addr_expr [slice]
0056 ///                | '(' expr ')' [slice]
0057 ///                | ident_expr [slice]
0058 ///                | number [slice]
0059 ///
0060 /// slice = '[' high-bit-index ':' low-bit-index ']'
0061 ///
0062 /// load_addr_expr = symbol
0063 ///                | '(' symbol '+' number ')'
0064 ///                | '(' symbol '-' number ')'
0065 ///
0066 /// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')'
0067 ///            | 'next_pc'        '(' symbol ')'
0068 ///            | 'stub_addr' '(' stub-container-name ',' symbol ')'
0069 ///            | 'got_addr' '(' stub-container-name ',' symbol ')'
0070 ///            | 'section_addr' '(' stub-container-name ',' symbol ')'
0071 ///            | symbol
0072 ///
0073 /// binary_expr = expr '+' expr
0074 ///             | expr '-' expr
0075 ///             | expr '&' expr
0076 ///             | expr '|' expr
0077 ///             | expr '<<' expr
0078 ///             | expr '>>' expr
0079 ///
0080 class RuntimeDyldChecker {
0081 public:
0082   class MemoryRegionInfo {
0083   public:
0084     MemoryRegionInfo() = default;
0085 
0086     /// Constructor for symbols/sections with content and TargetFlag.
0087     MemoryRegionInfo(ArrayRef<char> Content, JITTargetAddress TargetAddress,
0088                      TargetFlagsType TargetFlags)
0089         : ContentPtr(Content.data()), Size(Content.size()),
0090           TargetAddress(TargetAddress), TargetFlags(TargetFlags) {}
0091 
0092     /// Constructor for zero-fill symbols/sections.
0093     MemoryRegionInfo(uint64_t Size, JITTargetAddress TargetAddress)
0094         : Size(Size), TargetAddress(TargetAddress) {}
0095 
0096     /// Returns true if this is a zero-fill symbol/section.
0097     bool isZeroFill() const {
0098       assert(Size && "setContent/setZeroFill must be called first");
0099       return !ContentPtr;
0100     }
0101 
0102     /// Set the content for this memory region.
0103     void setContent(ArrayRef<char> Content) {
0104       assert(!ContentPtr && !Size && "Content/zero-fill already set");
0105       ContentPtr = Content.data();
0106       Size = Content.size();
0107     }
0108 
0109     /// Set a zero-fill length for this memory region.
0110     void setZeroFill(uint64_t Size) {
0111       assert(!ContentPtr && !this->Size && "Content/zero-fill already set");
0112       this->Size = Size;
0113     }
0114 
0115     /// Returns the content for this section if there is any.
0116     ArrayRef<char> getContent() const {
0117       assert(!isZeroFill() && "Can't get content for a zero-fill section");
0118       return {ContentPtr, static_cast<size_t>(Size)};
0119     }
0120 
0121     /// Returns the zero-fill length for this section.
0122     uint64_t getZeroFillLength() const {
0123       assert(isZeroFill() && "Can't get zero-fill length for content section");
0124       return Size;
0125     }
0126 
0127     /// Set the target address for this region.
0128     void setTargetAddress(JITTargetAddress TargetAddress) {
0129       assert(!this->TargetAddress && "TargetAddress already set");
0130       this->TargetAddress = TargetAddress;
0131     }
0132 
0133     /// Return the target address for this region.
0134     JITTargetAddress getTargetAddress() const { return TargetAddress; }
0135 
0136     /// Get the target flags for this Symbol.
0137     TargetFlagsType getTargetFlags() const { return TargetFlags; }
0138 
0139     /// Set the target flags for this Symbol.
0140     void setTargetFlags(TargetFlagsType Flags) {
0141       assert(Flags <= 1 && "Add more bits to store more than one flag");
0142       TargetFlags = Flags;
0143     }
0144 
0145   private:
0146     const char *ContentPtr = nullptr;
0147     uint64_t Size = 0;
0148     JITTargetAddress TargetAddress = 0;
0149     TargetFlagsType TargetFlags = 0;
0150   };
0151 
0152   using IsSymbolValidFunction = std::function<bool(StringRef Symbol)>;
0153   using GetSymbolInfoFunction =
0154       std::function<Expected<MemoryRegionInfo>(StringRef SymbolName)>;
0155   using GetSectionInfoFunction = std::function<Expected<MemoryRegionInfo>(
0156       StringRef FileName, StringRef SectionName)>;
0157   using GetStubInfoFunction = std::function<Expected<MemoryRegionInfo>(
0158       StringRef StubContainer, StringRef TargetName, StringRef StubKindFilter)>;
0159   using GetGOTInfoFunction = std::function<Expected<MemoryRegionInfo>(
0160       StringRef GOTContainer, StringRef TargetName)>;
0161 
0162   RuntimeDyldChecker(IsSymbolValidFunction IsSymbolValid,
0163                      GetSymbolInfoFunction GetSymbolInfo,
0164                      GetSectionInfoFunction GetSectionInfo,
0165                      GetStubInfoFunction GetStubInfo,
0166                      GetGOTInfoFunction GetGOTInfo, llvm::endianness Endianness,
0167                      Triple TT, StringRef CPU, SubtargetFeatures TF,
0168                      raw_ostream &ErrStream);
0169   ~RuntimeDyldChecker();
0170 
0171   /// Check a single expression against the attached RuntimeDyld
0172   ///        instance.
0173   bool check(StringRef CheckExpr) const;
0174 
0175   /// Scan the given memory buffer for lines beginning with the string
0176   ///        in RulePrefix. The remainder of the line is passed to the check
0177   ///        method to be evaluated as an expression.
0178   bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
0179 
0180   /// Returns the address of the requested section (or an error message
0181   ///        in the second element of the pair if the address cannot be found).
0182   ///
0183   /// if 'LocalAddress' is true, this returns the address of the section
0184   /// within the linker's memory. If 'LocalAddress' is false it returns the
0185   /// address within the target process (i.e. the load address).
0186   std::pair<uint64_t, std::string> getSectionAddr(StringRef FileName,
0187                                                   StringRef SectionName,
0188                                                   bool LocalAddress);
0189 
0190   /// If there is a section at the given local address, return its load
0191   /// address, otherwise return std::nullopt.
0192   std::optional<uint64_t> getSectionLoadAddress(void *LocalAddress) const;
0193 
0194 private:
0195   std::unique_ptr<RuntimeDyldCheckerImpl> Impl;
0196 };
0197 
0198 } // end namespace llvm
0199 
0200 #endif