TPCIndirectionUtils.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. //===--- TPCIndirectionUtils.h - TPC based indirection utils ----*- 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. // Indirection utilities (stubs, trampolines, lazy call-throughs) that use the
  10. // TargetProcessControl API to interact with the target process.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_EXECUTIONENGINE_ORC_TPCINDIRECTIONUTILS_H
  14. #define LLVM_EXECUTIONENGINE_ORC_TPCINDIRECTIONUTILS_H
  15. #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
  16. #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
  17. #include "llvm/ExecutionEngine/Orc/LazyReexports.h"
  18. #include <mutex>
  19. namespace llvm {
  20. namespace orc {
  21. class TargetProcessControl;
  22. /// Provides TargetProcessControl based indirect stubs, trampoline pool and
  23. /// lazy call through manager.
  24. class TPCIndirectionUtils {
  25. friend class TPCIndirectionUtilsAccess;
  26. public:
  27. /// ABI support base class. Used to write resolver, stub, and trampoline
  28. /// blocks.
  29. class ABISupport {
  30. protected:
  31. ABISupport(unsigned PointerSize, unsigned TrampolineSize, unsigned StubSize,
  32. unsigned StubToPointerMaxDisplacement, unsigned ResolverCodeSize)
  33. : PointerSize(PointerSize), TrampolineSize(TrampolineSize),
  34. StubSize(StubSize),
  35. StubToPointerMaxDisplacement(StubToPointerMaxDisplacement),
  36. ResolverCodeSize(ResolverCodeSize) {}
  37. public:
  38. virtual ~ABISupport();
  39. unsigned getPointerSize() const { return PointerSize; }
  40. unsigned getTrampolineSize() const { return TrampolineSize; }
  41. unsigned getStubSize() const { return StubSize; }
  42. unsigned getStubToPointerMaxDisplacement() const {
  43. return StubToPointerMaxDisplacement;
  44. }
  45. unsigned getResolverCodeSize() const { return ResolverCodeSize; }
  46. virtual void writeResolverCode(char *ResolverWorkingMem,
  47. JITTargetAddress ResolverTargetAddr,
  48. JITTargetAddress ReentryFnAddr,
  49. JITTargetAddress ReentryCtxAddr) const = 0;
  50. virtual void writeTrampolines(char *TrampolineBlockWorkingMem,
  51. JITTargetAddress TrampolineBlockTragetAddr,
  52. JITTargetAddress ResolverAddr,
  53. unsigned NumTrampolines) const = 0;
  54. virtual void
  55. writeIndirectStubsBlock(char *StubsBlockWorkingMem,
  56. JITTargetAddress StubsBlockTargetAddress,
  57. JITTargetAddress PointersBlockTargetAddress,
  58. unsigned NumStubs) const = 0;
  59. private:
  60. unsigned PointerSize = 0;
  61. unsigned TrampolineSize = 0;
  62. unsigned StubSize = 0;
  63. unsigned StubToPointerMaxDisplacement = 0;
  64. unsigned ResolverCodeSize = 0;
  65. };
  66. /// Create using the given ABI class.
  67. template <typename ORCABI>
  68. static std::unique_ptr<TPCIndirectionUtils>
  69. CreateWithABI(TargetProcessControl &TPC);
  70. /// Create based on the TargetProcessControl triple.
  71. static Expected<std::unique_ptr<TPCIndirectionUtils>>
  72. Create(TargetProcessControl &TPC);
  73. /// Return a reference to the TargetProcessControl object.
  74. TargetProcessControl &getTargetProcessControl() const { return TPC; }
  75. /// Return a reference to the ABISupport object for this instance.
  76. ABISupport &getABISupport() const { return *ABI; }
  77. /// Release memory for resources held by this instance. This *must* be called
  78. /// prior to destruction of the class.
  79. Error cleanup();
  80. /// Write resolver code to the target process and return its address.
  81. /// This must be called before any call to createTrampolinePool or
  82. /// createLazyCallThroughManager.
  83. Expected<JITTargetAddress>
  84. writeResolverBlock(JITTargetAddress ReentryFnAddr,
  85. JITTargetAddress ReentryCtxAddr);
  86. /// Returns the address of the Resolver block. Returns zero if the
  87. /// writeResolverBlock method has not previously been called.
  88. JITTargetAddress getResolverBlockAddress() const { return ResolverBlockAddr; }
  89. /// Create an IndirectStubsManager for the target process.
  90. std::unique_ptr<IndirectStubsManager> createIndirectStubsManager();
  91. /// Create a TrampolinePool for the target process.
  92. TrampolinePool &getTrampolinePool();
  93. /// Create a LazyCallThroughManager.
  94. /// This function should only be called once.
  95. LazyCallThroughManager &
  96. createLazyCallThroughManager(ExecutionSession &ES,
  97. JITTargetAddress ErrorHandlerAddr);
  98. /// Create a LazyCallThroughManager for the target process.
  99. LazyCallThroughManager &getLazyCallThroughManager() {
  100. assert(LCTM && "createLazyCallThroughManager must be called first");
  101. return *LCTM;
  102. }
  103. private:
  104. using Allocation = jitlink::JITLinkMemoryManager::Allocation;
  105. struct IndirectStubInfo {
  106. IndirectStubInfo() = default;
  107. IndirectStubInfo(JITTargetAddress StubAddress,
  108. JITTargetAddress PointerAddress)
  109. : StubAddress(StubAddress), PointerAddress(PointerAddress) {}
  110. JITTargetAddress StubAddress = 0;
  111. JITTargetAddress PointerAddress = 0;
  112. };
  113. using IndirectStubInfoVector = std::vector<IndirectStubInfo>;
  114. /// Create a TPCIndirectionUtils instance.
  115. TPCIndirectionUtils(TargetProcessControl &TPC,
  116. std::unique_ptr<ABISupport> ABI);
  117. Expected<IndirectStubInfoVector> getIndirectStubs(unsigned NumStubs);
  118. std::mutex TPCUIMutex;
  119. TargetProcessControl &TPC;
  120. std::unique_ptr<ABISupport> ABI;
  121. JITTargetAddress ResolverBlockAddr;
  122. std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation> ResolverBlock;
  123. std::unique_ptr<TrampolinePool> TP;
  124. std::unique_ptr<LazyCallThroughManager> LCTM;
  125. std::vector<IndirectStubInfo> AvailableIndirectStubs;
  126. std::vector<std::unique_ptr<Allocation>> IndirectStubAllocs;
  127. };
  128. /// This will call writeResolver on the given TPCIndirectionUtils instance
  129. /// to set up re-entry via a function that will directly return the trampoline
  130. /// landing address.
  131. ///
  132. /// The TPCIndirectionUtils' LazyCallThroughManager must have been previously
  133. /// created via TPCIndirectionUtils::createLazyCallThroughManager.
  134. ///
  135. /// The TPCIndirectionUtils' writeResolver method must not have been previously
  136. /// called.
  137. ///
  138. /// This function is experimental and likely subject to revision.
  139. Error setUpInProcessLCTMReentryViaTPCIU(TPCIndirectionUtils &TPCIU);
  140. namespace detail {
  141. template <typename ORCABI>
  142. class ABISupportImpl : public TPCIndirectionUtils::ABISupport {
  143. public:
  144. ABISupportImpl()
  145. : ABISupport(ORCABI::PointerSize, ORCABI::TrampolineSize,
  146. ORCABI::StubSize, ORCABI::StubToPointerMaxDisplacement,
  147. ORCABI::ResolverCodeSize) {}
  148. void writeResolverCode(char *ResolverWorkingMem,
  149. JITTargetAddress ResolverTargetAddr,
  150. JITTargetAddress ReentryFnAddr,
  151. JITTargetAddress ReentryCtxAddr) const override {
  152. ORCABI::writeResolverCode(ResolverWorkingMem, ResolverTargetAddr,
  153. ReentryFnAddr, ReentryCtxAddr);
  154. }
  155. void writeTrampolines(char *TrampolineBlockWorkingMem,
  156. JITTargetAddress TrampolineBlockTargetAddr,
  157. JITTargetAddress ResolverAddr,
  158. unsigned NumTrampolines) const override {
  159. ORCABI::writeTrampolines(TrampolineBlockWorkingMem,
  160. TrampolineBlockTargetAddr, ResolverAddr,
  161. NumTrampolines);
  162. }
  163. void writeIndirectStubsBlock(char *StubsBlockWorkingMem,
  164. JITTargetAddress StubsBlockTargetAddress,
  165. JITTargetAddress PointersBlockTargetAddress,
  166. unsigned NumStubs) const override {
  167. ORCABI::writeIndirectStubsBlock(StubsBlockWorkingMem,
  168. StubsBlockTargetAddress,
  169. PointersBlockTargetAddress, NumStubs);
  170. }
  171. };
  172. } // end namespace detail
  173. template <typename ORCABI>
  174. std::unique_ptr<TPCIndirectionUtils>
  175. TPCIndirectionUtils::CreateWithABI(TargetProcessControl &TPC) {
  176. return std::unique_ptr<TPCIndirectionUtils>(new TPCIndirectionUtils(
  177. TPC, std::make_unique<detail::ABISupportImpl<ORCABI>>()));
  178. }
  179. } // end namespace orc
  180. } // end namespace llvm
  181. #endif // LLVM_EXECUTIONENGINE_ORC_TPCINDIRECTIONUTILS_H